summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Braun <d_braun@kabelmail.de>2022-06-13 22:45:45 +0200
committerDennis Braun <d_braun@kabelmail.de>2022-06-13 22:45:45 +0200
commited972b70dcba4055781085ac5599730321b4ccdd (patch)
treee4c61b228ac66b83e30577e41d5b04f9bfae72e4
parent6be2fd4da5ca72688c5363886c6d0842c9edb54e (diff)
New upstream version 0.22.0
-rw-r--r--CMakeLists.txt28
-rw-r--r--ChangeLog22
-rw-r--r--extras/com.giadamusic.Giada.desktop10
-rw-r--r--src/core/channels/channel.cpp30
-rw-r--r--src/core/channels/channel.h34
-rw-r--r--src/core/channels/channelShared.cpp35
-rw-r--r--src/core/channels/channelShared.h77
-rw-r--r--src/core/channels/midiController.cpp28
-rw-r--r--src/core/channels/midiController.h10
-rw-r--r--src/core/channels/midiReceiver.cpp37
-rw-r--r--src/core/channels/midiReceiver.h13
-rw-r--r--src/core/channels/midiSender.cpp15
-rw-r--r--src/core/channels/midiSender.h7
-rw-r--r--src/core/channels/sampleReactor.cpp25
-rw-r--r--src/core/channels/sampleReactor.h10
-rw-r--r--src/core/conf.cpp30
-rw-r--r--src/core/conf.h52
-rw-r--r--src/core/const.h30
-rw-r--r--src/core/engine.cpp8
-rw-r--r--src/core/engine.h4
-rw-r--r--src/core/eventDispatcher.cpp4
-rw-r--r--src/core/eventDispatcher.h2
-rw-r--r--src/core/init.cpp6
-rw-r--r--src/core/kernelMidi.cpp41
-rw-r--r--src/core/kernelMidi.h2
-rw-r--r--src/core/midiDispatcher.cpp2
-rw-r--r--src/core/midiMapper.cpp52
-rw-r--r--src/core/midiMapper.h23
-rw-r--r--src/core/patch.cpp14
-rw-r--r--src/core/plugins/pluginManager.cpp2
-rw-r--r--src/core/waveManager.cpp4
-rw-r--r--src/glue/channel.cpp19
-rw-r--r--src/glue/config.cpp9
-rw-r--r--src/glue/config.h9
-rw-r--r--src/glue/io.cpp4
-rw-r--r--src/glue/layout.cpp14
-rw-r--r--src/glue/main.cpp9
-rw-r--r--src/glue/recorder.cpp9
-rw-r--r--src/glue/sampleEditor.cpp3
-rw-r--r--src/glue/storage.cpp43
-rw-r--r--src/gui/dialogs/about.cpp101
-rw-r--r--src/gui/dialogs/about.h14
-rw-r--r--src/gui/dialogs/actionEditor/baseActionEditor.cpp16
-rw-r--r--src/gui/dialogs/actionEditor/sampleActionEditor.cpp15
-rw-r--r--src/gui/dialogs/beatsInput.cpp48
-rw-r--r--src/gui/dialogs/beatsInput.h4
-rw-r--r--src/gui/dialogs/bpmInput.cpp62
-rw-r--r--src/gui/dialogs/bpmInput.h9
-rw-r--r--src/gui/dialogs/browser/browserBase.cpp9
-rw-r--r--src/gui/dialogs/browser/browserDir.cpp7
-rw-r--r--src/gui/dialogs/browser/browserLoad.cpp7
-rw-r--r--src/gui/dialogs/browser/browserSave.cpp7
-rw-r--r--src/gui/dialogs/channelNameInput.cpp70
-rw-r--r--src/gui/dialogs/channelNameInput.h5
-rw-r--r--src/gui/dialogs/config.cpp9
-rw-r--r--src/gui/dialogs/keyGrabber.cpp11
-rw-r--r--src/gui/dialogs/mainWindow.cpp78
-rw-r--r--src/gui/dialogs/midiIO/midiInputChannel.cpp51
-rw-r--r--src/gui/dialogs/midiIO/midiInputMaster.cpp30
-rw-r--r--src/gui/dialogs/midiIO/midiOutputBase.cpp28
-rw-r--r--src/gui/dialogs/midiIO/midiOutputBase.h5
-rw-r--r--src/gui/dialogs/midiIO/midiOutputMidiCh.cpp13
-rw-r--r--src/gui/dialogs/midiIO/midiOutputSampleCh.cpp18
-rw-r--r--src/gui/dialogs/missingAssets.cpp13
-rw-r--r--src/gui/dialogs/pluginChooser.cpp68
-rw-r--r--src/gui/dialogs/pluginList.cpp14
-rw-r--r--src/gui/dialogs/sampleEditor.cpp39
-rw-r--r--src/gui/dialogs/warnings.cpp11
-rw-r--r--src/gui/elems/actionEditor/gridTool.cpp7
-rw-r--r--src/gui/elems/actionEditor/sampleActionEditor.cpp9
-rw-r--r--src/gui/elems/actionEditor/velocityEditor.cpp5
-rw-r--r--src/gui/elems/basics/scroll.cpp7
-rw-r--r--src/gui/elems/basics/scroll.h1
-rw-r--r--src/gui/elems/basics/statusButton.cpp9
-rw-r--r--src/gui/elems/basics/statusButton.h7
-rw-r--r--src/gui/elems/config/stringMenu.cpp48
-rw-r--r--src/gui/elems/config/stringMenu.h (renamed from src/gui/elems/sampleEditor/boostTool.h)33
-rw-r--r--src/gui/elems/config/tabAudio.cpp43
-rw-r--r--src/gui/elems/config/tabBehaviors.cpp13
-rw-r--r--src/gui/elems/config/tabBindings.cpp15
-rw-r--r--src/gui/elems/config/tabMidi.cpp47
-rw-r--r--src/gui/elems/config/tabMidi.h22
-rw-r--r--src/gui/elems/config/tabMisc.cpp30
-rw-r--r--src/gui/elems/config/tabMisc.h6
-rw-r--r--src/gui/elems/config/tabPlugins.cpp12
-rw-r--r--src/gui/elems/fileBrowser.cpp37
-rw-r--r--src/gui/elems/fileBrowser.h14
-rw-r--r--src/gui/elems/keyBinder.cpp7
-rw-r--r--src/gui/elems/mainWindow/keyboard/column.cpp66
-rw-r--r--src/gui/elems/mainWindow/keyboard/keyboard.cpp4
-rw-r--r--src/gui/elems/mainWindow/keyboard/keyboard.h2
-rw-r--r--src/gui/elems/mainWindow/keyboard/midiActivity.cpp6
-rw-r--r--src/gui/elems/mainWindow/keyboard/midiChannel.cpp33
-rw-r--r--src/gui/elems/mainWindow/keyboard/sampleChannel.cpp56
-rw-r--r--src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp7
-rw-r--r--src/gui/elems/mainWindow/mainIO.cpp25
-rw-r--r--src/gui/elems/mainWindow/mainIO.h2
-rw-r--r--src/gui/elems/mainWindow/mainMenu.cpp157
-rw-r--r--src/gui/elems/mainWindow/mainMenu.h6
-rw-r--r--src/gui/elems/mainWindow/mainTimer.cpp44
-rw-r--r--src/gui/elems/mainWindow/mainTimer.h6
-rw-r--r--src/gui/elems/mainWindow/mainTransport.cpp93
-rw-r--r--src/gui/elems/mainWindow/mainTransport.h27
-rw-r--r--src/gui/elems/mainWindow/sequencer.cpp9
-rw-r--r--src/gui/elems/mainWindow/sequencer.h6
-rw-r--r--src/gui/elems/midiIO/midiLearner.cpp7
-rw-r--r--src/gui/elems/midiIO/midiLearnerPack.cpp7
-rw-r--r--src/gui/elems/midiIO/midiLearnerPack.h9
-rw-r--r--src/gui/elems/plugin/pluginBrowser.cpp39
-rw-r--r--src/gui/elems/plugin/pluginElement.cpp6
-rw-r--r--src/gui/elems/sampleEditor/boostTool.cpp107
-rw-r--r--src/gui/elems/sampleEditor/panTool.cpp14
-rw-r--r--src/gui/elems/sampleEditor/pitchTool.cpp11
-rw-r--r--src/gui/elems/sampleEditor/rangeTool.cpp15
-rw-r--r--src/gui/elems/sampleEditor/shiftTool.cpp14
-rw-r--r--src/gui/elems/sampleEditor/volumeTool.cpp12
-rw-r--r--src/gui/elems/sampleEditor/waveTools.cpp35
-rw-r--r--src/gui/langMapper.cpp388
-rw-r--r--src/gui/langMapper.h375
-rw-r--r--src/gui/ui.cpp3
-rw-r--r--src/gui/ui.h2
-rw-r--r--src/mapper.cpp73
-rw-r--r--src/mapper.h69
-rw-r--r--src/utils/fs.cpp22
-rw-r--r--src/utils/fs.h7
-rw-r--r--src/utils/log.cpp2
-rw-r--r--vcpkg.json34
127 files changed, 2398 insertions, 1312 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ec69d1..e66f0f1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,6 +33,7 @@ project(giada LANGUAGES CXX)
list(APPEND SOURCES
src/main.cpp
+ src/mapper.cpp
src/core/engine.cpp
src/core/worker.cpp
src/core/eventDispatcher.cpp
@@ -77,6 +78,7 @@ list(APPEND SOURCES
src/core/channels/midiSender.cpp
src/core/channels/midiReceiver.cpp
src/core/channels/channel.cpp
+ src/core/channels/channelShared.cpp
src/core/channels/channelManager.cpp
src/core/model/sequencer.cpp
src/core/model/mixer.cpp
@@ -99,6 +101,7 @@ list(APPEND SOURCES
src/gui/dialogs/window.cpp
src/gui/dispatcher.cpp
src/gui/updater.cpp
+ src/gui/langMapper.cpp
src/gui/drawing.cpp
src/gui/dialogs/progress.cpp
src/gui/dialogs/keyGrabber.cpp
@@ -139,7 +142,6 @@ list(APPEND SOURCES
src/gui/elems/sampleEditor/waveform.cpp
src/gui/elems/sampleEditor/waveTools.cpp
src/gui/elems/sampleEditor/volumeTool.cpp
- src/gui/elems/sampleEditor/boostTool.cpp
src/gui/elems/sampleEditor/panTool.cpp
src/gui/elems/sampleEditor/pitchTool.cpp
src/gui/elems/sampleEditor/rangeTool.cpp
@@ -177,6 +179,7 @@ list(APPEND SOURCES
src/gui/elems/config/tabBehaviors.cpp
src/gui/elems/config/tabPlugins.cpp
src/gui/elems/config/tabBindings.cpp
+ src/gui/elems/config/stringMenu.cpp
src/gui/elems/basics/scroll.cpp
src/gui/elems/basics/pack.cpp
src/gui/elems/basics/group.cpp
@@ -303,14 +306,15 @@ if (NOT RtMidi_FOUND)
message(FATAL_ERROR "Can't find RtMidi, aborting.")
endif()
- # RtMidi header path may vary across OSes, so a fix is needed.
- # TODO - Find a way to avoid this additional step
-
- find_path(LIBRARY_RTMIDI_INCLUDE_DIR RtMidi.h PATH_SUFFIXES rtmidi)
- list(APPEND INCLUDE_DIRS ${LIBRARY_RTMIDI_INCLUDE_DIR})
message("RtMidi library found in " ${RtMidi_DIR})
endif()
+# RtMidi header path may vary across OSes, so a fix is needed.
+# TODO - Find a way to avoid this additional step
+
+find_path(LIBRARY_RTMIDI_INCLUDE_DIR RtMidi.h PATH_SUFFIXES rtmidi)
+list(APPEND INCLUDE_DIRS ${LIBRARY_RTMIDI_INCLUDE_DIR})
+
# FLTK
set(FLTK_SKIP_FLUID TRUE) # Don't search for FLTK's fluid
@@ -386,6 +390,18 @@ else()
message("Libsamplerate library found in " ${LIBRARY_SAMPLERATE})
endif()
+# fmt
+
+find_package(fmt REQUIRED)
+list(APPEND LIBRARIES fmt::fmt)
+
+# nlohmann_json (embedded as git submodule)
+
+set(JSON_Install OFF CACHE INTERNAL "") # No need to install it
+set(JSON_BuildTests OFF CACHE INTERNAL "") # Don't build tests
+add_subdirectory(src/deps/json)
+list(APPEND LIBRARIES nlohmann_json::nlohmann_json)
+
# Catch (if tests enabled)
if (WITH_TESTS)
diff --git a/ChangeLog b/ChangeLog
index 77bd592..f36ee3a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,28 @@
--------------------------------------------------------------------------------
+0.22.0 --- 2022 . 06 . 13
+- Multi-language support via langmaps (#34)
+- Add new 'fmt' dependency
+- Add vcpkg.json manifest file
+- Log compiled RtMidi APIs on startup
+- Fix missing header with RtMidi 5.0.0
+- Fix Stream Linker button not working (#585)
+- Minor code refactoring and cleanups
+
+
+0.21.0 --- 2022 . 04 . 01
+- Custom keyboard mappings for global actions (#213)
+- Pressing 'Esc' key no longer closes windows
+- Resizable Configuration window
+- Shut down the main UI nicely when closing a project or loading a new one
+- Prevent crashes when loading a new project by cleaning up the data model
+- Fix wrong plug-in processing where the local plug-in buffer was incorrectly
+ deleted in case of instruments (#563)
+- Lots of UI code modernizations and cleanups
+- [Windows] Fix several assertions and MSVC warnings
+
+
0.20.1 --- 2022 . 02 . 21
- New MIDI I/O activity LEDs on channels (#143)
- New "Missing Assets" alert window (#344)
diff --git a/extras/com.giadamusic.Giada.desktop b/extras/com.giadamusic.Giada.desktop
index b9d33b5..3c81580 100644
--- a/extras/com.giadamusic.Giada.desktop
+++ b/extras/com.giadamusic.Giada.desktop
@@ -2,11 +2,17 @@
Version=1.0
Type=Application
Name=Giada
-Name[es]=Giada
GenericName=Drum machine and loop sequencer
+Comment=Drum machine and loop sequencer
+GenericName[de]=Drum Maschine und Loop Sequenzer
GenericName[es]=Caja de ritmos y secuenciador de loops
+GenericName[fr]=Boîte à rythme et séquenceur de boucle
+Comment=Drum machine and loop sequencer
+Comment[de]=Drum Maschine und Loop Sequenzer
+Comment[es]=Caja de ritmos y secuenciador de loops
+Comment[fr]=Boîte à rythme et séquenceur de boucle
Exec=giada %f
Terminal=false
Icon=com.giadamusic.Giada
Categories=Music;AudioVideo;Audio;Midi;X-Digital_Processing;X-Jack;X-MIDI;
-Keywords=Giada;
+Keywords=midi;jackd;alsa;pulse;audio;sound;loop;
diff --git a/src/core/channels/channel.cpp b/src/core/channels/channel.cpp
index 7cf7081..ff92e4d 100644
--- a/src/core/channels/channel.cpp
+++ b/src/core/channels/channel.cpp
@@ -60,13 +60,6 @@ mcl::AudioBuffer::Pan calcPanning_(float pan)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-ChannelShared::ChannelShared(Frame bufferSize)
-: audioBuffer(bufferSize, G_MAX_IO_CHANS)
-{
-}
-
-/* -------------------------------------------------------------------------- */
-
Channel::Channel(ChannelType type, ID id, ID columnId, ChannelShared& s)
: shared(&s)
, id(id)
@@ -324,14 +317,14 @@ void Channel::advance(const Sequencer::EventBuffer& events, Range<Frame> block,
for (const Sequencer::Event& e : events)
{
if (midiController)
- midiController->advance(*this, e);
+ midiController->advance(shared->playStatus, e);
if (samplePlayer)
sampleAdvancer->advance(*this, e);
- if (midiSender)
- midiSender->advance(*this, e);
+ if (midiSender && isPlaying() && !isMuted())
+ midiSender->advance(id, e);
#ifdef WITH_VST
- if (midiReceiver)
- midiReceiver->advance(*this, e);
+ if (midiReceiver && isPlaying())
+ midiReceiver->advance(id, shared->midiQueue, e);
#endif
}
}
@@ -347,9 +340,9 @@ void Channel::react(const EventDispatcher::EventBuffer& events)
react(e);
if (midiController)
- midiController->react(*this, e);
- if (midiSender)
- midiSender->react(*this, e);
+ midiController->react(shared->playStatus, e);
+ if (midiSender && isPlaying() && !isMuted())
+ midiSender->react(e);
if (samplePlayer)
samplePlayer->react(e);
if (midiActionRecorder)
@@ -358,10 +351,11 @@ void Channel::react(const EventDispatcher::EventBuffer& events)
sampleActionRecorder->react(*this, e, g_engine.conf.data.treatRecsAsLoops,
g_engine.sequencer.isRunning(), g_engine.recorder.canRecordActions());
if (sampleReactor)
- sampleReactor->react(*this, e, g_engine.sequencer, g_engine.conf.data);
+ sampleReactor->react(*this, e, g_engine.conf.data.chansStopOnSeqHalt,
+ g_engine.sequencer.canQuantize());
#ifdef WITH_VST
if (midiReceiver)
- midiReceiver->react(*this, e);
+ midiReceiver->react(shared->midiQueue, e);
#endif
}
}
@@ -457,7 +451,7 @@ void Channel::renderChannel(mcl::AudioBuffer& out, mcl::AudioBuffer& in, bool au
#ifdef WITH_VST
if (midiReceiver)
- midiReceiver->render(*this, g_engine.pluginHost);
+ midiReceiver->render(*shared, plugins, g_engine.pluginHost);
else if (plugins.size() > 0)
g_engine.pluginHost.processStack(shared->audioBuffer, plugins, nullptr);
#endif
diff --git a/src/core/channels/channel.h b/src/core/channels/channel.h
index 020ba9e..4926c1f 100644
--- a/src/core/channels/channel.h
+++ b/src/core/channels/channel.h
@@ -32,6 +32,7 @@
#include "deps/juce-config.h"
#endif
#include "core/channels/audioReceiver.h"
+#include "core/channels/channelShared.h"
#include "core/channels/midiActionRecorder.h"
#include "core/channels/midiController.h"
#include "core/channels/midiLearner.h"
@@ -57,39 +58,6 @@
namespace giada::m
{
class Plugin;
-
-struct ChannelShared final
-{
- ChannelShared(Frame bufferSize);
-
- mcl::AudioBuffer audioBuffer;
-#ifdef WITH_VST
- juce::MidiBuffer midiBuffer;
- Queue<MidiEvent, 32> midiQueue;
-#endif
-
- WeakAtomic<Frame> tracker = 0;
- WeakAtomic<ChannelStatus> playStatus = ChannelStatus::OFF;
- WeakAtomic<ChannelStatus> recStatus = ChannelStatus::OFF;
- WeakAtomic<bool> readActions = false;
-
- std::optional<Quantizer> quantizer;
-
- /* Optional render queue for sample-based channels. Used by SampleReactor
- and SampleAdvancer to instruct SamplePlayer how to render audio. */
-
- std::optional<Queue<SamplePlayer::Render, 2>> renderQueue = {};
-
- /* Optional resampler for sample-based channels. Unfortunately a Resampler
- object (based on libsamplerate) doesn't like to get copied while rendering
- audio, so can't live inside WaveReader object (which is copied on model
- changes by the Swapper mechanism). Let's put it in the shared state here. */
-
- std::optional<Resampler> resampler = {};
-};
-
-/* -------------------------------------------------------------------------- */
-
class Channel final
{
public:
diff --git a/src/core/channels/channelShared.cpp b/src/core/channels/channelShared.cpp
new file mode 100644
index 0000000..afbf1da
--- /dev/null
+++ b/src/core/channels/channelShared.cpp
@@ -0,0 +1,35 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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 "core/channels/channelShared.h"
+
+namespace giada::m
+{
+ChannelShared::ChannelShared(Frame bufferSize)
+: audioBuffer(bufferSize, G_MAX_IO_CHANS)
+{
+}
+} // namespace giada::m \ No newline at end of file
diff --git a/src/core/channels/channelShared.h b/src/core/channels/channelShared.h
new file mode 100644
index 0000000..a77c54a
--- /dev/null
+++ b/src/core/channels/channelShared.h
@@ -0,0 +1,77 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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 G_CHANNELSHARED_H
+#define G_CHANNELSHARED_H
+
+#include <optional>
+#ifdef WITH_VST
+#include "deps/juce-config.h"
+#endif
+#include "core/channels/samplePlayer.h"
+#include "core/const.h"
+#include "core/midiEvent.h"
+#include "core/queue.h"
+#include "core/resampler.h"
+#include "deps/mcl-audio-buffer/src/audioBuffer.hpp"
+
+namespace giada::m
+{
+struct ChannelShared final
+{
+ using MidiQueue = Queue<MidiEvent, 32>;
+ using RenderQueue = Queue<SamplePlayer::Render, 2>;
+
+ ChannelShared(Frame bufferSize);
+
+ mcl::AudioBuffer audioBuffer;
+#ifdef WITH_VST
+ juce::MidiBuffer midiBuffer;
+ MidiQueue midiQueue;
+#endif
+
+ WeakAtomic<Frame> tracker = 0;
+ WeakAtomic<ChannelStatus> playStatus = ChannelStatus::OFF;
+ WeakAtomic<ChannelStatus> recStatus = ChannelStatus::OFF;
+ WeakAtomic<bool> readActions = false;
+
+ std::optional<Quantizer> quantizer;
+
+ /* Optional render queue for sample-based channels. Used by SampleReactor
+ and SampleAdvancer to instruct SamplePlayer how to render audio. */
+
+ std::optional<RenderQueue> renderQueue = {};
+
+ /* Optional resampler for sample-based channels. Unfortunately a Resampler
+ object (based on libsamplerate) doesn't like to get copied while rendering
+ audio, so can't live inside WaveReader object (which is copied on model
+ changes by the Swapper mechanism). Let's put it in the shared state here. */
+
+ std::optional<Resampler> resampler = {};
+};
+} // namespace giada::m
+
+#endif
diff --git a/src/core/channels/midiController.cpp b/src/core/channels/midiController.cpp
index 3ad920d..29fdb33 100644
--- a/src/core/channels/midiController.cpp
+++ b/src/core/channels/midiController.cpp
@@ -25,27 +25,26 @@
* -------------------------------------------------------------------------- */
#include "midiController.h"
-#include "core/channels/channel.h"
-#include "core/conf.h"
-#include <cassert>
namespace giada::m
{
-void MidiController::react(Channel& ch, const EventDispatcher::Event& e) const
+void MidiController::react(WeakAtomic<ChannelStatus>& a_playStatus, const EventDispatcher::Event& e) const
{
+ const ChannelStatus playStatus = a_playStatus.load();
+
switch (e.type)
{
case EventDispatcher::EventType::KEY_PRESS:
- ch.shared->playStatus.store(press(ch));
+ a_playStatus.store(press(playStatus));
break;
case EventDispatcher::EventType::KEY_KILL:
case EventDispatcher::EventType::SEQUENCER_STOP:
- ch.shared->playStatus.store(ChannelStatus::OFF);
+ a_playStatus.store(ChannelStatus::OFF);
break;
case EventDispatcher::EventType::SEQUENCER_REWIND:
- ch.shared->playStatus.store(onFirstBeat(ch));
+ a_playStatus.store(onFirstBeat(playStatus));
default:
break;
@@ -54,18 +53,17 @@ void MidiController::react(Channel& ch, const EventDispatcher::Event& e) const
/* -------------------------------------------------------------------------- */
-void MidiController::advance(const Channel& ch, const Sequencer::Event& e) const
+void MidiController::advance(WeakAtomic<ChannelStatus>& a_playStatus, const Sequencer::Event& e) const
{
- if (e.type == Sequencer::EventType::FIRST_BEAT)
- ch.shared->playStatus.store(onFirstBeat(ch));
+ if (e.type != Sequencer::EventType::FIRST_BEAT)
+ return;
+ a_playStatus.store(onFirstBeat(a_playStatus.load()));
}
/* -------------------------------------------------------------------------- */
-ChannelStatus MidiController::onFirstBeat(const Channel& ch) const
+ChannelStatus MidiController::onFirstBeat(ChannelStatus playStatus) const
{
- ChannelStatus playStatus = ch.shared->playStatus.load();
-
if (playStatus == ChannelStatus::ENDING)
playStatus = ChannelStatus::OFF;
else if (playStatus == ChannelStatus::WAIT)
@@ -76,10 +74,8 @@ ChannelStatus MidiController::onFirstBeat(const Channel& ch) const
/* -------------------------------------------------------------------------- */
-ChannelStatus MidiController::press(const Channel& ch) const
+ChannelStatus MidiController::press(ChannelStatus playStatus) const
{
- ChannelStatus playStatus = ch.shared->playStatus.load();
-
switch (playStatus)
{
case ChannelStatus::PLAY:
diff --git a/src/core/channels/midiController.h b/src/core/channels/midiController.h
index 61c701e..a975f20 100644
--- a/src/core/channels/midiController.h
+++ b/src/core/channels/midiController.h
@@ -27,20 +27,20 @@
#ifndef G_CHANNEL_MIDI_CONTROLLER_H
#define G_CHANNEL_MIDI_CONTROLLER_H
+#include "core/eventDispatcher.h"
#include "core/sequencer.h"
namespace giada::m
{
-class Channel;
class MidiController final
{
public:
- void advance(const Channel& ch, const Sequencer::Event& e) const;
- void react(Channel& ch, const EventDispatcher::Event& e) const;
+ void advance(WeakAtomic<ChannelStatus>&, const Sequencer::Event& e) const;
+ void react(WeakAtomic<ChannelStatus>&, const EventDispatcher::Event& e) const;
private:
- ChannelStatus onFirstBeat(const Channel& ch) const;
- ChannelStatus press(const Channel& ch) const;
+ ChannelStatus onFirstBeat(ChannelStatus) const;
+ ChannelStatus press(ChannelStatus) const;
};
} // namespace giada::m
diff --git a/src/core/channels/midiReceiver.cpp b/src/core/channels/midiReceiver.cpp
index 599f2ca..da7c47f 100644
--- a/src/core/channels/midiReceiver.cpp
+++ b/src/core/channels/midiReceiver.cpp
@@ -27,25 +27,23 @@
#ifdef WITH_VST
#include "midiReceiver.h"
-#include "core/channels/channel.h"
#include "core/eventDispatcher.h"
-#include "core/mixer.h"
#include "core/plugins/pluginHost.h"
namespace giada::m
{
-void MidiReceiver::react(const Channel& ch, const EventDispatcher::Event& e) const
+void MidiReceiver::react(ChannelShared::MidiQueue& midiQueue, const EventDispatcher::Event& e) const
{
switch (e.type)
{
case EventDispatcher::EventType::MIDI:
- parseMidi(ch, std::get<Action>(e.data).event);
+ parseMidi(midiQueue, std::get<Action>(e.data).event);
break;
case EventDispatcher::EventType::KEY_KILL:
case EventDispatcher::EventType::SEQUENCER_STOP:
case EventDispatcher::EventType::SEQUENCER_REWIND:
- sendToPlugins(ch, MidiEvent(G_MIDI_ALL_NOTES_OFF), 0);
+ sendToPlugins(midiQueue, MidiEvent(G_MIDI_ALL_NOTES_OFF), 0);
break;
default:
@@ -55,43 +53,44 @@ void MidiReceiver::react(const Channel& ch, const EventDispatcher::Event& e) con
/* -------------------------------------------------------------------------- */
-void MidiReceiver::advance(const Channel& ch, const Sequencer::Event& e) const
+void MidiReceiver::advance(ID channelId, ChannelShared::MidiQueue& midiQueue, const Sequencer::Event& e) const
{
- if (e.type == Sequencer::EventType::ACTIONS && ch.isPlaying())
- for (const Action& action : *e.actions)
- if (action.channelId == ch.id)
- sendToPlugins(ch, action.event, e.delta);
+ if (e.type != Sequencer::EventType::ACTIONS)
+ return;
+ for (const Action& action : *e.actions)
+ if (action.channelId == channelId)
+ sendToPlugins(midiQueue, action.event, e.delta);
}
/* -------------------------------------------------------------------------- */
-void MidiReceiver::render(const Channel& ch, PluginHost& pluginHost) const
+void MidiReceiver::render(ChannelShared& shared, const std::vector<Plugin*>& plugins, PluginHost& pluginHost) const
{
- ch.shared->midiBuffer.clear();
+ shared.midiBuffer.clear();
MidiEvent e;
- while (ch.shared->midiQueue.pop(e))
+ while (shared.midiQueue.pop(e))
{
juce::MidiMessage message = juce::MidiMessage(
e.getStatus(),
e.getNote(),
e.getVelocity());
- ch.shared->midiBuffer.addEvent(message, e.getDelta());
+ shared.midiBuffer.addEvent(message, e.getDelta());
}
- pluginHost.processStack(ch.shared->audioBuffer, ch.plugins, &ch.shared->midiBuffer);
+ pluginHost.processStack(shared.audioBuffer, plugins, &shared.midiBuffer);
}
/* -------------------------------------------------------------------------- */
-void MidiReceiver::sendToPlugins(const Channel& ch, const MidiEvent& e, Frame localFrame) const
+void MidiReceiver::sendToPlugins(ChannelShared::MidiQueue& midiQueue, const MidiEvent& e, Frame localFrame) const
{
- ch.shared->midiQueue.push(MidiEvent(e.getRaw(), localFrame));
+ midiQueue.push(MidiEvent(e.getRaw(), localFrame));
}
/* -------------------------------------------------------------------------- */
-void MidiReceiver::parseMidi(const Channel& ch, const MidiEvent& e) const
+void MidiReceiver::parseMidi(ChannelShared::MidiQueue& midiQueue, const MidiEvent& e) const
{
/* Now all messages are turned into Channel-0 messages. Giada doesn't care
about holding MIDI channel information. Moreover, having all internal
@@ -99,7 +98,7 @@ void MidiReceiver::parseMidi(const Channel& ch, const MidiEvent& e) const
MidiEvent flat(e);
flat.setChannel(0);
- sendToPlugins(ch, flat, /*delta=*/0);
+ sendToPlugins(midiQueue, flat, /*delta=*/0);
}
} // namespace giada::m
diff --git a/src/core/channels/midiReceiver.h b/src/core/channels/midiReceiver.h
index 4f8fdb5..c28fefa 100644
--- a/src/core/channels/midiReceiver.h
+++ b/src/core/channels/midiReceiver.h
@@ -29,22 +29,23 @@
#ifdef WITH_VST
+#include "core/channels/channelShared.h"
#include "core/sequencer.h"
namespace giada::m
{
class PluginHost;
-class Channel;
+class Plugin;
class MidiReceiver final
{
public:
- void react(const Channel& ch, const EventDispatcher::Event& e) const;
- void advance(const Channel& ch, const Sequencer::Event& e) const;
- void render(const Channel& ch, PluginHost& plugiHost) const;
+ void react(ChannelShared::MidiQueue&, const EventDispatcher::Event&) const;
+ void advance(ID channelId, ChannelShared::MidiQueue&, const Sequencer::Event&) const;
+ void render(ChannelShared&, const std::vector<Plugin*>&, PluginHost&) const;
private:
- void sendToPlugins(const Channel& ch, const MidiEvent& e, Frame localFrame) const;
- void parseMidi(const Channel& ch, const MidiEvent& e) const;
+ void sendToPlugins(ChannelShared::MidiQueue&, const MidiEvent&, Frame localFrame) const;
+ void parseMidi(ChannelShared::MidiQueue&, const MidiEvent&) const;
};
} // namespace giada::m
diff --git a/src/core/channels/midiSender.cpp b/src/core/channels/midiSender.cpp
index 6eee0ba..4f93a3a 100644
--- a/src/core/channels/midiSender.cpp
+++ b/src/core/channels/midiSender.cpp
@@ -25,7 +25,6 @@
* -------------------------------------------------------------------------- */
#include "core/channels/midiSender.h"
-#include "core/channels/channel.h"
#include "core/kernelMidi.h"
#include "core/mixer.h"
@@ -50,9 +49,9 @@ MidiSender::MidiSender(const Patch::Channel& p, KernelMidi& k)
/* -------------------------------------------------------------------------- */
-void MidiSender::react(const Channel& ch, const EventDispatcher::Event& e)
+void MidiSender::react(const EventDispatcher::Event& e)
{
- if (!ch.isPlaying() || !enabled || ch.isMuted())
+ if (!enabled)
return;
if (e.type == EventDispatcher::EventType::KEY_KILL ||
@@ -62,12 +61,12 @@ void MidiSender::react(const Channel& ch, const EventDispatcher::Event& e)
/* -------------------------------------------------------------------------- */
-void MidiSender::advance(const Channel& ch, const Sequencer::Event& e) const
+void MidiSender::advance(ID channelId, const Sequencer::Event& e) const
{
- if (!ch.isPlaying() || !enabled || ch.isMuted())
+ if (!enabled)
return;
if (e.type == Sequencer::EventType::ACTIONS)
- parseActions(ch, *e.actions);
+ parseActions(channelId, *e.actions);
}
/* -------------------------------------------------------------------------- */
@@ -83,10 +82,10 @@ void MidiSender::send(MidiEvent e) const
/* -------------------------------------------------------------------------- */
-void MidiSender::parseActions(const Channel& ch, const std::vector<Action>& as) const
+void MidiSender::parseActions(ID channelId, const std::vector<Action>& as) const
{
for (const Action& a : as)
- if (a.channelId == ch.id)
+ if (a.channelId == channelId)
send(a.event);
}
} // namespace giada::m \ No newline at end of file
diff --git a/src/core/channels/midiSender.h b/src/core/channels/midiSender.h
index 140f291..7076164 100644
--- a/src/core/channels/midiSender.h
+++ b/src/core/channels/midiSender.h
@@ -33,7 +33,6 @@
namespace giada::m
{
class KernelMidi;
-class Channel;
class MidiSender final
{
public:
@@ -41,8 +40,8 @@ public:
MidiSender(const Patch::Channel& p, KernelMidi&);
MidiSender(const MidiSender& o) = default;
- void react(const Channel& ch, const EventDispatcher::Event& e);
- void advance(const Channel& ch, const Sequencer::Event& e) const;
+ void react(const EventDispatcher::Event& e);
+ void advance(ID channelId, const Sequencer::Event& e) const;
KernelMidi* kernelMidi;
@@ -63,7 +62,7 @@ public:
private:
void send(MidiEvent e) const;
- void parseActions(const Channel& ch, const std::vector<Action>& as) const;
+ void parseActions(ID channelId, const std::vector<Action>& as) const;
};
} // namespace giada::m
diff --git a/src/core/channels/sampleReactor.cpp b/src/core/channels/sampleReactor.cpp
index b009d7b..b94e410 100644
--- a/src/core/channels/sampleReactor.cpp
+++ b/src/core/channels/sampleReactor.cpp
@@ -29,7 +29,6 @@
#include "core/conf.h"
#include "core/model/model.h"
#include "utils/math.h"
-#include <cassert>
namespace giada::m
{
@@ -61,7 +60,7 @@ SampleReactor::SampleReactor(Channel& ch, ID channelId)
/* -------------------------------------------------------------------------- */
void SampleReactor::react(Channel& ch, const EventDispatcher::Event& e,
- Sequencer& sequencer, const Conf::Data& conf) const
+ bool chansStopOnSeqHalt, bool canQuantize) const
{
if (!ch.hasWave())
return;
@@ -69,7 +68,7 @@ void SampleReactor::react(Channel& ch, const EventDispatcher::Event& e,
switch (e.type)
{
case EventDispatcher::EventType::KEY_PRESS:
- press(ch, sequencer, std::get<int>(e.data));
+ press(ch, std::get<int>(e.data), canQuantize);
break;
case EventDispatcher::EventType::KEY_RELEASE:
@@ -82,7 +81,7 @@ void SampleReactor::react(Channel& ch, const EventDispatcher::Event& e,
break;
case EventDispatcher::EventType::SEQUENCER_STOP:
- onStopBySeq(ch, conf.chansStopOnSeqHalt);
+ onStopBySeq(ch, chansStopOnSeqHalt);
break;
default:
@@ -114,8 +113,8 @@ void SampleReactor::stop(ChannelShared& shared) const
/* -------------------------------------------------------------------------- */
-ChannelStatus SampleReactor::pressWhileOff(Channel& ch, Sequencer& sequencer,
- int velocity, bool isLoop) const
+ChannelStatus SampleReactor::pressWhileOff(Channel& ch, int velocity, bool isLoop,
+ bool canQuantize) const
{
if (isLoop)
return ChannelStatus::WAIT;
@@ -123,7 +122,7 @@ ChannelStatus SampleReactor::pressWhileOff(Channel& ch, Sequencer& sequencer,
if (ch.samplePlayer->velocityAsVol)
ch.volume_i = u::math::map(velocity, G_MAX_VELOCITY, G_MAX_VOLUME);
- if (sequencer.canQuantize())
+ if (canQuantize)
{
ch.shared->quantizer->trigger(Q_ACTION_PLAY + ch.id);
return ChannelStatus::OFF;
@@ -134,8 +133,8 @@ ChannelStatus SampleReactor::pressWhileOff(Channel& ch, Sequencer& sequencer,
/* -------------------------------------------------------------------------- */
-ChannelStatus SampleReactor::pressWhilePlay(Channel& ch, Sequencer& sequencer,
- SamplePlayerMode mode, bool isLoop) const
+ChannelStatus SampleReactor::pressWhilePlay(Channel& ch, SamplePlayerMode mode,
+ bool isLoop, bool canQuantize) const
{
if (isLoop)
return ChannelStatus::ENDING;
@@ -143,7 +142,7 @@ ChannelStatus SampleReactor::pressWhilePlay(Channel& ch, Sequencer& sequencer,
switch (mode)
{
case SamplePlayerMode::SINGLE_RETRIG:
- if (sequencer.canQuantize())
+ if (canQuantize)
ch.shared->quantizer->trigger(Q_ACTION_REWIND + ch.id);
else
rewind(*ch.shared, /*localFrame=*/0);
@@ -163,7 +162,7 @@ ChannelStatus SampleReactor::pressWhilePlay(Channel& ch, Sequencer& sequencer,
/* -------------------------------------------------------------------------- */
-void SampleReactor::press(Channel& ch, Sequencer& sequencer, int velocity) const
+void SampleReactor::press(Channel& ch, int velocity, bool canQuantize) const
{
const SamplePlayerMode mode = ch.samplePlayer->mode;
const bool isLoop = ch.samplePlayer->isAnyLoopMode();
@@ -173,11 +172,11 @@ void SampleReactor::press(Channel& ch, Sequencer& sequencer, int velocity) const
switch (playStatus)
{
case ChannelStatus::OFF:
- playStatus = pressWhileOff(ch, sequencer, velocity, isLoop);
+ playStatus = pressWhileOff(ch, velocity, isLoop, canQuantize);
break;
case ChannelStatus::PLAY:
- playStatus = pressWhilePlay(ch, sequencer, mode, isLoop);
+ playStatus = pressWhilePlay(ch, mode, isLoop, canQuantize);
break;
case ChannelStatus::WAIT:
diff --git a/src/core/channels/sampleReactor.h b/src/core/channels/sampleReactor.h
index 0915779..693faf8 100644
--- a/src/core/channels/sampleReactor.h
+++ b/src/core/channels/sampleReactor.h
@@ -29,7 +29,6 @@
#include "core/conf.h"
#include "core/eventDispatcher.h"
-#include "core/quantizer.h"
namespace giada::m::model
{
@@ -40,7 +39,6 @@ namespace giada::m
{
class Channel;
struct ChannelShared;
-class Sequencer;
/* SampleReactor
Reacts to manual events sent to Sample Channels: key press, key release,
@@ -57,14 +55,14 @@ public:
SampleReactor(Channel&, ID channelId);
- void react(Channel&, const EventDispatcher::Event&, Sequencer&, const Conf::Data&) const;
+ void react(Channel&, const EventDispatcher::Event&, bool chansStopOnSeqHalt, bool canQuantize) const;
private:
void onStopBySeq(Channel&, bool chansStopOnSeqHalt) const;
void release(Channel&) const;
- void press(Channel&, Sequencer&, int velocity) const;
- ChannelStatus pressWhilePlay(Channel&, Sequencer&, SamplePlayerMode, bool isLoop) const;
- ChannelStatus pressWhileOff(Channel&, Sequencer&, int velocity, bool isLoop) const;
+ void press(Channel&, int velocity, bool canQuantize) const;
+ ChannelStatus pressWhilePlay(Channel&, SamplePlayerMode, bool isLoop, bool canQuantize) const;
+ ChannelStatus pressWhileOff(Channel&, int velocity, bool isLoop, bool canQuantize) const;
void rewind(ChannelShared&, Frame localFrame) const;
void play(ChannelShared&, Frame localFrame) const;
void stop(ChannelShared&) const;
diff --git a/src/core/conf.cpp b/src/core/conf.cpp
index ed38bf8..462e514 100644
--- a/src/core/conf.cpp
+++ b/src/core/conf.cpp
@@ -27,12 +27,12 @@
#include "core/conf.h"
#include "core/const.h"
#include "core/types.h"
-#include "deps/json/single_include/nlohmann/json.hpp"
#include "utils/fs.h"
#include "utils/log.h"
#include <FL/Fl.H>
#include <cassert>
#include <fstream>
+#include <nlohmann/json.hpp>
#include <string>
namespace nl = nlohmann;
@@ -41,20 +41,8 @@ namespace giada::m
{
Conf::Conf()
{
- /* Initialize m_confFilePath, i.e. the configuration file. In windows it is
- in the same dir of the .exe, while in Linux and OS X in ~/.giada */
-
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
-
- m_confFilePath = u::fs::getHomePath() + G_SLASH + CONF_FILENAME;
- m_confDirPath = u::fs::getHomePath() + G_SLASH;
-
-#elif defined(_WIN32)
-
- m_confFilePath = CONF_FILENAME;
- m_confDirPath = "";
-
-#endif
+ m_confFilePath = u::fs::join(u::fs::getHomePath(), CONF_FILENAME);
+ m_confDirPath = u::fs::getHomePath();
}
/* -------------------------------------------------------------------------- */
@@ -71,6 +59,7 @@ bool Conf::read()
data.logMode = j.value(CONF_KEY_LOG_MODE, data.logMode);
data.showTooltips = j.value(CONF_KEY_SHOW_TOOLTIPS, data.showTooltips);
+ data.langMap = j.value(CONF_KEY_LANGMAP, data.langMap);
data.soundSystem = j.value(CONF_KEY_SOUND_SYSTEM, data.soundSystem);
data.soundDeviceOut = j.value(CONF_KEY_SOUND_DEVICE_OUT, data.soundDeviceOut);
data.soundDeviceIn = j.value(CONF_KEY_SOUND_DEVICE_IN, data.soundDeviceIn);
@@ -174,6 +163,7 @@ bool Conf::write() const
j[CONF_KEY_HEADER] = "GIADACFG";
j[CONF_KEY_LOG_MODE] = data.logMode;
j[CONF_KEY_SHOW_TOOLTIPS] = data.showTooltips;
+ j[CONF_KEY_LANGMAP] = data.langMap;
j[CONF_KEY_SOUND_SYSTEM] = data.soundSystem;
j[CONF_KEY_SOUND_DEVICE_OUT] = data.soundDeviceOut;
j[CONF_KEY_SOUND_DEVICE_IN] = data.soundDeviceIn;
@@ -246,11 +236,11 @@ bool Conf::write() const
j[CONF_KEY_REC_TRIGGER_LEVEL] = data.recTriggerLevel;
j[CONF_KEY_INPUT_REC_MODE] = static_cast<int>(data.inputRecMode);
- j[CONF_KEY_BIND_PLAY] = data.keyBindings.find(KEY_BIND_PLAY)->second;
- j[CONF_KEY_BIND_REWIND] = data.keyBindings.find(KEY_BIND_REWIND)->second;
- j[CONF_KEY_BIND_RECORD_ACTIONS] = data.keyBindings.find(KEY_BIND_RECORD_ACTIONS)->second;
- j[CONF_KEY_BIND_RECORD_INPUT] = data.keyBindings.find(KEY_BIND_RECORD_INPUT)->second;
- j[CONF_KEY_BIND_EXIT] = data.keyBindings.find(KEY_BIND_EXIT)->second;
+ j[CONF_KEY_BIND_PLAY] = data.keyBindings[KEY_BIND_PLAY];
+ j[CONF_KEY_BIND_REWIND] = data.keyBindings[KEY_BIND_REWIND];
+ j[CONF_KEY_BIND_RECORD_ACTIONS] = data.keyBindings[KEY_BIND_RECORD_ACTIONS];
+ j[CONF_KEY_BIND_RECORD_INPUT] = data.keyBindings[KEY_BIND_RECORD_INPUT];
+ j[CONF_KEY_BIND_EXIT] = data.keyBindings[KEY_BIND_EXIT];
#ifdef WITH_VST
j[CONF_KEY_PLUGIN_CHOOSER_X] = data.pluginChooserX;
diff --git a/src/core/conf.h b/src/core/conf.h
index 8541878..1126f71 100644
--- a/src/core/conf.h
+++ b/src/core/conf.h
@@ -31,36 +31,37 @@
#include "core/types.h"
#include "utils/gui.h"
#include <string>
-#include <unordered_map>
+#include <vector>
namespace giada::m
{
class Conf final
{
public:
- using KeyBindings = std::unordered_map<int, int>;
+ using KeyBindings = std::vector<int>;
- static constexpr int KEY_BIND_PLAY = 1;
- static constexpr int KEY_BIND_REWIND = 2;
- static constexpr int KEY_BIND_RECORD_ACTIONS = 3;
- static constexpr int KEY_BIND_RECORD_INPUT = 4;
- static constexpr int KEY_BIND_EXIT = 5;
+ static constexpr int KEY_BIND_PLAY = 0;
+ static constexpr int KEY_BIND_REWIND = 1;
+ static constexpr int KEY_BIND_RECORD_ACTIONS = 2;
+ static constexpr int KEY_BIND_RECORD_INPUT = 3;
+ static constexpr int KEY_BIND_EXIT = 4;
struct Data
{
- int logMode = LOG_MODE_MUTE;
- bool showTooltips = true;
- int soundSystem = G_DEFAULT_SOUNDSYS;
- int soundDeviceOut = G_DEFAULT_SOUNDDEV_OUT;
- int soundDeviceIn = G_DEFAULT_SOUNDDEV_IN;
- int channelsOutCount = G_MAX_IO_CHANS;
- int channelsOutStart = 0;
- int channelsInCount = 1;
- int channelsInStart = 0;
- int samplerate = G_DEFAULT_SAMPLERATE;
- int buffersize = G_DEFAULT_BUFSIZE;
- bool limitOutput = false;
- int rsmpQuality = 0;
+ int logMode = LOG_MODE_MUTE;
+ bool showTooltips = true;
+ std::string langMap = "";
+ int soundSystem = G_DEFAULT_SOUNDSYS;
+ int soundDeviceOut = G_DEFAULT_SOUNDDEV_OUT;
+ int soundDeviceIn = G_DEFAULT_SOUNDDEV_IN;
+ int channelsOutCount = G_MAX_IO_CHANS;
+ int channelsOutStart = 0;
+ int channelsInCount = 1;
+ int channelsInStart = 0;
+ int samplerate = G_DEFAULT_SAMPLERATE;
+ int buffersize = G_DEFAULT_BUFSIZE;
+ bool limitOutput = false;
+ int rsmpQuality = 0;
int midiSystem = 0;
int midiPortOut = G_DEFAULT_MIDI_PORT_OUT;
@@ -144,11 +145,12 @@ public:
#endif
KeyBindings keyBindings = {
- {KEY_BIND_PLAY, ' '},
- {KEY_BIND_REWIND, FL_BackSpace},
- {KEY_BIND_RECORD_ACTIONS, FL_Enter},
- {KEY_BIND_RECORD_INPUT, FL_End},
- {KEY_BIND_EXIT, FL_Escape}};
+ ' ', // KEY_BIND_PLAY
+ FL_BackSpace, // KEY_BIND_REWIND
+ FL_Enter, // KEY_BIND_RECORD_ACTIONS
+ FL_End, // KEY_BIND_RECORD_INPUT
+ FL_Escape // KEY_BIND_EXIT
+ };
};
Conf();
diff --git a/src/core/const.h b/src/core/const.h
index db9bc5b..97b0343 100644
--- a/src/core/const.h
+++ b/src/core/const.h
@@ -59,21 +59,13 @@
/* -- version --------------------------------------------------------------- */
constexpr auto G_APP_NAME = "Giada";
-constexpr auto G_VERSION_STR = "0.21.0";
+constexpr auto G_VERSION_STR = "0.22.0";
constexpr int G_VERSION_MAJOR = 0;
-constexpr int G_VERSION_MINOR = 21;
+constexpr int G_VERSION_MINOR = 22;
constexpr int G_VERSION_PATCH = 0;
constexpr auto CONF_FILENAME = "giada.conf";
-#ifdef G_OS_WINDOWS
-#define G_SLASH '\\'
-#define G_SLASH_STR "\\"
-#else
-#define G_SLASH '/'
-#define G_SLASH_STR "/"
-#endif
-
/* -- Engine ---------------------------------------------------------------- */
/* G_EVENT_DISPATCHER_RATE_MS
The amount of sleep between each Event Dispatcher cycle. It should be lower
@@ -209,17 +201,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;
-constexpr int G_PATCH_UNREADABLE = -1;
-constexpr int G_PATCH_INVALID = 0;
-constexpr int G_PATCH_OK = 1;
-
-/* -- midimap signals ------------------------------------------------------- */
-constexpr int MIDIMAP_NOT_SPECIFIED = 0x00;
-constexpr int MIDIMAP_UNREADABLE = 0x01;
-constexpr int MIDIMAP_INVALID = 0x02;
-constexpr int MIDIMAP_READ_OK = 0x04;
+/* -- File signals ---------------------------------------------------------- */
+constexpr int G_FILE_NOT_SPECIFIED = -3;
+constexpr int G_FILE_UNSUPPORTED = -2;
+constexpr int G_FILE_UNREADABLE = -1;
+constexpr int G_FILE_INVALID = 0;
+constexpr int G_FILE_OK = 1;
/* -- MIDI in parameters (for MIDI learning) -------------------------------- */
constexpr int G_MIDI_IN_ENABLED = 1;
@@ -367,6 +354,7 @@ constexpr auto G_PATCH_KEY_ACTION_NEXT = "next";
constexpr auto CONF_KEY_HEADER = "header";
constexpr auto CONF_KEY_LOG_MODE = "log_mode";
constexpr auto CONF_KEY_SHOW_TOOLTIPS = "show_tooltips";
+constexpr auto CONF_KEY_LANGMAP = "langmap";
constexpr auto CONF_KEY_SOUND_SYSTEM = "sound_system";
constexpr auto CONF_KEY_SOUND_DEVICE_IN = "sound_device_in";
constexpr auto CONF_KEY_SOUND_DEVICE_OUT = "sound_device_out";
diff --git a/src/core/engine.cpp b/src/core/engine.cpp
index 2b05d8f..0514011 100644
--- a/src/core/engine.cpp
+++ b/src/core/engine.cpp
@@ -35,7 +35,7 @@ namespace giada::m
{
bool LoadState::isGood() const
{
- return patch == G_PATCH_OK && missingWaves.empty() && missingPlugins.empty();
+ return patch == G_FILE_OK && missingWaves.empty() && missingPlugins.empty();
}
/* -------------------------------------------------------------------------- */
@@ -174,7 +174,7 @@ void Engine::init()
init::printBuildInfo();
midiMapper.init();
- if (midiMapper.read(conf.data.midiMapPath) != MIDIMAP_READ_OK)
+ if (midiMapper.read(conf.data.midiMapPath) != G_FILE_OK)
u::log::print("[Engine::init] MIDI map read failed!\n");
/* Initialize KernelAudio. If fails, interrupt the Engine initialization:
@@ -383,7 +383,7 @@ LoadState Engine::load(const std::string& projectPath, const std::string& patchP
progress(0.0f);
patch.reset();
- if (int res = patch.read(patchPath, projectPath); res != G_PATCH_OK)
+ if (int res = patch.read(patchPath, projectPath); res != G_FILE_OK)
return {res};
progress(0.3f);
@@ -418,7 +418,7 @@ LoadState Engine::load(const std::string& projectPath, const std::string& patchP
progress(1.0f);
- state.patch = G_PATCH_OK;
+ state.patch = G_FILE_OK;
return state;
}
diff --git a/src/core/engine.h b/src/core/engine.h
index c7d242e..ed2596d 100644
--- a/src/core/engine.h
+++ b/src/core/engine.h
@@ -55,7 +55,7 @@ struct LoadState
{
bool isGood() const;
- int patch = G_PATCH_OK;
+ int patch = G_FILE_OK;
std::vector<std::string> missingWaves = {};
std::vector<std::string> missingPlugins = {};
};
@@ -97,7 +97,7 @@ public:
/* reset
Resets all sub-components to the initial state. Useful when Giada needs to
- be brought back to the starup state. */
+ be brought back to the startup state. */
void reset();
diff --git a/src/core/eventDispatcher.cpp b/src/core/eventDispatcher.cpp
index e0c8939..1760a55 100644
--- a/src/core/eventDispatcher.cpp
+++ b/src/core/eventDispatcher.cpp
@@ -54,7 +54,7 @@ void EventDispatcher::pumpMidiEvent(Event e) { MidiEvents.push(e); }
/* -------------------------------------------------------------------------- */
-void EventDispatcher::processFuntions()
+void EventDispatcher::processFunctions()
{
assert(onMidiLearn != nullptr);
assert(onMidiProcess != nullptr);
@@ -105,7 +105,7 @@ void EventDispatcher::process()
if (m_eventBuffer.size() == 0)
return;
- processFuntions();
+ processFunctions();
onProcessChannels(m_eventBuffer);
onProcessSequencer(m_eventBuffer);
}
diff --git a/src/core/eventDispatcher.h b/src/core/eventDispatcher.h
index 3462201..e506d67 100644
--- a/src/core/eventDispatcher.h
+++ b/src/core/eventDispatcher.h
@@ -124,7 +124,7 @@ public:
std::function<void()> onMixerEndOfRecCallback;
private:
- void processFuntions();
+ void processFunctions();
void process();
/* m_worker
diff --git a/src/core/init.cpp b/src/core/init.cpp
index ccd97f0..b72400c 100644
--- a/src/core/init.cpp
+++ b/src/core/init.cpp
@@ -92,6 +92,7 @@ void printBuildInfo()
u::log::print("[init] JUCE - %d.%d.%d\n", JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JUCE_BUILDNUMBER);
#endif
KernelAudio::logCompiledAPIs();
+ KernelMidi::logCompiledAPIs();
}
/* -------------------------------------------------------------------------- */
@@ -105,8 +106,7 @@ void startup(int argc, char** argv)
g_ui.init(argc, argv, g_engine);
if (!g_engine.kernelAudio.isReady())
- v::gdAlert("Your soundcard isn't configured correctly.\n"
- "Check the configuration and restart Giada.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_INIT_WRONGSYSTEM));
}
/* -------------------------------------------------------------------------- */
@@ -121,7 +121,7 @@ int run()
void closeMainWindow()
{
- if (!v::gdConfirmWin("Warning", "Quit Giada: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING), g_ui.langMapper.get(v::LangMap::MESSAGE_INIT_QUITGIADA)))
return;
shutdown();
}
diff --git a/src/core/kernelMidi.cpp b/src/core/kernelMidi.cpp
index 040b0e2..9d2b119 100644
--- a/src/core/kernelMidi.cpp
+++ b/src/core/kernelMidi.cpp
@@ -244,4 +244,45 @@ void KernelMidi::logPorts(RtMidi& device, std::string name) const
for (unsigned i = 0; i < device.getPortCount(); i++)
u::log::print(" %d) %s\n", i, device.getPortName(i));
}
+
+/* -------------------------------------------------------------------------- */
+
+void KernelMidi::logCompiledAPIs()
+{
+ std::vector<RtMidi::Api> apis;
+ RtMidi::getCompiledApi(apis);
+
+ u::log::print("[KM] Compiled RtMidi APIs: %d\n", apis.size());
+
+ for (const RtMidi::Api& api : apis)
+ {
+ switch (api)
+ {
+ case RtMidi::Api::UNSPECIFIED:
+ u::log::print(" UNSPECIFIED\n");
+ break;
+ case RtMidi::Api::MACOSX_CORE:
+ u::log::print(" CoreAudio\n");
+ break;
+ case RtMidi::Api::LINUX_ALSA:
+ u::log::print(" ALSA\n");
+ break;
+ case RtMidi::Api::UNIX_JACK:
+ u::log::print(" JACK\n");
+ break;
+ case RtMidi::Api::WINDOWS_MM:
+ u::log::print(" Microsoft Multimedia MIDI API\n");
+ break;
+ case RtMidi::Api::RTMIDI_DUMMY:
+ u::log::print(" Dummy\n");
+ break;
+ case RtMidi::Api::WEB_MIDI_API:
+ u::log::print(" Web MIDI API\n");
+ break;
+ default:
+ u::log::print(" (unknown)\n");
+ break;
+ }
+ }
+}
} // namespace giada::m
diff --git a/src/core/kernelMidi.h b/src/core/kernelMidi.h
index ac10e22..93fe8cc 100644
--- a/src/core/kernelMidi.h
+++ b/src/core/kernelMidi.h
@@ -41,6 +41,8 @@ class KernelMidi final
public:
KernelMidi();
+ static void logCompiledAPIs();
+
unsigned countOutPorts() const;
unsigned countInPorts() const;
diff --git a/src/core/midiDispatcher.cpp b/src/core/midiDispatcher.cpp
index 2cff699..843fd15 100644
--- a/src/core/midiDispatcher.cpp
+++ b/src/core/midiDispatcher.cpp
@@ -116,7 +116,7 @@ void MidiDispatcher::dispatch(uint32_t msg)
/* Start dispatcher. Don't parse channels if MIDI learn is ON, just learn
the incoming MIDI signal. The action is not invoked directly, but scheduled
- to be perfomed by the Event Dispatcher. */
+ to be performed by the Event Dispatcher. */
Action action = {0, 0, 0, midiEvent};
auto event = m_learnCb != nullptr ? EventDispatcher::EventType::MIDI_DISPATCHER_LEARN : EventDispatcher::EventType::MIDI_DISPATCHER_PROCESS;
diff --git a/src/core/midiMapper.cpp b/src/core/midiMapper.cpp
index 839d69d..1adfac5 100644
--- a/src/core/midiMapper.cpp
+++ b/src/core/midiMapper.cpp
@@ -58,14 +58,7 @@ template <typename KernelMidiI>
MidiMapper<KernelMidiI>::MidiMapper(KernelMidiI& k)
: m_kernelMidi(k)
{
-}
-
-/* -------------------------------------------------------------------------- */
-
-template <typename KernelMidiI>
-const std::vector<std::string>& MidiMapper<KernelMidiI>::getMapFilesFound() const
-{
- return m_mapFiles;
+ m_mapsPath = u::fs::getMidiMapsPath();
}
/* -------------------------------------------------------------------------- */
@@ -73,28 +66,7 @@ const std::vector<std::string>& MidiMapper<KernelMidiI>::getMapFilesFound() cons
template <typename KernelMidiI>
void MidiMapper<KernelMidiI>::init()
{
- m_mapsPath = u::fs::getHomePath() + G_SLASH + "midimaps" + G_SLASH;
-
- /* scan dir of midi maps and load the filenames into m_mapFiles vector. */
-
- u::log::print("[MidiMapper::init] scanning midimaps directory '%s'...\n",
- m_mapsPath);
-
- if (!std::filesystem::exists(m_mapsPath))
- {
- u::log::print("[MidiMapper::init] unable to scan midimaps directory!\n");
- return;
- }
-
- for (const auto& d : std::filesystem::directory_iterator(m_mapsPath))
- {
- // TODO - check if is a valid midiMap file (verify headers)
- if (!d.is_regular_file())
- continue;
- u::log::print("[MidiMapper::init] found midiMap '%s'\n", d.path().filename().string());
- m_mapFiles.push_back(d.path().filename().string());
- }
-
+ Mapper::init();
u::log::print("[MidiMapper::init] total midimaps found: %d\n", m_mapFiles.size());
}
@@ -103,25 +75,17 @@ void MidiMapper<KernelMidiI>::init()
template <typename KernelMidiI>
int MidiMapper<KernelMidiI>::read(const std::string& file)
{
- if (file.empty())
- {
- u::log::print("[MidiMapper::read] midiMap not specified, nothing to do\n");
- return MIDIMAP_NOT_SPECIFIED;
- }
-
- u::log::print("[MidiMapper::read] reading midiMap file '%s'\n", file);
-
- std::ifstream ifs(m_mapsPath + file);
- if (!ifs.good())
- return MIDIMAP_UNREADABLE;
+ std::optional<nl::json> res = Mapper::read(file);
+ if (!res)
+ return G_FILE_UNREADABLE;
- nl::json j = nl::json::parse(ifs);
+ nl::json j = res.value();
currentMap.brand = j[MIDIMAP_KEY_BRAND];
currentMap.device = j[MIDIMAP_KEY_DEVICE];
if (!readInitCommands(currentMap, j))
- return MIDIMAP_UNREADABLE;
+ return G_FILE_UNREADABLE;
if (readCommand(j, currentMap.muteOn, MIDIMAP_KEY_MUTE_ON))
parse(currentMap.muteOn);
if (readCommand(j, currentMap.muteOff, MIDIMAP_KEY_MUTE_OFF))
@@ -141,7 +105,7 @@ int MidiMapper<KernelMidiI>::read(const std::string& file)
if (readCommand(j, currentMap.playingInaudible, MIDIMAP_KEY_PLAYING_INAUDIBLE))
parse(currentMap.playingInaudible);
- return MIDIMAP_READ_OK;
+ return G_FILE_OK;
}
/* -------------------------------------------------------------------------- */
diff --git a/src/core/midiMapper.h b/src/core/midiMapper.h
index f8f2c13..8bcd890 100644
--- a/src/core/midiMapper.h
+++ b/src/core/midiMapper.h
@@ -27,7 +27,8 @@
#ifndef G_MIDIMAPPER_H
#define G_MIDIMAPPER_H
-#include "deps/json/single_include/nlohmann/json.hpp"
+#include "mapper.h"
+#include <nlohmann/json.hpp>
#include <string>
#include <vector>
@@ -70,17 +71,14 @@ struct MidiMap
Message playingInaudible;
};
+/* -------------------------------------------------------------------------- */
+
template <typename KernelMidiI>
-class MidiMapper final
+class MidiMapper final : public Mapper
{
public:
MidiMapper(KernelMidiI&);
- /* getMapFilesFound
- Returns a reference to the list of midimaps found. */
-
- const std::vector<std::string>& getMapFilesFound() const;
-
/* init
Parses the midimap folders and find the available midimaps. */
@@ -126,17 +124,6 @@ private:
/* TODO - don't edit message in place! */
bool readCommand(const nlohmann::json& j, MidiMap::Message& m, const std::string& key) const;
-
- /* m_mapsPath
- Path to folder containing midimap files, different between OSes. */
-
- std::string m_mapsPath;
-
- /* m_mapFiles
- The available .giadamap files. Each element of the vector represents
- a .giadamap file found in the midimap folder. */
-
- std::vector<std::string> m_mapFiles;
};
extern template class MidiMapper<KernelMidi>;
diff --git a/src/core/patch.cpp b/src/core/patch.cpp
index 498b12f..bfeb64c 100644
--- a/src/core/patch.cpp
+++ b/src/core/patch.cpp
@@ -26,10 +26,10 @@
#include "patch.h"
#include "core/mixer.h"
-#include "deps/json/single_include/nlohmann/json.hpp"
#include "utils/log.h"
#include "utils/math.h"
#include <fstream>
+#include <nlohmann/json.hpp>
namespace nl = nlohmann;
@@ -107,7 +107,7 @@ void readWaves_(Patch::Data& patch, const nl::json& j, const std::string& basePa
{
Patch::Wave w;
w.id = jwave.value(PATCH_KEY_WAVE_ID, ++id);
- w.path = basePath + G_SLASH + jwave.value(PATCH_KEY_WAVE_PATH, "");
+ w.path = u::fs::join(basePath, jwave.value(PATCH_KEY_WAVE_PATH, ""));
patch.waves.push_back(w);
}
}
@@ -439,19 +439,19 @@ int Patch::read(const std::string& file, const std::string& basePath)
{
std::ifstream ifs(file);
if (!ifs.good())
- return G_PATCH_UNREADABLE;
+ return G_FILE_UNREADABLE;
nl::json j = nl::json::parse(ifs);
if (j[PATCH_KEY_HEADER] != "GIADAPTC")
- return G_PATCH_INVALID;
+ return G_FILE_INVALID;
data.version = {
static_cast<int>(j[PATCH_KEY_VERSION_MAJOR]),
static_cast<int>(j[PATCH_KEY_VERSION_MINOR]),
static_cast<int>(j[PATCH_KEY_VERSION_PATCH])};
if (data.version < Version{0, 16, 0})
- return G_PATCH_UNSUPPORTED;
+ return G_FILE_UNSUPPORTED;
try
{
@@ -468,9 +468,9 @@ int Patch::read(const std::string& file, const std::string& basePath)
catch (nl::json::exception& e)
{
u::log::print("[patch::read] Exception thrown: %s\n", e.what());
- return G_PATCH_INVALID;
+ return G_FILE_INVALID;
}
- return G_PATCH_OK;
+ return G_FILE_OK;
}
} // namespace giada::m
diff --git a/src/core/plugins/pluginManager.cpp b/src/core/plugins/pluginManager.cpp
index 8ffbf6e..ce874dd 100644
--- a/src/core/plugins/pluginManager.cpp
+++ b/src/core/plugins/pluginManager.cpp
@@ -49,7 +49,7 @@ void PluginManager::reset(SortMethod sortMethod)
if (m_formatManager.getNumFormats() == 0) // Must be called only once
m_formatManager.addDefaultFormats();
- loadList(u::fs::getHomePath() + G_SLASH + "plugins.xml");
+ loadList(u::fs::join(u::fs::getHomePath(), "plugins.xml"));
sortPlugins(sortMethod);
}
diff --git a/src/core/waveManager.cpp b/src/core/waveManager.cpp
index fbb16bb..fb8cec7 100644
--- a/src/core/waveManager.cpp
+++ b/src/core/waveManager.cpp
@@ -65,7 +65,7 @@ int getBits_(const SF_INFO& header)
std::string makeWavePath_(const std::string& base, const m::Wave& w, int k)
{
- return base + G_SLASH + w.getBasename(/*ext=*/false) + "-" + std::to_string(k) + w.getExtension();
+ return u::fs::join(base, w.getBasename(/*ext=*/false) + "-" + std::to_string(k) + w.getExtension());
}
/* -------------------------------------------------------------------------- */
@@ -88,7 +88,7 @@ bool isWavePathUnique_(const m::Wave& skip, const std::string& path,
std::string makeUniqueWavePath(const std::string& base, const m::Wave& w,
const std::vector<std::unique_ptr<Wave>>& waves)
{
- std::string path = base + G_SLASH + w.getBasename(/*ext=*/true);
+ std::string path = u::fs::join(base, w.getBasename(/*ext=*/true));
if (isWavePathUnique_(w, path, waves))
return path;
diff --git a/src/glue/channel.cpp b/src/glue/channel.cpp
index 2e25bc2..0644342 100644
--- a/src/glue/channel.cpp
+++ b/src/glue/channel.cpp
@@ -51,7 +51,6 @@
#include "gui/elems/mainWindow/keyboard/channelButton.h"
#include "gui/elems/mainWindow/keyboard/keyboard.h"
#include "gui/elems/mainWindow/keyboard/sampleChannel.h"
-#include "gui/elems/sampleEditor/boostTool.h"
#include "gui/elems/sampleEditor/panTool.h"
#include "gui/elems/sampleEditor/pitchTool.h"
#include "gui/elems/sampleEditor/rangeTool.h"
@@ -78,13 +77,13 @@ namespace
void printLoadError_(int res)
{
if (res == G_RES_ERR_WRONG_DATA)
- v::gdAlert("Multichannel samples not supported.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_MULTICHANNOTSUPPORTED));
else if (res == G_RES_ERR_IO)
- v::gdAlert("Unable to read this sample.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_CANTREADSAMPLE));
else if (res == G_RES_ERR_PATH_TOO_LONG)
- v::gdAlert("File path too long.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_PATHTOOLONG));
else if (res == G_RES_ERR_NO_DATA)
- v::gdAlert("No file specified.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_NOFILESPECIFIED));
}
} // namespace
@@ -176,7 +175,7 @@ std::vector<Data> getChannels()
int loadChannel(ID channelId, const std::string& fname)
{
- auto progress = g_ui.mainWindow->getScopedProgress("Loading sample...");
+ auto progress = g_ui.mainWindow->getScopedProgress(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_LOADINGSAMPLES));
m::WaveManager::Result res = g_engine.waveManager.createFromFile(fname, /*id=*/0,
g_engine.kernelAudio.getSampleRate(), g_engine.conf.data.rsmpQuality);
@@ -213,7 +212,7 @@ void addChannel(ID columnId, ChannelType type)
void addAndLoadChannels(ID columnId, const std::vector<std::string>& fnames)
{
- auto progress = g_ui.mainWindow->getScopedProgress("Loading samples...");
+ auto progress = g_ui.mainWindow->getScopedProgress(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_LOADINGSAMPLES));
bool errors = false;
int i = 0;
@@ -231,14 +230,14 @@ void addAndLoadChannels(ID columnId, const std::vector<std::string>& fnames)
}
if (errors)
- v::gdAlert("Some files weren't loaded successfully.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_LOADINGSAMPLESERROR));
}
/* -------------------------------------------------------------------------- */
void deleteChannel(ID channelId)
{
- if (!v::gdConfirmWin("Warning", "Delete channel: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING), g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_DELETE)))
return;
g_ui.closeAllSubwindows();
@@ -256,7 +255,7 @@ void deleteChannel(ID channelId)
void freeChannel(ID channelId)
{
- if (!v::gdConfirmWin("Warning", "Free channel: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING), g_ui.langMapper.get(v::LangMap::MESSAGE_CHANNEL_FREE)))
return;
g_ui.closeAllSubwindows();
g_engine.actionRecorder.clearChannel(channelId);
diff --git a/src/glue/config.cpp b/src/glue/config.cpp
index db2c926..258e3a9 100644
--- a/src/glue/config.cpp
+++ b/src/glue/config.cpp
@@ -243,6 +243,8 @@ MiscData getMiscData()
MiscData miscData;
miscData.logMode = g_engine.conf.data.logMode;
miscData.showTooltips = g_engine.conf.data.showTooltips;
+ miscData.langMaps = g_ui.langMapper.getMapFilesFound();
+ miscData.langMap = g_engine.conf.data.langMap;
return miscData;
}
/* -------------------------------------------------------------------------- */
@@ -293,7 +295,8 @@ void save(const MiscData& data)
{
g_engine.conf.data.logMode = data.logMode;
g_engine.conf.data.showTooltips = data.showTooltips;
- Fl_Tooltip::enable(g_engine.conf.data.showTooltips);
+ g_engine.conf.data.langMap = data.langMap;
+ Fl_Tooltip::enable(g_engine.conf.data.showTooltips); // TODO - move this to UI init
}
/* -------------------------------------------------------------------------- */
@@ -303,7 +306,7 @@ void save(const MiscData& data)
void scanPlugins(std::string dir, const std::function<void(float)>& progress)
{
g_engine.pluginManager.scanDirs(dir, progress);
- g_engine.pluginManager.saveList(u::fs::getHomePath() + G_SLASH + "plugins.xml");
+ g_engine.pluginManager.saveList(u::fs::join(u::fs::getHomePath(), "plugins.xml"));
}
/* -------------------------------------------------------------------------- */
@@ -315,7 +318,7 @@ void setPluginPathCb(void* data)
if (browser->getCurrentPath() == "")
{
- v::gdAlert("Invalid path.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::CONFIG_PLUGINS_INVALIDPATH));
return;
}
diff --git a/src/glue/config.h b/src/glue/config.h
index 55878c6..fa9105f 100644
--- a/src/glue/config.h
+++ b/src/glue/config.h
@@ -108,8 +108,13 @@ struct PluginData
struct MiscData
{
- int logMode;
- bool showTooltips;
+ int logMode;
+ bool showTooltips;
+ std::vector<std::string> langMaps;
+
+ /* Selectable values. */
+
+ std::string langMap;
};
/* get*
diff --git a/src/glue/io.cpp b/src/glue/io.cpp
index 30e2d4f..d7c1a50 100644
--- a/src/glue/io.cpp
+++ b/src/glue/io.cpp
@@ -72,8 +72,8 @@ bool isValidKey_(int key)
{
if (strlen(Fl::event_text()) == 0)
return false;
- for (const auto& [_, val] : g_engine.conf.data.keyBindings)
- if (key == val)
+ for (const int& bind : g_engine.conf.data.keyBindings)
+ if (key == bind)
return false;
return true;
}
diff --git a/src/glue/layout.cpp b/src/glue/layout.cpp
index 76e7357..f611a0f 100644
--- a/src/glue/layout.cpp
+++ b/src/glue/layout.cpp
@@ -62,8 +62,8 @@ namespace giada::c::layout
{
void openBrowserForProjectLoad()
{
- v::gdWindow* childWin = new v::gdBrowserLoad("Open project", g_engine.conf.data.patchPath,
- c::storage::loadProject, 0, g_engine.conf.data);
+ v::gdWindow* childWin = new v::gdBrowserLoad(g_ui.langMapper.get(v::LangMap::BROWSER_OPENPROJECT),
+ g_engine.conf.data.patchPath, c::storage::loadProject, 0, g_engine.conf.data);
g_ui.openSubWindow(*g_ui.mainWindow.get(), childWin, WID_FILE_BROWSER);
}
@@ -71,8 +71,8 @@ void openBrowserForProjectLoad()
void openBrowserForProjectSave()
{
- v::gdWindow* childWin = new v::gdBrowserSave("Save project", g_engine.conf.data.patchPath,
- g_engine.patch.data.name, c::storage::saveProject, 0, g_engine.conf.data);
+ v::gdWindow* childWin = new v::gdBrowserSave(g_ui.langMapper.get(v::LangMap::BROWSER_SAVEPROJECT),
+ g_engine.conf.data.patchPath, g_engine.patch.data.name, c::storage::saveProject, 0, g_engine.conf.data);
g_ui.openSubWindow(*g_ui.mainWindow.get(), childWin, WID_FILE_BROWSER);
}
@@ -80,7 +80,7 @@ void openBrowserForProjectSave()
void openBrowserForSampleLoad(ID channelId)
{
- v::gdWindow* w = new v::gdBrowserLoad("Browse sample",
+ v::gdWindow* w = new v::gdBrowserLoad(g_ui.langMapper.get(v::LangMap::BROWSER_OPENSAMPLE),
g_engine.conf.data.samplePath.c_str(), c::storage::loadSample, channelId, g_engine.conf.data);
g_ui.openSubWindow(*g_ui.mainWindow.get(), w, WID_FILE_BROWSER);
}
@@ -89,7 +89,7 @@ void openBrowserForSampleLoad(ID channelId)
void openBrowserForSampleSave(ID channelId)
{
- v::gdWindow* w = new v::gdBrowserSave("Save sample",
+ v::gdWindow* w = new v::gdBrowserSave(g_ui.langMapper.get(v::LangMap::BROWSER_SAVESAMPLE),
g_engine.conf.data.samplePath.c_str(), "", c::storage::saveSample, channelId, g_engine.conf.data);
g_ui.openSubWindow(*g_ui.mainWindow.get(), w, WID_FILE_BROWSER);
}
@@ -209,7 +209,7 @@ void openMissingAssetsWindow(const m::LoadState& state)
void openBrowserForPlugins(v::gdWindow& parent)
{
- v::gdBrowserDir* browser = new v::gdBrowserDir("Add plug-ins directory",
+ v::gdBrowserDir* browser = new v::gdBrowserDir(g_ui.langMapper.get(v::LangMap::BROWSER_OPENPLUGINSDIR),
g_engine.conf.data.patchPath, c::config::setPluginPathCb, g_engine.conf.data);
parent.addSubWindow(browser);
}
diff --git a/src/glue/main.cpp b/src/glue/main.cpp
index dca6339..320ebf2 100644
--- a/src/glue/main.cpp
+++ b/src/glue/main.cpp
@@ -213,7 +213,8 @@ void quantize(int val)
void clearAllSamples()
{
- if (!v::gdConfirmWin("Warning", "Free all Sample channels: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_MAIN_FREEALLSAMPLES)))
return;
g_ui.closeSubWindow(WID_SAMPLE_EDITOR);
g_engine.sequencer.setStatus(SeqStatus::STOPPED);
@@ -226,7 +227,8 @@ void clearAllSamples()
void clearAllActions()
{
- if (!v::gdConfirmWin("Warning", "Clear all actions: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_MAIN_CLEARALLACTIONS)))
return;
g_ui.closeSubWindow(WID_ACTION_EDITOR);
g_engine.actionRecorder.clearAllActions();
@@ -276,7 +278,8 @@ void printDebugInfo()
void closeProject()
{
- if (!v::gdConfirmWin("Warning", "Close project: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_MAIN_CLOSEPROJECT)))
return;
g_engine.mixer.disable();
g_ui.reset();
diff --git a/src/glue/recorder.cpp b/src/glue/recorder.cpp
index a25f382..326f1aa 100644
--- a/src/glue/recorder.cpp
+++ b/src/glue/recorder.cpp
@@ -50,7 +50,8 @@ namespace giada::c::recorder
{
void clearAllActions(ID channelId)
{
- if (!v::gdConfirmWin("Warning", "Clear all actions: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_MAIN_CLEARALLACTIONS)))
return;
g_engine.actionRecorder.clearChannel(channelId);
updateChannel(channelId, /*updateActionEditor=*/true);
@@ -60,7 +61,8 @@ void clearAllActions(ID channelId)
void clearVolumeActions(ID channelId)
{
- if (!v::gdConfirmWin("Warning", "Clear all volume actions: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_MAIN_CLEARALLVOLUMEACTIONS)))
return;
g_engine.actionRecorder.clearActions(channelId, m::MidiEvent::ENVELOPE);
updateChannel(channelId, /*updateActionEditor=*/true);
@@ -70,7 +72,8 @@ void clearVolumeActions(ID channelId)
void clearStartStopActions(ID channelId)
{
- if (!v::gdConfirmWin("Warning", "Clear all start/stop actions: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_MAIN_CLEARALLSTARTSTOPACTIONS)))
return;
g_engine.actionRecorder.clearActions(channelId, m::MidiEvent::NOTE_ON);
g_engine.actionRecorder.clearActions(channelId, m::MidiEvent::NOTE_OFF);
diff --git a/src/glue/sampleEditor.cpp b/src/glue/sampleEditor.cpp
index 942fb9e..e3545e2 100644
--- a/src/glue/sampleEditor.cpp
+++ b/src/glue/sampleEditor.cpp
@@ -40,7 +40,6 @@
#include "gui/elems/basics/button.h"
#include "gui/elems/mainWindow/keyboard/channel.h"
#include "gui/elems/mainWindow/keyboard/keyboard.h"
-#include "gui/elems/sampleEditor/boostTool.h"
#include "gui/elems/sampleEditor/panTool.h"
#include "gui/elems/sampleEditor/pitchTool.h"
#include "gui/elems/sampleEditor/rangeTool.h"
@@ -372,7 +371,7 @@ bool isWaveBufferFull()
void reload(ID channelId)
{
- if (!v::gdConfirmWin("Warning", "Reload sample: are you sure?"))
+ if (!v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING), "Reload sample: are you sure?"))
return;
if (channel::loadChannel(channelId, getWave_(channelId).getPath()) != G_RES_OK)
diff --git a/src/glue/storage.cpp b/src/glue/storage.cpp
index 8a7ab66..cb3c6aa 100644
--- a/src/glue/storage.cpp
+++ b/src/glue/storage.cpp
@@ -67,9 +67,9 @@ void loadProject(void* data)
v::gdBrowserLoad* browser = static_cast<v::gdBrowserLoad*>(data);
const std::string projectPath = browser->getSelectedItem();
- const std::string patchPath = projectPath + G_SLASH + u::fs::stripExt(u::fs::basename(projectPath)) + ".gptc";
+ const std::string patchPath = u::fs::join(projectPath, u::fs::stripExt(u::fs::basename(projectPath)) + ".gptc");
- auto progress = g_ui.mainWindow->getScopedProgress("Loading project...");
+ auto progress = g_ui.mainWindow->getScopedProgress(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_LOADINGPROJECT));
auto progressCb = [&p = progress.get()](float v) {
p.setProgress(v);
};
@@ -81,14 +81,14 @@ void loadProject(void* data)
m::LoadState state = g_engine.load(projectPath, patchPath, progressCb);
- if (state.patch != G_PATCH_OK)
+ if (state.patch != G_FILE_OK)
{
- if (state.patch == G_PATCH_UNREADABLE)
- v::gdAlert("This patch is unreadable.");
- else if (state.patch == G_PATCH_INVALID)
- v::gdAlert("This patch is not valid.");
- else if (state.patch == G_PATCH_UNSUPPORTED)
- v::gdAlert("This patch format is no longer supported.");
+ if (state.patch == G_FILE_UNREADABLE)
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_PATCHUNREADABLE));
+ else if (state.patch == G_FILE_INVALID)
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_PATCHINVALID));
+ else if (state.patch == G_FILE_UNSUPPORTED)
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_PATCHUNSUPPORTED));
return;
}
@@ -109,19 +109,20 @@ void saveProject(void* data)
v::gdBrowserSave* browser = static_cast<v::gdBrowserSave*>(data);
const std::string projectName = u::fs::stripExt(browser->getName());
- const std::string projectPath = browser->getCurrentPath() + G_SLASH + projectName + ".gprj";
- const std::string patchPath = projectPath + G_SLASH + projectName + ".gptc";
+ const std::string projectPath = u::fs::join(browser->getCurrentPath(), projectName + ".gprj");
+ const std::string patchPath = u::fs::join(projectPath, projectName + ".gptc");
if (projectName == "")
{
- v::gdAlert("Please choose a project name.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_CHOOSEPROJECTNAME));
return;
}
- if (u::fs::dirExists(projectPath) && !v::gdConfirmWin("Warning", "Project exists: overwrite?"))
+ if (u::fs::dirExists(projectPath) &&
+ !v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING), g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_PROJECTEXISTS)))
return;
- auto progress = g_ui.mainWindow->getScopedProgress("Saving project...");
+ auto progress = g_ui.mainWindow->getScopedProgress(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_SAVINGPROJECT));
auto progressCb = [&p = progress.get()](float v) {
p.setProgress(v);
};
@@ -130,7 +131,7 @@ void saveProject(void* data)
if (!g_engine.store(projectName, projectPath, patchPath, progressCb))
{
- v::gdAlert("Unable to save the project!");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_SAVINGPROJECTERROR));
return;
}
@@ -147,7 +148,7 @@ void loadSample(void* data)
if (fullPath.empty())
return;
- auto progress = g_ui.mainWindow->getScopedProgress("Loading sample...");
+ auto progress = g_ui.mainWindow->getScopedProgress(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_LOADINGSAMPLE));
if (int res = c::channel::loadChannel(browser->getChannelId(), fullPath); res == G_RES_OK)
{
@@ -168,13 +169,15 @@ void saveSample(void* data)
if (name == "")
{
- v::gdAlert("Please choose a file name.");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_CHOOSEFILENAME));
return;
}
- std::string filePath = folderPath + G_SLASH + u::fs::stripExt(name) + ".wav";
+ std::string filePath = u::fs::join(folderPath, u::fs::stripExt(name) + ".wav");
- if (u::fs::fileExists(filePath) && !v::gdConfirmWin("Warning", "File exists: overwrite?"))
+ if (u::fs::fileExists(filePath) &&
+ !v::gdConfirmWin(g_ui.langMapper.get(v::LangMap::COMMON_WARNING),
+ g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_FILEEXISTS)))
return;
ID waveId = g_engine.model.get().getChannel(channelId).samplePlayer->getWaveId();
@@ -184,7 +187,7 @@ void saveSample(void* data)
if (!g_engine.waveManager.save(*wave, filePath))
{
- v::gdAlert("Unable to save this sample!");
+ v::gdAlert(g_ui.langMapper.get(v::LangMap::MESSAGE_STORAGE_SAVINGFILEERROR));
return;
}
diff --git a/src/gui/dialogs/about.cpp b/src/gui/dialogs/about.cpp
index ac3ded7..9635c79 100644
--- a/src/gui/dialogs/about.cpp
+++ b/src/gui/dialogs/about.cpp
@@ -32,78 +32,83 @@
#ifdef WITH_VST
#include "deps/juce-config.h"
#endif
-#include "about.h"
+#include "gui/dialogs/about.h"
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/button.h"
+#include "gui/elems/basics/flex.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
+#include <fmt/core.h>
+
+extern giada::v::Ui g_ui;
namespace giada::v
{
gdAbout::gdAbout()
#ifdef WITH_VST
-: gdWindow(340, 415, "About Giada")
+: gdWindow(340, 415, g_ui.langMapper.get(LangMap::ABOUT_TITLE))
#else
-: gdWindow(340, 330, "About Giada")
-#endif
-, logo(8, 20, 324, 86)
-, text(8, 120, 324, 140)
-, close(252, h() - 28, 80, 20, "Close")
-#ifdef WITH_VST
-, vstText(8, 315, 324, 46)
-, vstLogo(8, 265, 324, 50)
+: gdWindow(340, 330, g_ui.langMapper.get(LangMap::ABOUT_TITLE))
#endif
{
- set_modal();
-
- std::string version = G_VERSION_STR;
#ifdef G_DEBUG_MODE
- version += " (debug build)";
+ constexpr bool debug = true;
+#else
+ constexpr bool debug = false;
#endif
- logo.image(new Fl_Pixmap(giada_logo_xpm));
- text.align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_TOP);
- text.copy_label(std::string(
- "Version " + version + " (" BUILD_DATE ")\n\n"
- "Developed by Monocasual Laboratories\n\n"
- "Released under the terms of the GNU General\n"
- "Public License (GPL v3)\n\n"
- "News, infos, contacts and documentation:\n"
- "www.giadamusic.com")
- .c_str());
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
+ {
+ geFlex* body = new geFlex(Direction::VERTICAL);
+ {
+ geBox* logo = new geBox();
+ logo->image(new Fl_Pixmap(giada_logo_xpm));
- add(logo);
- add(text);
- add(close);
+ geBox* text = new geBox();
+ text->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_TOP);
+ text->copy_label(fmt::format(g_ui.langMapper.get(LangMap::ABOUT_BODY),
+ G_VERSION_STR, debug ? "Debug" : "Release", BUILD_DATE)
+ .c_str());
#ifdef WITH_VST
+ geBox* vstLogo = new geBox();
+ vstLogo->image(new Fl_Pixmap(vstLogo_xpm));
+ vstLogo->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
- vstLogo.image(new Fl_Pixmap(vstLogo_xpm));
- vstLogo.position(vstLogo.x(), text.y() + text.h() + 8);
- vstText.label(
- "VST Plug-In Technology by Steinberg\n"
- "VST is a trademark of Steinberg\nMedia Technologies GmbH");
- vstText.position(vstText.x(), vstLogo.y() + vstLogo.h());
-
- add(vstLogo);
- add(vstText);
-
+ geBox* vstText = new geBox();
+ vstText->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_TOP);
+ vstText->label(g_ui.langMapper.get(LangMap::ABOUT_BODY_VST));
#endif
- close.callback(cb_close, (void*)this);
- u::gui::setFavicon(this);
- setId(WID_ABOUT);
- show();
-}
+ body->add(logo, 120);
+ body->add(text, 140);
+#ifdef WITH_VST
+ body->add(vstLogo, 60);
+ body->add(vstText);
+#endif
+ body->end();
+ }
-/* -------------------------------------------------------------------------- */
+ geFlex* footer = new geFlex(Direction::HORIZONTAL);
+ {
+ geButton* close = new geButton(g_ui.langMapper.get(LangMap::COMMON_CLOSE));
+ close->onClick = [this]() { do_callback(); };
+ footer->add(new geBox()); // Spacer
+ footer->add(close, 80);
+ footer->end();
+ }
-void gdAbout::cb_close(Fl_Widget* /*w*/, void* p) { ((gdAbout*)p)->cb_close(); }
+ container->add(body);
+ container->add(footer, G_GUI_UNIT);
+ container->end();
+ }
-/* -------------------------------------------------------------------------- */
+ add(container);
-void gdAbout::cb_close()
-{
- do_callback();
+ set_modal();
+ u::gui::setFavicon(this);
+ setId(WID_ABOUT);
+ show();
}
} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/dialogs/about.h b/src/gui/dialogs/about.h
index 7083d6d..0a9394d 100644
--- a/src/gui/dialogs/about.h
+++ b/src/gui/dialogs/about.h
@@ -28,8 +28,6 @@
#define GD_ABOUT_H
#include "gui/dialogs/window.h"
-#include "gui/elems/basics/box.h"
-#include "gui/elems/basics/button.h"
namespace giada::v
{
@@ -37,18 +35,6 @@ class gdAbout : public gdWindow
{
public:
gdAbout();
-
- static void cb_close(Fl_Widget* /*w*/, void* p);
- inline void cb_close();
-
-private:
- geBox logo;
- geBox text;
- geButton close;
-#ifdef WITH_VST
- geBox vstText;
- geBox vstLogo;
-#endif
};
} // namespace giada::v
diff --git a/src/gui/dialogs/actionEditor/baseActionEditor.cpp b/src/gui/dialogs/actionEditor/baseActionEditor.cpp
index 18c9051..f92529a 100644
--- a/src/gui/dialogs/actionEditor/baseActionEditor.cpp
+++ b/src/gui/dialogs/actionEditor/baseActionEditor.cpp
@@ -34,6 +34,7 @@
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/choice.h"
#include "gui/elems/basics/scrollPack.h"
+#include "gui/ui.h"
#include "src/core/actions/action.h"
#include "utils/gui.h"
#include "utils/string.h"
@@ -43,10 +44,12 @@
#include <limits>
#include <string>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdBaseActionEditor::gdBaseActionEditor(ID channelId, m::Conf::Data& conf)
-: gdWindow(conf.actionEditorX, conf.actionEditorY, conf.actionEditorW, conf.actionEditorH)
+: gdWindow(conf.actionEditorX, conf.actionEditorY, conf.actionEditorW, conf.actionEditorH, g_ui.langMapper.get(LangMap::ACTIONEDITOR_TITLE))
, channelId(channelId)
, gridTool(0, 0, conf)
, zoomInBtn(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", zoomInOff_xpm, zoomInOn_xpm)
@@ -67,9 +70,9 @@ gdBaseActionEditor::gdBaseActionEditor(ID channelId, m::Conf::Data& conf)
h() - (G_GUI_OUTER_MARGIN * 3) - 20);
zoomInBtn.callback(cb_zoomIn, this);
- zoomInBtn.copy_tooltip("Zoom in");
+ zoomInBtn.copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_ZOOMIN));
zoomOutBtn.callback(cb_zoomOut, this);
- zoomOutBtn.copy_tooltip("Zoom out");
+ zoomOutBtn.copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_ZOOMOUT));
add(m_barTop);
add(m_splitScroll);
@@ -142,15 +145,8 @@ void gdBaseActionEditor::zoomOut()
void gdBaseActionEditor::prepareWindow()
{
u::gui::setFavicon(this);
-
- std::string l = "Action Editor";
- if (m_data.channelName != "")
- l += " - " + m_data.channelName;
- copy_label(l.c_str());
-
set_non_modal();
size_range(640, 284);
-
show();
}
diff --git a/src/gui/dialogs/actionEditor/sampleActionEditor.cpp b/src/gui/dialogs/actionEditor/sampleActionEditor.cpp
index 944d4c4..a42c25e 100644
--- a/src/gui/dialogs/actionEditor/sampleActionEditor.cpp
+++ b/src/gui/dialogs/actionEditor/sampleActionEditor.cpp
@@ -24,7 +24,7 @@
*
* -------------------------------------------------------------------------- */
-#include "sampleActionEditor.h"
+#include "gui/dialogs/actionEditor/sampleActionEditor.h"
#include "core/conf.h"
#include "core/const.h"
#include "core/midiEvent.h"
@@ -32,15 +32,18 @@
#include "glue/actionEditor.h"
#include "glue/channel.h"
#include "gui/elems/basics/box.h"
+#include "gui/ui.h"
#include <string>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
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)
+, m_envelopeEditor(0, 0, g_ui.langMapper.get(LangMap::ACTIONEDITOR_VOLUME), this)
, m_actionType(0, 0, 80, G_GUI_UNIT)
{
end();
@@ -52,11 +55,11 @@ gdSampleActionEditor::gdSampleActionEditor(ID channelId, m::Conf::Data& conf)
m_barTop.add(&zoomOutBtn);
m_barTop.resizable(m_barPadding);
- m_actionType.addItem("Key press");
- m_actionType.addItem("Key release");
- m_actionType.addItem("Stop sample");
+ m_actionType.addItem(g_ui.langMapper.get(LangMap::ACTIONEDITOR_KEYPRESS));
+ m_actionType.addItem(g_ui.langMapper.get(LangMap::ACTIONEDITOR_KEYRELEASE));
+ m_actionType.addItem(g_ui.langMapper.get(LangMap::ACTIONEDITOR_STOPSAMPLE));
m_actionType.showItem(0);
- m_actionType.copy_tooltip("Action type to add");
+ m_actionType.copy_tooltip(g_ui.langMapper.get(LangMap::ACTIONEDITOR_LABEL_ACTIONTYPE));
if (!canChangeActionType())
m_actionType.deactivate();
diff --git a/src/gui/dialogs/beatsInput.cpp b/src/gui/dialogs/beatsInput.cpp
index c777498..d30f678 100644
--- a/src/gui/dialogs/beatsInput.cpp
+++ b/src/gui/dialogs/beatsInput.cpp
@@ -24,31 +24,37 @@
*
* -------------------------------------------------------------------------- */
-#include "beatsInput.h"
+#include "gui/dialogs/beatsInput.h"
#include "core/const.h"
#include "glue/main.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/check.h"
+#include "gui/elems/basics/flex.h"
#include "gui/elems/basics/input.h"
-#include "mainWindow.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <cstring>
-extern giada::v::gdMainWindow* mainWin;
+extern giada::v::Ui g_ui;
namespace giada::v
{
gdBeatsInput::gdBeatsInput(int beats, int bars)
-: gdWindow(u::gui::centerWindowX(180), u::gui::centerWindowY(36), 180, 36, "Beats")
+: gdWindow(u::gui::getCenterWinBounds(180, 36), "Beats")
{
- set_modal();
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::HORIZONTAL, G_GUI_INNER_MARGIN);
+ {
+ m_beats = new geInput(0, 0, 0, 0);
+ m_bars = new geInput(0, 0, 0, 0);
+ m_ok = new geButton(g_ui.langMapper.get(LangMap::COMMON_OK));
+ container->add(m_beats);
+ container->add(m_bars);
+ container->add(m_ok, 70);
+ container->end();
+ }
- 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");
- end();
+ add(container);
m_beats->maximum_size(2);
m_beats->value(std::to_string(beats).c_str());
@@ -59,24 +65,16 @@ gdBeatsInput::gdBeatsInput(int beats, int bars)
m_bars->type(FL_INT_INPUT);
m_ok->shortcut(FL_Enter);
- m_ok->callback(cb_update, (void*)this);
+ m_ok->onClick = [this]() {
+ if (!strcmp(m_beats->value(), "") || !strcmp(m_bars->value(), ""))
+ return;
+ c::main::setBeats(atoi(m_beats->value()), atoi(m_bars->value()));
+ do_callback();
+ };
+ set_modal();
u::gui::setFavicon(this);
setId(WID_BEATS);
show();
}
-
-/* -------------------------------------------------------------------------- */
-
-void gdBeatsInput::cb_update(Fl_Widget* /*w*/, void* p) { ((gdBeatsInput*)p)->cb_update(); }
-
-/* -------------------------------------------------------------------------- */
-
-void gdBeatsInput::cb_update()
-{
- if (!strcmp(m_beats->value(), "") || !strcmp(m_bars->value(), ""))
- return;
- c::main::setBeats(atoi(m_beats->value()), atoi(m_bars->value()));
- do_callback();
-}
} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/dialogs/beatsInput.h b/src/gui/dialogs/beatsInput.h
index 5a68724..09dfccd 100644
--- a/src/gui/dialogs/beatsInput.h
+++ b/src/gui/dialogs/beatsInput.h
@@ -30,7 +30,6 @@
#include "window.h"
class geInput;
-class geCheck;
namespace giada::v
{
@@ -41,9 +40,6 @@ public:
gdBeatsInput(int beats, int bars);
private:
- static void cb_update(Fl_Widget* /*w*/, void* p);
- void cb_update();
-
geInput* m_beats;
geInput* m_bars;
geButton* m_ok;
diff --git a/src/gui/dialogs/bpmInput.cpp b/src/gui/dialogs/bpmInput.cpp
index b84c655..56e745f 100644
--- a/src/gui/dialogs/bpmInput.cpp
+++ b/src/gui/dialogs/bpmInput.cpp
@@ -24,62 +24,60 @@
*
* -------------------------------------------------------------------------- */
-#include "bpmInput.h"
+#include "gui/dialogs/bpmInput.h"
#include "core/conf.h"
#include "core/const.h"
#include "core/mixer.h"
#include "glue/main.h"
#include "gui/elems/basics/button.h"
+#include "gui/elems/basics/flex.h"
#include "gui/elems/basics/input.h"
-#include "mainWindow.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <cstring>
-extern giada::v::gdMainWindow* mainWin;
+extern giada::v::Ui g_ui;
namespace giada::v
{
gdBpmInput::gdBpmInput(const char* label)
-: gdWindow(u::gui::centerWindowX(144), u::gui::centerWindowY(36), 144, 36, "Bpm")
+: gdWindow(u::gui::getCenterWinBounds(180, 36), "Bpm")
{
- set_modal();
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::HORIZONTAL, G_GUI_INNER_MARGIN);
+ {
+ m_input_a = new geInput(0, 0, 0, 0);
+ m_input_b = new geInput(0, 0, 0, 0);
+ m_ok = new geButton(g_ui.langMapper.get(LangMap::COMMON_OK));
+ container->add(m_input_a);
+ container->add(m_input_b);
+ container->add(m_ok, 70);
+ container->end();
+ }
- 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");
- end();
+ add(container);
std::vector<std::string> parts = u::string::split(label, ".");
- input_a->maximum_size(3);
- input_a->type(FL_INT_INPUT);
- input_a->value(parts[0].c_str());
+ m_input_a->maximum_size(3);
+ m_input_a->type(FL_INT_INPUT);
+ m_input_a->value(parts[0].c_str());
- input_b->maximum_size(1);
- input_b->type(FL_INT_INPUT);
- input_b->value(parts[1].c_str());
+ m_input_b->maximum_size(1);
+ m_input_b->type(FL_INT_INPUT);
+ m_input_b->value(parts[1].c_str());
- ok->shortcut(FL_Enter);
- ok->callback(cb_update, (void*)this);
+ m_ok->shortcut(FL_Enter);
+ m_ok->onClick = [this]() {
+ if (strcmp(m_input_a->value(), "") == 0)
+ return;
+ c::main::setBpm(m_input_a->value(), m_input_b->value());
+ do_callback();
+ };
+ set_modal();
u::gui::setFavicon(this);
setId(WID_BPM);
show();
}
-
-/* -------------------------------------------------------------------------- */
-
-void gdBpmInput::cb_update(Fl_Widget* /*w*/, void* p) { ((gdBpmInput*)p)->cb_update(); }
-
-/* -------------------------------------------------------------------------- */
-
-void gdBpmInput::cb_update()
-{
- if (strcmp(input_a->value(), "") == 0)
- return;
- c::main::setBpm(input_a->value(), input_b->value());
- do_callback();
-}
} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/dialogs/bpmInput.h b/src/gui/dialogs/bpmInput.h
index 8658e9a..34d51b9 100644
--- a/src/gui/dialogs/bpmInput.h
+++ b/src/gui/dialogs/bpmInput.h
@@ -40,12 +40,9 @@ public:
gdBpmInput(const char* label); // pointer to mainWin->timing->bpm->label()
private:
- static void cb_update(Fl_Widget* /*w*/, void* p);
- void cb_update();
-
- geInput* input_a;
- geInput* input_b;
- geButton* ok;
+ geInput* m_input_a;
+ geInput* m_input_b;
+ geButton* m_ok;
};
} // namespace giada::v
diff --git a/src/gui/dialogs/browser/browserBase.cpp b/src/gui/dialogs/browser/browserBase.cpp
index 1ed0028..9f4fb44 100644
--- a/src/gui/dialogs/browser/browserBase.cpp
+++ b/src/gui/dialogs/browser/browserBase.cpp
@@ -34,9 +34,12 @@
#include "gui/elems/basics/input.h"
#include "gui/elems/basics/progress.h"
#include "gui/elems/fileBrowser.h"
+#include "gui/ui.h"
#include "utils/fs.h"
#include "utils/gui.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdBrowserBase::gdBrowserBase(const std::string& title, const std::string& path,
@@ -50,9 +53,9 @@ gdBrowserBase::gdBrowserBase(const std::string& title, const std::string& path,
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");
+ hiddenFiles = new geCheck(groupTop->x(), groupTop->y(), 400, 20, g_ui.langMapper.get(LangMap::BROWSER_SHOWHIDDENFILES));
where = new geInput(groupTop->x(), hiddenFiles->y() + hiddenFiles->h() + 8, 20, 20);
updir = new geButton(groupTop->x() + groupTop->w() - 20, where->y(), 20, 20, "", updirOff_xpm, updirOn_xpm);
groupTop->end();
@@ -73,7 +76,7 @@ gdBrowserBase::gdBrowserBase(const std::string& title, const std::string& path,
Fl_Group* groupButtons = new Fl_Group(8, browser->y() + browser->h() + 8, w() - 16, 20);
ok = new geButton(w() - 88, groupButtons->y(), 80, 20);
- cancel = new geButton(w() - ok->w() - 96, groupButtons->y(), 80, 20, "Cancel");
+ cancel = new geButton(w() - ok->w() - 96, groupButtons->y(), 80, 20, g_ui.langMapper.get(LangMap::COMMON_CANCEL));
geBox* spacer = new geBox(8, groupButtons->y(), cancel->x() - 16, 20);
groupButtons->resizable(spacer);
groupButtons->end();
diff --git a/src/gui/dialogs/browser/browserDir.cpp b/src/gui/dialogs/browser/browserDir.cpp
index 69ea65a..1dffcb5 100644
--- a/src/gui/dialogs/browser/browserDir.cpp
+++ b/src/gui/dialogs/browser/browserDir.cpp
@@ -24,12 +24,15 @@
*
* -------------------------------------------------------------------------- */
-#include "browserDir.h"
+#include "gui/dialogs/browser/browserDir.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/input.h"
#include "gui/elems/fileBrowser.h"
+#include "gui/ui.h"
#include "utils/fs.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdBrowserDir::gdBrowserDir(const std::string& title, const std::string& path,
@@ -40,7 +43,7 @@ gdBrowserDir::gdBrowserDir(const std::string& title, const std::string& path,
browser->callback(cb_down, (void*)this);
- ok->label("Select");
+ ok->label(g_ui.langMapper.get(LangMap::COMMON_SELECT));
ok->callback(cb_load, (void*)this);
ok->shortcut(FL_ENTER);
diff --git a/src/gui/dialogs/browser/browserLoad.cpp b/src/gui/dialogs/browser/browserLoad.cpp
index 5b4d90f..237b3d9 100644
--- a/src/gui/dialogs/browser/browserLoad.cpp
+++ b/src/gui/dialogs/browser/browserLoad.cpp
@@ -24,12 +24,15 @@
*
* -------------------------------------------------------------------------- */
-#include "browserLoad.h"
+#include "gui/dialogs/browser/browserLoad.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/input.h"
#include "gui/elems/fileBrowser.h"
+#include "gui/ui.h"
#include "utils/fs.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdBrowserLoad::gdBrowserLoad(const std::string& title, const std::string& path,
@@ -40,7 +43,7 @@ gdBrowserLoad::gdBrowserLoad(const std::string& title, const std::string& path,
browser->callback(cb_down, (void*)this);
- ok->label("Load");
+ ok->label(g_ui.langMapper.get(LangMap::COMMON_LOAD));
ok->callback(cb_load, (void*)this);
ok->shortcut(FL_ENTER);
diff --git a/src/gui/dialogs/browser/browserSave.cpp b/src/gui/dialogs/browser/browserSave.cpp
index 56f18c0..207da68 100644
--- a/src/gui/dialogs/browser/browserSave.cpp
+++ b/src/gui/dialogs/browser/browserSave.cpp
@@ -24,12 +24,15 @@
*
* -------------------------------------------------------------------------- */
-#include "browserSave.h"
+#include "gui/dialogs/browser/browserSave.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/input.h"
#include "gui/elems/fileBrowser.h"
+#include "gui/ui.h"
#include "utils/fs.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdBrowserSave::gdBrowserSave(const std::string& title, const std::string& path,
@@ -45,7 +48,7 @@ gdBrowserSave::gdBrowserSave(const std::string& title, const std::string& path,
browser->callback(cb_down, (void*)this);
- ok->label("Save");
+ ok->label(g_ui.langMapper.get(LangMap::COMMON_SAVE));
ok->callback(cb_save, (void*)this);
ok->shortcut(FL_ENTER);
diff --git a/src/gui/dialogs/channelNameInput.cpp b/src/gui/dialogs/channelNameInput.cpp
index ed9ac9c..71ba778 100644
--- a/src/gui/dialogs/channelNameInput.cpp
+++ b/src/gui/dialogs/channelNameInput.cpp
@@ -24,62 +24,60 @@
*
* -------------------------------------------------------------------------- */
-#include "channelNameInput.h"
+#include "gui/dialogs/channelNameInput.h"
#include "core/conf.h"
#include "core/const.h"
#include "core/model/model.h"
#include "glue/channel.h"
#include "gui/elems/basics/button.h"
+#include "gui/elems/basics/flex.h"
#include "gui/elems/basics/input.h"
+#include "gui/ui.h"
#include "utils/gui.h"
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
gdChannelNameInput::gdChannelNameInput(const c::channel::Data& d)
-: gdWindow(u::gui::centerWindowX(400), u::gui::centerWindowY(64), 400, 64, "New channel name")
+: gdWindow(u::gui::getCenterWinBounds(400, 64), g_ui.langMapper.get(LangMap::CHANNELNAME_TITLE))
, m_data(d)
{
- set_modal();
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
+ {
+ m_name = new geInput(0, 0, 0, 0);
+
+ geFlex* footer = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
+ {
+ m_ok = new geButton(g_ui.langMapper.get(LangMap::COMMON_OK));
+ m_cancel = new geButton(g_ui.langMapper.get(LangMap::COMMON_CANCEL));
+ footer->add(new geBox());
+ footer->add(m_cancel, 70);
+ footer->add(m_ok, 70);
+ footer->end();
+ }
+ container->add(m_name, G_GUI_UNIT);
+ container->add(footer, G_GUI_UNIT);
+ container->end();
+ }
- 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");
- end();
+ add(container);
m_name->value(m_data.name.c_str());
m_ok->shortcut(FL_Enter);
- m_ok->callback(cb_update, (void*)this);
+ m_ok->onClick = [this]() {
+ c::channel::setName(m_data.id, m_name->value());
+ do_callback();
+ };
- m_cancel->callback(cb_cancel, (void*)this);
+ m_cancel->onClick = [this]() {
+ do_callback();
+ };
+ set_modal();
u::gui::setFavicon(this);
setId(WID_SAMPLE_NAME);
show();
}
-
-/* -------------------------------------------------------------------------- */
-
-void gdChannelNameInput::cb_update(Fl_Widget* /*w*/, void* p) { ((gdChannelNameInput*)p)->cb_update(); }
-void gdChannelNameInput::cb_cancel(Fl_Widget* /*w*/, void* p) { ((gdChannelNameInput*)p)->cb_cancel(); }
-
-/* -------------------------------------------------------------------------- */
-
-void gdChannelNameInput::cb_cancel()
-{
- do_callback();
-}
-
-/* -------------------------------------------------------------------------- */
-
-void gdChannelNameInput::cb_update()
-{
- c::channel::setName(m_data.id, m_name->value());
- do_callback();
-}
-
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/dialogs/channelNameInput.h b/src/gui/dialogs/channelNameInput.h
index c9286ae..44e86df 100644
--- a/src/gui/dialogs/channelNameInput.h
+++ b/src/gui/dialogs/channelNameInput.h
@@ -45,11 +45,6 @@ public:
gdChannelNameInput(const c::channel::Data& d);
private:
- static void cb_update(Fl_Widget* /*w*/, void* p);
- static void cb_cancel(Fl_Widget* /*w*/, void* p);
- void cb_update();
- void cb_cancel();
-
const c::channel::Data& m_data;
geInput* m_name;
diff --git a/src/gui/dialogs/config.cpp b/src/gui/dialogs/config.cpp
index 29048a8..75eee81 100644
--- a/src/gui/dialogs/config.cpp
+++ b/src/gui/dialogs/config.cpp
@@ -38,12 +38,15 @@
#include "gui/elems/config/tabMidi.h"
#include "gui/elems/config/tabMisc.h"
#include "gui/elems/config/tabPlugins.h"
+#include "gui/ui.h"
#include "utils/gui.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdConfig::gdConfig(int w, int h, m::Conf::Data& conf)
-: gdWindow(u::gui::getCenterWinBounds(w, h), "Configuration")
+: gdWindow(u::gui::getCenterWinBounds(w, h), g_ui.langMapper.get(LangMap::CONFIG_TITLE))
{
const geompp::Rect<int> bounds = getContentBounds().reduced(G_GUI_OUTER_MARGIN);
@@ -71,8 +74,8 @@ gdConfig::gdConfig(int w, int h, m::Conf::Data& conf)
geFlex* footer = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- geButton* save = new geButton("Save");
- geButton* cancel = new geButton("Cancel");
+ geButton* save = new geButton(g_ui.langMapper.get(LangMap::COMMON_SAVE));
+ geButton* cancel = new geButton(g_ui.langMapper.get(LangMap::COMMON_CANCEL));
save->onClick = [this]() { saveConfig(); };
cancel->onClick = [this]() { do_callback(); };
diff --git a/src/gui/dialogs/keyGrabber.cpp b/src/gui/dialogs/keyGrabber.cpp
index 51fae3c..4c87186 100644
--- a/src/gui/dialogs/keyGrabber.cpp
+++ b/src/gui/dialogs/keyGrabber.cpp
@@ -31,15 +31,18 @@
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/flex.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/log.h"
#include "utils/string.h"
#include <cassert>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdKeyGrabber::gdKeyGrabber(int key)
-: gdWindow(300, 126, "Key configuration")
+: gdWindow(300, 126, g_ui.langMapper.get(LangMap::KEYGRABBER_TITLE))
, onSetKey(nullptr)
, m_key(key)
{
@@ -49,8 +52,8 @@ gdKeyGrabber::gdKeyGrabber(int key)
geFlex* footer = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- m_clear = new geButton("Clear");
- m_cancel = new geButton("Close");
+ m_clear = new geButton(g_ui.langMapper.get(LangMap::COMMON_CLEAR));
+ m_cancel = new geButton(g_ui.langMapper.get(LangMap::COMMON_CLOSE));
footer->add(new geBox()); // Spacer
footer->add(m_clear, 80);
@@ -88,7 +91,7 @@ gdKeyGrabber::gdKeyGrabber(int key)
void gdKeyGrabber::rebuild()
{
- std::string tmp = "Press a key.\n\nCurrent binding: " + u::gui::keyToString(m_key);
+ std::string tmp = g_ui.langMapper.get(LangMap::KEYGRABBER_BODY) + u::gui::keyToString(m_key);
m_text->copy_label(tmp.c_str());
}
diff --git a/src/gui/dialogs/mainWindow.cpp b/src/gui/dialogs/mainWindow.cpp
index c0c6582..603903e 100644
--- a/src/gui/dialogs/mainWindow.cpp
+++ b/src/gui/dialogs/mainWindow.cpp
@@ -87,45 +87,44 @@ gdMainWindow::gdMainWindow(int W, int H, const char* title, int argc, char** arg
Fl_Tooltip::size(G_GUI_FONT_SIZE_BASE);
Fl_Tooltip::enable(m_conf.showTooltips);
- size_range(G_MIN_GUI_WIDTH, G_MIN_GUI_HEIGHT);
-
- 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);
- keyboard = new v::geKeyboard(8, 122, w() - 16, 380);
-
- /* zone 1 - menus, and I/O tools */
-
- 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 */
-
- Fl_Group* zone2 = new Fl_Group(8, mainTransport->y(), W - 16, mainTransport->h());
- zone2->add(mainTransport);
- zone2->resizable(new Fl_Box(mainTransport->x() + mainTransport->w() + 4, zone2->y(), 80, 20));
- zone2->add(mainTimer);
-
- /* zone 3 - beat meter */
-
- Fl_Group* zone3 = new Fl_Group(8, sequencer->y(), W - 16, sequencer->h());
- zone3->add(sequencer);
-
- /* zone 4 - the keyboard (Fl_Group is unnecessary here, keyboard is
- * a group by itself) */
-
- resizable(keyboard);
-
- add(zone1);
- add(zone2);
- add(zone3);
- add(keyboard);
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
+ {
+ /* zone 1 - menus, and I/O tools */
+
+ geFlex* zone1 = new geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN);
+ {
+ mainMenu = new v::geMainMenu();
+ mainIO = new v::geMainIO();
+ zone1->add(mainMenu, 350);
+ zone1->add(new geBox());
+ zone1->add(mainIO, 430);
+ zone1->end();
+ }
+
+ /* zone 2 - mainTransport and timing tools */
+
+ geFlex* zone2 = new geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN);
+ {
+ mainTransport = new v::geMainTransport();
+ mainTimer = new v::geMainTimer();
+ zone2->add(mainTransport, 400);
+ zone2->add(new geBox());
+ zone2->add(mainTimer, 237, {2, 0, 3, 0});
+ zone2->end();
+ }
+
+ sequencer = new v::geSequencer();
+ keyboard = new v::geKeyboard();
+
+ container->add(zone1, G_GUI_UNIT);
+ container->add(zone2, 30, {5, 0, 0, 0});
+ container->add(sequencer, 40, {4, 80, 4, 80});
+ container->add(keyboard);
+ container->end();
+ }
+
+ add(container);
+ resizable(container);
callback([](Fl_Widget* /*w*/, void* /*v*/) {
if (Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape)
@@ -134,6 +133,7 @@ gdMainWindow::gdMainWindow(int W, int H, const char* title, int argc, char** arg
});
u::gui::setFavicon(this);
+ size_range(G_MIN_GUI_WIDTH, G_MIN_GUI_HEIGHT);
refresh();
show(argc, argv);
diff --git a/src/gui/dialogs/midiIO/midiInputChannel.cpp b/src/gui/dialogs/midiIO/midiInputChannel.cpp
index b41afff..77c099e 100644
--- a/src/gui/dialogs/midiIO/midiInputChannel.cpp
+++ b/src/gui/dialogs/midiIO/midiInputChannel.cpp
@@ -24,16 +24,9 @@
*
* -------------------------------------------------------------------------- */
+#include "gui/dialogs/midiIO/midiInputChannel.h"
#include "core/conf.h"
#include "core/const.h"
-#include "utils/gui.h"
-#include "utils/log.h"
-#include <FL/Fl_Pack.H>
-#include <cassert>
-#include <cstddef>
-#ifdef WITH_VST
-#include "core/plugins/plugin.h"
-#endif
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/check.h"
@@ -42,26 +35,36 @@
#include "gui/elems/basics/scrollPack.h"
#include "gui/elems/midiIO/midiLearner.h"
#include "gui/elems/midiIO/midiLearnerPack.h"
-#include "midiInputChannel.h"
+#include "gui/ui.h"
+#include "utils/gui.h"
+#include "utils/log.h"
#include "utils/string.h"
+#include <FL/Fl_Pack.H>
+#include <cassert>
+#include <cstddef>
+#ifdef WITH_VST
+#include "core/plugins/plugin.h"
+#endif
+
+extern giada::v::Ui g_ui;
namespace giada::v
{
geChannelLearnerPack::geChannelLearnerPack(int x, int y, const c::io::Channel_InputData& channel)
-: geMidiLearnerPack(x, y, "Channel")
+: geMidiLearnerPack(x, y, g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_CHANNEL))
{
setCallbacks(
[channelId = channel.channelId](int param) { c::io::channel_startMidiLearn(param, channelId); },
[channelId = channel.channelId](int param) { c::io::channel_clearMidiLearn(param, channelId); });
- 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);
- addMidiLearner("mute", G_MIDI_IN_MUTE);
- addMidiLearner("solo", G_MIDI_IN_SOLO);
- addMidiLearner("volume", G_MIDI_IN_VOLUME);
- addMidiLearner("pitch", G_MIDI_IN_PITCH, /*visible=*/channel.channelType == ChannelType::SAMPLE);
- addMidiLearner("read actions", G_MIDI_IN_READ_ACTIONS, /*visible=*/channel.channelType == ChannelType::SAMPLE);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_KEYPRESS), G_MIDI_IN_KEYPRESS);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_KEYREL), G_MIDI_IN_KEYREL);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_KEYKILL), G_MIDI_IN_KILL);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_ARM), G_MIDI_IN_ARM);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_MUTE), G_MIDI_IN_MUTE);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_SOLO), G_MIDI_IN_SOLO);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_VOLUME), G_MIDI_IN_VOLUME);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_PITCH), G_MIDI_IN_PITCH, /*visible=*/channel.channelType == ChannelType::SAMPLE);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_LEARN_READACTIONS), G_MIDI_IN_READ_ACTIONS, /*visible=*/channel.channelType == ChannelType::SAMPLE);
}
/* -------------------------------------------------------------------------- */
@@ -114,21 +117,19 @@ void gePluginLearnerPack::update(const c::io::PluginData& d, bool enabled)
/* -------------------------------------------------------------------------- */
gdMidiInputChannel::gdMidiInputChannel(ID channelId, m::Conf::Data& c)
-: gdMidiInputBase(c.midiInputX, c.midiInputY, c.midiInputW, c.midiInputH, "", c)
+: gdMidiInputBase(c.midiInputX, c.midiInputY, c.midiInputW, c.midiInputH, g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_TITLE), c)
, m_channelId(channelId)
, m_data(c::io::channel_getInputData(channelId))
{
end();
- copy_label(std::string("MIDI Input Setup (channel " + std::to_string(channelId) + ")").c_str());
-
/* Header */
geGroup* groupHeader = new geGroup(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN);
- m_enable = new geCheck(0, 0, 120, G_GUI_UNIT, "Enable MIDI input");
+ m_enable = new geCheck(0, 0, 120, G_GUI_UNIT, g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_ENABLE));
m_channel = new geChoice(m_enable->x() + m_enable->w() + 44, 0, 120, G_GUI_UNIT);
m_veloAsVol = new geCheck(0, m_enable->y() + m_enable->h() + G_GUI_OUTER_MARGIN, w() - 16, G_GUI_UNIT,
- "Velocity drives volume (Sample Channels)");
+ g_ui.langMapper.get(LangMap::MIDIINPUT_CHANNEL_VELOCITYDRIVESVOL));
groupHeader->add(m_enable);
groupHeader->add(m_channel);
groupHeader->add(m_veloAsVol);
@@ -148,7 +149,7 @@ gdMidiInputChannel::gdMidiInputChannel(ID channelId, m::Conf::Data& c)
geGroup* groupButtons = new geGroup(G_GUI_OUTER_MARGIN, m_container->y() + m_container->h() + G_GUI_OUTER_MARGIN);
geBox* spacer = new geBox(0, 0, w() - 80, G_GUI_UNIT); // spacer window border <-> buttons
- m_ok = new geButton(w() - 96, 0, 80, G_GUI_UNIT, "Close");
+ m_ok = new geButton(w() - 96, 0, 80, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_CLOSE));
groupButtons->add(spacer);
groupButtons->add(m_ok);
groupButtons->resizable(spacer);
diff --git a/src/gui/dialogs/midiIO/midiInputMaster.cpp b/src/gui/dialogs/midiIO/midiInputMaster.cpp
index 2a79e12..fad4329 100644
--- a/src/gui/dialogs/midiIO/midiInputMaster.cpp
+++ b/src/gui/dialogs/midiIO/midiInputMaster.cpp
@@ -24,7 +24,7 @@
*
* -------------------------------------------------------------------------- */
-#include "midiInputMaster.h"
+#include "gui/dialogs/midiIO/midiInputMaster.h"
#include "core/conf.h"
#include "core/const.h"
#include "gui/elems/basics/button.h"
@@ -33,8 +33,10 @@
#include "gui/elems/basics/group.h"
#include "gui/elems/basics/scrollPack.h"
#include "gui/elems/midiIO/midiLearner.h"
+#include "gui/ui.h"
#include "utils/gui.h"
-#include <FL/Fl_Pack.H>
+
+extern giada::v::Ui g_ui;
namespace giada::v
{
@@ -44,15 +46,15 @@ geMasterLearnerPack::geMasterLearnerPack(int x, int y)
setCallbacks(
[](int param) { c::io::master_startMidiLearn(param); },
[](int param) { c::io::master_clearMidiLearn(param); });
- addMidiLearner("rewind", G_MIDI_IN_REWIND);
- addMidiLearner("play/stop", G_MIDI_IN_START_STOP);
- addMidiLearner("action recording", G_MIDI_IN_ACTION_REC);
- addMidiLearner("input recording", G_MIDI_IN_INPUT_REC);
- addMidiLearner("metronome", G_MIDI_IN_METRONOME);
- addMidiLearner("input volume", G_MIDI_IN_VOLUME_IN);
- addMidiLearner("output volume", G_MIDI_IN_VOLUME_OUT);
- addMidiLearner("sequencer ×2", G_MIDI_IN_BEAT_DOUBLE);
- addMidiLearner("sequencer ÷2", G_MIDI_IN_BEAT_HALF);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_REWIND), G_MIDI_IN_REWIND);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_PLAYSTOP), G_MIDI_IN_START_STOP);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_ACTIONREC), G_MIDI_IN_ACTION_REC);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_INPUTREC), G_MIDI_IN_INPUT_REC);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_METRONOME), G_MIDI_IN_METRONOME);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_INVOLUME), G_MIDI_IN_VOLUME_IN);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_OUTVOLUME), G_MIDI_IN_VOLUME_OUT);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_SEQDOUBLE), G_MIDI_IN_BEAT_DOUBLE);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_LEARN_SEQHALF), G_MIDI_IN_BEAT_HALF);
}
/* -------------------------------------------------------------------------- */
@@ -76,19 +78,19 @@ void geMasterLearnerPack::update(const c::io::Master_InputData& d)
/* -------------------------------------------------------------------------- */
gdMidiInputMaster::gdMidiInputMaster(m::Conf::Data& c)
-: gdMidiInputBase(c.midiInputX, c.midiInputY, 300, 284, "MIDI Input Setup (global)", c)
+: gdMidiInputBase(c.midiInputX, c.midiInputY, 300, 284, g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_TITLE), c)
{
end();
geGroup* groupHeader = new geGroup(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN);
- m_enable = new geCheck(0, 0, 120, G_GUI_UNIT, "Enable MIDI input");
+ m_enable = new geCheck(0, 0, 120, G_GUI_UNIT, g_ui.langMapper.get(LangMap::MIDIINPUT_MASTER_ENABLE));
m_channel = new geChoice(m_enable->x() + m_enable->w() + 44, 0, 120, G_GUI_UNIT);
groupHeader->resizable(nullptr);
groupHeader->add(m_enable);
groupHeader->add(m_channel);
m_learners = new geMasterLearnerPack(G_GUI_OUTER_MARGIN, groupHeader->y() + groupHeader->h() + G_GUI_OUTER_MARGIN);
- m_ok = new geButton(w() - 88, m_learners->y() + m_learners->h() + G_GUI_OUTER_MARGIN, 80, G_GUI_UNIT, "Close");
+ m_ok = new geButton(w() - 88, m_learners->y() + m_learners->h() + G_GUI_OUTER_MARGIN, 80, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_CLOSE));
add(groupHeader);
add(m_learners);
diff --git a/src/gui/dialogs/midiIO/midiOutputBase.cpp b/src/gui/dialogs/midiIO/midiOutputBase.cpp
index 7635ab9..0eba87f 100644
--- a/src/gui/dialogs/midiIO/midiOutputBase.cpp
+++ b/src/gui/dialogs/midiIO/midiOutputBase.cpp
@@ -24,14 +24,15 @@
*
* -------------------------------------------------------------------------- */
-#include "midiOutputBase.h"
+#include "gui/dialogs/midiIO/midiOutputBase.h"
#include "glue/io.h"
#include "gui/elems/basics/check.h"
#include "gui/elems/midiIO/midiLearner.h"
+#include "gui/ui.h"
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
geLightningLearnerPack::geLightningLearnerPack(int x, int y, ID channelId)
: geMidiLearnerPack(x, y)
@@ -39,9 +40,9 @@ geLightningLearnerPack::geLightningLearnerPack(int x, int y, ID channelId)
setCallbacks(
[channelId](int param) { c::io::channel_startMidiLearn(param, channelId); },
[channelId](int param) { c::io::channel_clearMidiLearn(param, channelId); });
- addMidiLearner("playing", G_MIDI_OUT_L_PLAYING);
- addMidiLearner("mute", G_MIDI_OUT_L_MUTE);
- addMidiLearner("solo", G_MIDI_OUT_L_SOLO);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_LEARN_PLAYING), G_MIDI_OUT_L_PLAYING);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_LEARN_MUTE), G_MIDI_OUT_L_MUTE);
+ addMidiLearner(g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_LEARN_SOLO), G_MIDI_OUT_L_SOLO);
}
/* -------------------------------------------------------------------------- */
@@ -59,7 +60,7 @@ void geLightningLearnerPack::update(const c::io::Channel_OutputData& d)
/* -------------------------------------------------------------------------- */
gdMidiOutputBase::gdMidiOutputBase(int w, int h, ID channelId)
-: gdWindow(w, h, "Midi Output Setup")
+: gdWindow(w, h, g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_TITLE))
, m_channelId(channelId)
{
}
@@ -89,13 +90,4 @@ void gdMidiOutputBase::cb_enableLightning()
{
c::io::channel_enableMidiLightning(m_channelId, m_enableLightning->value());
}
-
-/* -------------------------------------------------------------------------- */
-
-void gdMidiOutputBase::setTitle(ID channelId)
-{
- std::string tmp = "MIDI Output Setup (channel " + std::to_string(channelId) + ")";
- copy_label(tmp.c_str());
-}
-} // namespace v
-} // namespace giada
+} // namespace giada::v
diff --git a/src/gui/dialogs/midiIO/midiOutputBase.h b/src/gui/dialogs/midiIO/midiOutputBase.h
index 28b9e8f..aea7420 100644
--- a/src/gui/dialogs/midiIO/midiOutputBase.h
+++ b/src/gui/dialogs/midiIO/midiOutputBase.h
@@ -73,11 +73,6 @@ protected:
static void cb_enableLightning(Fl_Widget* /*w*/, void* p);
void cb_enableLightning();
- /* setTitle
- * set window title. */
-
- void setTitle(ID channelId);
-
ID m_channelId;
c::io::Channel_OutputData m_data;
diff --git a/src/gui/dialogs/midiIO/midiOutputMidiCh.cpp b/src/gui/dialogs/midiIO/midiOutputMidiCh.cpp
index ca31890..977274d 100644
--- a/src/gui/dialogs/midiIO/midiOutputMidiCh.cpp
+++ b/src/gui/dialogs/midiIO/midiOutputMidiCh.cpp
@@ -24,33 +24,36 @@
*
* -------------------------------------------------------------------------- */
-#include "midiOutputMidiCh.h"
+#include "gui/dialogs/midiIO/midiOutputMidiCh.h"
#include "glue/io.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/check.h"
#include "gui/elems/basics/choice.h"
#include "gui/elems/midiIO/midiLearner.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include <FL/Fl_Pack.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdMidiOutputMidiCh::gdMidiOutputMidiCh(ID channelId)
: gdMidiOutputBase(300, 168, channelId)
{
end();
- setTitle(m_channelId + 1);
- m_enableOut = new geCheck(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, 150, G_GUI_UNIT, "Enable MIDI output");
+ m_enableOut = new geCheck(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, 150, G_GUI_UNIT, g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_ENABLE));
m_chanListOut = new geChoice(w() - 108, G_GUI_OUTER_MARGIN, 100, G_GUI_UNIT);
m_enableLightning = new geCheck(G_GUI_OUTER_MARGIN, m_chanListOut->y() + m_chanListOut->h() + G_GUI_OUTER_MARGIN,
- 120, G_GUI_UNIT, "Enable MIDI lightning output");
+ 120, G_GUI_UNIT, g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_ENABLE_LIGHTNING));
m_learners = new geLightningLearnerPack(G_GUI_OUTER_MARGIN,
m_enableLightning->y() + m_enableLightning->h() + G_GUI_OUTER_MARGIN, channelId);
- m_close = new geButton(w() - 88, m_learners->y() + m_learners->h() + G_GUI_OUTER_MARGIN, 80, G_GUI_UNIT, "Close");
+ m_close = new geButton(w() - 88, m_learners->y() + m_learners->h() + G_GUI_OUTER_MARGIN, 80, G_GUI_UNIT,
+ g_ui.langMapper.get(LangMap::COMMON_CLOSE));
add(m_enableOut);
add(m_chanListOut);
diff --git a/src/gui/dialogs/midiIO/midiOutputSampleCh.cpp b/src/gui/dialogs/midiIO/midiOutputSampleCh.cpp
index 0c0fde3..9ce092b 100644
--- a/src/gui/dialogs/midiIO/midiOutputSampleCh.cpp
+++ b/src/gui/dialogs/midiIO/midiOutputSampleCh.cpp
@@ -24,30 +24,31 @@
*
* -------------------------------------------------------------------------- */
-#include "midiOutputSampleCh.h"
+#include "gui/dialogs/midiIO/midiOutputSampleCh.h"
#include "core/model/model.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/check.h"
#include "gui/elems/midiIO/midiLearner.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include <FL/Fl_Pack.H>
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
gdMidiOutputSampleCh::gdMidiOutputSampleCh(ID channelId)
: gdMidiOutputBase(300, 140, channelId)
{
end();
- setTitle(m_channelId);
- m_enableLightning = new geCheck(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, 120, 20, "Enable MIDI lightning output");
+ m_enableLightning = new geCheck(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, 120, 20, g_ui.langMapper.get(LangMap::MIDIOUTPUT_CHANNEL_ENABLE_LIGHTNING));
m_learners = new geLightningLearnerPack(G_GUI_OUTER_MARGIN,
m_enableLightning->y() + m_enableLightning->h() + 8, channelId);
- m_close = new geButton(w() - 88, m_learners->y() + m_learners->h() + 8, 80, 20, "Close");
+ m_close = new geButton(w() - 88, m_learners->y() + m_learners->h() + 8, 80, 20,
+ g_ui.langMapper.get(LangMap::COMMON_CLOSE));
add(m_enableLightning);
add(m_learners);
@@ -72,5 +73,4 @@ void gdMidiOutputSampleCh::rebuild()
m_enableLightning->value(m_data.lightningEnabled);
m_learners->update(m_data);
}
-} // namespace v
-} // namespace giada
+} // namespace giada::v
diff --git a/src/gui/dialogs/missingAssets.cpp b/src/gui/dialogs/missingAssets.cpp
index 03b897f..e2d10b4 100644
--- a/src/gui/dialogs/missingAssets.cpp
+++ b/src/gui/dialogs/missingAssets.cpp
@@ -30,19 +30,22 @@
#include "gui/elems/basics/browser.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/flex.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include <FL/Fl_Group.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdMissingAssets::gdMissingAssets(const m::LoadState& state)
-: gdWindow(u::gui::getCenterWinBounds(400, 300), "Warning")
+: gdWindow(u::gui::getCenterWinBounds(400, 300), g_ui.langMapper.get(LangMap::COMMON_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);
+ geBox* textIntro = new geBox(g_ui.langMapper.get(LangMap::MISSINGASSETS_INTRO), FL_ALIGN_LEFT);
textIntro->color(G_COLOR_BLUE);
body->add(textIntro, G_GUI_UNIT);
@@ -52,7 +55,7 @@ gdMissingAssets::gdMissingAssets(const m::LoadState& state)
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(new geBox(g_ui.langMapper.get(LangMap::MISSINGASSETS_AUDIOFILES), FL_ALIGN_LEFT), G_GUI_UNIT);
body->add(waves);
}
@@ -61,7 +64,7 @@ gdMissingAssets::gdMissingAssets(const m::LoadState& state)
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(new geBox(g_ui.langMapper.get(LangMap::MISSINGASSETS_PLUGINS), FL_ALIGN_LEFT), G_GUI_UNIT);
body->add(plugins);
}
body->end();
@@ -69,7 +72,7 @@ gdMissingAssets::gdMissingAssets(const m::LoadState& state)
geFlex* footer = new geFlex(Direction::HORIZONTAL);
{
- geButton* close = new geButton("Close");
+ geButton* close = new geButton(g_ui.langMapper.get(LangMap::COMMON_CLOSE));
close->onClick = [this]() { do_callback(); };
footer->add(new geBox()); // Spacer
footer->add(close, 80);
diff --git a/src/gui/dialogs/pluginChooser.cpp b/src/gui/dialogs/pluginChooser.cpp
index 1f06e17..3ded71c 100644
--- a/src/gui/dialogs/pluginChooser.cpp
+++ b/src/gui/dialogs/pluginChooser.cpp
@@ -32,42 +32,55 @@
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/choice.h"
+#include "gui/elems/basics/flex.h"
#include "gui/elems/plugin/pluginBrowser.h"
+#include "gui/ui.h"
#include "utils/gui.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdPluginChooser::gdPluginChooser(int X, int Y, int W, int H, ID channelId, m::Conf::Data& c)
-: gdWindow(X, Y, W, H, "Available plugins")
+: gdWindow(X, Y, W, H, g_ui.langMapper.get(LangMap::PLUGINCHOOSER_TITLE))
, 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(), group_top->y(), 180, 20, "Sort by", 0);
- geBox* b1 = new geBox(sortMethod->x() + sortMethod->w(), group_top->y(), 100, 20); // spacer window border <-> menu
- group_top->resizable(b1);
- group_top->end();
-
- /* center browser */
- browser = new v::gePluginBrowser(8, 36, w() - 16, h() - 70);
-
- /* ok/cancel buttons */
- Fl_Group* group_btn = new Fl_Group(8, browser->y() + browser->h() + 8, w() - 16, h() - browser->h() - 16);
- geBox* b2 = new geBox(8, browser->y() + browser->h(), 100, 20); // spacer window border <-> buttons
- addBtn = new geButton(w() - 88, group_btn->y(), 80, 20, "Add");
- cancelBtn = new geButton(addBtn->x() - 88, group_btn->y(), 80, 20, "Cancel");
- group_btn->resizable(b2);
- group_btn->end();
-
- end();
-
- sortMethod->addItem("Name");
- sortMethod->addItem("Category");
- sortMethod->addItem("Manufacturer");
- sortMethod->addItem("Format");
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
+ {
+ geFlex* header = new geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN);
+ {
+ sortMethod = new geChoice(g_ui.langMapper.get(LangMap::PLUGINCHOOSER_SORTBY), 0);
+ header->add(sortMethod, 180);
+ header->add(new geBox());
+ header->end();
+ }
+
+ browser = new v::gePluginBrowser(0, 0, 0, 0);
+
+ geFlex* footer = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
+ {
+ addBtn = new geButton(g_ui.langMapper.get(LangMap::COMMON_ADD));
+ cancelBtn = new geButton(g_ui.langMapper.get(LangMap::COMMON_CANCEL));
+ footer->add(new geBox());
+ footer->add(cancelBtn, 80);
+ footer->add(addBtn, 80);
+ footer->end();
+ }
+
+ container->add(header, G_GUI_UNIT);
+ container->add(browser);
+ container->add(footer, G_GUI_UNIT);
+ container->end();
+ }
+
+ add(container);
+ resizable(container);
+
+ sortMethod->addItem(g_ui.langMapper.get(LangMap::PLUGINCHOOSER_SORTBY_NAME));
+ sortMethod->addItem(g_ui.langMapper.get(LangMap::PLUGINCHOOSER_SORTBY_CATEGORY));
+ sortMethod->addItem(g_ui.langMapper.get(LangMap::PLUGINCHOOSER_SORTBY_MANIFACTURER));
+ sortMethod->addItem(g_ui.langMapper.get(LangMap::PLUGINCHOOSER_SORTBY_FORMAT));
sortMethod->showItem(m_conf.pluginSortMethod);
sortMethod->onChange = [this](ID id) {
c::plugin::sortPlugins(static_cast<m::PluginManager::SortMethod>(id));
@@ -78,7 +91,6 @@ gdPluginChooser::gdPluginChooser(int X, int Y, int W, int H, ID channelId, m::Co
addBtn->shortcut(FL_Enter);
cancelBtn->callback(cb_close, (void*)this);
- resizable(browser);
u::gui::setFavicon(this);
show();
}
diff --git a/src/gui/dialogs/pluginList.cpp b/src/gui/dialogs/pluginList.cpp
index 02fee22..f1cbdd0 100644
--- a/src/gui/dialogs/pluginList.cpp
+++ b/src/gui/dialogs/pluginList.cpp
@@ -37,11 +37,14 @@
#include "gui/elems/mainWindow/keyboard/channel.h"
#include "gui/elems/mainWindow/mainIO.h"
#include "gui/elems/plugin/pluginElement.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <cassert>
#include <string>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdPluginList::gdPluginList(ID channelId, m::Conf::Data& c)
@@ -83,14 +86,11 @@ void gdPluginList::rebuild()
m_plugins = c::plugin::getPlugins(m_channelId);
if (m_plugins.channelId == m::Mixer::MASTER_OUT_CHANNEL_ID)
- label("Master Out Plug-ins");
+ label(g_ui.langMapper.get(LangMap::PLUGINLIST_TITLE_MASTEROUT));
else if (m_plugins.channelId == m::Mixer::MASTER_IN_CHANNEL_ID)
- label("Master In Plug-ins");
+ label(g_ui.langMapper.get(LangMap::PLUGINLIST_TITLE_MASTERIN));
else
- {
- std::string l = "Channel " + u::string::iToString(m_plugins.channelId) + " Plug-ins";
- copy_label(l.c_str());
- }
+ label(g_ui.langMapper.get(LangMap::PLUGINLIST_TITLE_CHANNEL));
/* Clear the previous list. */
@@ -100,7 +100,7 @@ void gdPluginList::rebuild()
for (m::Plugin* plugin : m_plugins.plugins)
list->addWidget(new gePluginElement(0, 0, c::plugin::getPlugin(*plugin, m_plugins.channelId)));
- addPlugin = list->addWidget(new geButton(0, 0, 0, G_GUI_UNIT, "-- add new plugin --"));
+ addPlugin = list->addWidget(new geButton(0, 0, 0, G_GUI_UNIT, g_ui.langMapper.get(LangMap::PLUGINLIST_ADDPLUGIN)));
addPlugin->callback(cb_addPlugin, (void*)this);
}
diff --git a/src/gui/dialogs/sampleEditor.cpp b/src/gui/dialogs/sampleEditor.cpp
index 194748f..562237f 100644
--- a/src/gui/dialogs/sampleEditor.cpp
+++ b/src/gui/dialogs/sampleEditor.cpp
@@ -43,7 +43,6 @@
#include "gui/elems/basics/pack.h"
#include "gui/elems/basics/statusButton.h"
#include "gui/elems/mainWindow/keyboard/channel.h"
-#include "gui/elems/sampleEditor/boostTool.h"
#include "gui/elems/sampleEditor/panTool.h"
#include "gui/elems/sampleEditor/pitchTool.h"
#include "gui/elems/sampleEditor/rangeTool.h"
@@ -51,6 +50,7 @@
#include "gui/elems/sampleEditor/volumeTool.h"
#include "gui/elems/sampleEditor/waveTools.h"
#include "gui/elems/sampleEditor/waveform.h"
+#include "gui/ui.h"
#include "sampleEditor.h"
#include "utils/gui.h"
#include "utils/string.h"
@@ -58,16 +58,19 @@
#include <FL/Fl_Group.H>
#include <cassert>
#include <cmath>
+#include <fmt/core.h>
#ifdef G_OS_WINDOWS
#undef IN
#undef OUT
#endif
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gdSampleEditor::gdSampleEditor(ID channelId, m::Conf::Data& c)
-: gdWindow(c.sampleEditorX, c.sampleEditorY, c.sampleEditorW, c.sampleEditorH)
+: gdWindow(c.sampleEditorX, c.sampleEditorY, c.sampleEditorW, c.sampleEditorH, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TITLE))
, m_channelId(channelId)
, m_conf(c)
{
@@ -116,8 +119,6 @@ void gdSampleEditor::rebuild()
{
m_data = c::sampleEditor::getData(m_channelId);
- copy_label(m_data.name.c_str());
-
waveTools->rebuild(m_data);
volumeTool->rebuild(m_data);
panTool->rebuild(m_data);
@@ -143,16 +144,16 @@ void gdSampleEditor::refresh()
gePack* gdSampleEditor::createUpperBar()
{
- reload = new geButton(0, 0, 70, G_GUI_UNIT, "Reload");
+ reload = new geButton(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_RELOAD));
grid = new geChoice(0, 0, 50, G_GUI_UNIT);
- snap = new geCheck(0, 0, 12, G_GUI_UNIT, "Snap");
+ snap = new geCheck(0, 0, 12, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_SNAPTOGRID));
sep1 = new geBox(0, 0, w() - 208, G_GUI_UNIT);
zoomOut = new geButton(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", zoomOutOff_xpm, zoomOutOn_xpm);
zoomIn = new geButton(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", zoomInOff_xpm, zoomInOn_xpm);
reload->callback(cb_reload, (void*)this);
- grid->addItem("(off)");
+ grid->addItem("1");
grid->addItem("2");
grid->addItem("3");
grid->addItem("4");
@@ -161,22 +162,22 @@ gePack* gdSampleEditor::createUpperBar()
grid->addItem("16");
grid->addItem("32");
grid->addItem("64");
- grid->copy_tooltip("Grid frequency");
+ grid->copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_GRIDRES));
grid->showItem(m_conf.sampleEditorGridVal);
grid->onChange = [this](ID) {
waveTools->waveform->setGridLevel(std::stoi(grid->getSelectedLabel()));
};
snap->value(m_conf.sampleEditorGridOn);
- snap->copy_tooltip("Snap to grid");
+ snap->copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_SNAPTOGRID));
snap->callback(cb_enableSnap, (void*)this);
/* TODO - redraw grid if != (off) */
zoomOut->callback(cb_zoomOut, (void*)this);
- zoomOut->copy_tooltip("Zoom out");
+ zoomOut->copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_ZOOMOUT));
zoomIn->callback(cb_zoomIn, (void*)this);
- zoomIn->copy_tooltip("Zoom in");
+ zoomIn->copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_ZOOMIN));
gePack* g = new gePack(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, Direction::HORIZONTAL);
g->add(reload);
@@ -216,7 +217,7 @@ geGroup* gdSampleEditor::createPreviewBox(int x, int y, int h)
{
rewind = new geButton(x, y + (h / 2) - 12, 25, 25, "", rewindOff_xpm, rewindOn_xpm);
play = new geStatusButton(rewind->x() + rewind->w() + 4, rewind->y(), 25, 25, play_xpm, pause_xpm);
- loop = new geCheck(play->x() + play->w() + 4, play->y(), 50, 25, "Loop");
+ loop = new geCheck(play->x() + play->w() + 4, play->y(), 50, 25, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_LOOP));
play->callback(cb_togglePreview, (void*)this);
rewind->callback(cb_rewindPreview, (void*)this);
@@ -314,17 +315,9 @@ void gdSampleEditor::cb_zoomOut()
void gdSampleEditor::updateInfo()
{
- std::string bitDepth = m_data.waveBits != 0 ? u::string::iToString(m_data.waveBits) : "(unknown)";
- std::string infoText =
- "File: " + m_data.wavePath + "\n"
- "Size: " +
- u::string::iToString(m_data.waveSize) + " frames\n"
- "Duration: " +
- u::string::iToString(m_data.waveDuration) + " seconds\n"
- "Bit depth: " +
- bitDepth + "\n"
- "Frequency: " +
- u::string::iToString(m_data.waveRate) + " Hz\n";
+ std::string infoText = fmt::format(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_INFO),
+ m_data.wavePath, m_data.waveSize, m_data.waveDuration,
+ m_data.waveBits != 0 ? std::to_string(m_data.waveBits) : "?", m_data.waveRate);
info->copy_label(infoText.c_str());
}
diff --git a/src/gui/dialogs/warnings.cpp b/src/gui/dialogs/warnings.cpp
index 48964fe..1c79f7b 100644
--- a/src/gui/dialogs/warnings.cpp
+++ b/src/gui/dialogs/warnings.cpp
@@ -28,11 +28,14 @@
#include "core/const.h"
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/button.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "window.h"
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
namespace
@@ -46,11 +49,11 @@ bool confirmRet_ = false;
void gdAlert(const char* msg)
{
- gdWindow win(u::gui::getCenterWinBounds(300, 90), "Alert");
+ gdWindow win(u::gui::getCenterWinBounds(300, 90), g_ui.langMapper.get(LangMap::COMMON_WARNING));
win.set_modal();
win.begin();
geBox* box = new geBox(10, 10, 280, 40, msg);
- geButton* b = new geButton(210, 60, 80, 20, "Close");
+ geButton* b = new geButton(210, 60, 80, 20, g_ui.langMapper.get(LangMap::COMMON_CLOSE));
win.end();
box->labelsize(G_GUI_FONT_SIZE_BASE);
@@ -72,8 +75,8 @@ int gdConfirmWin(const char* title, const char* msg)
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");
+ geButton* ok = new geButton(212, 62, 80, 20, g_ui.langMapper.get(LangMap::COMMON_OK));
+ geButton* ko = new geButton(124, 62, 80, 20, g_ui.langMapper.get(LangMap::COMMON_CANCEL));
win.end();
ok->shortcut(FL_Enter);
diff --git a/src/gui/elems/actionEditor/gridTool.cpp b/src/gui/elems/actionEditor/gridTool.cpp
index 97ce87f..ac8150e 100644
--- a/src/gui/elems/actionEditor/gridTool.cpp
+++ b/src/gui/elems/actionEditor/gridTool.cpp
@@ -28,9 +28,12 @@
#include "core/conf.h"
#include "gui/elems/basics/check.h"
#include "gui/elems/basics/choice.h"
+#include "gui/ui.h"
#include "utils/math.h"
#include <FL/Fl_Double_Window.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geGridTool::geGridTool(Pixel x, Pixel y, m::Conf::Data& c)
@@ -58,8 +61,8 @@ geGridTool::geGridTool(Pixel x, Pixel y, m::Conf::Data& c)
end();
- gridType->copy_tooltip("Grid resolution");
- active->copy_tooltip("Snap to grid");
+ gridType->copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_GRIDRES));
+ active->copy_tooltip(g_ui.langMapper.get(LangMap::COMMON_SNAPTOGRID));
}
/* -------------------------------------------------------------------------- */
diff --git a/src/gui/elems/actionEditor/sampleActionEditor.cpp b/src/gui/elems/actionEditor/sampleActionEditor.cpp
index 16c6eab..f58bcfd 100644
--- a/src/gui/elems/actionEditor/sampleActionEditor.cpp
+++ b/src/gui/elems/actionEditor/sampleActionEditor.cpp
@@ -24,12 +24,13 @@
*
* -------------------------------------------------------------------------- */
-#include "sampleActionEditor.h"
+#include "gui/elems/actionEditor/sampleActionEditor.h"
#include "core/const.h"
#include "glue/actionEditor.h"
#include "glue/channel.h"
#include "gui/dialogs/actionEditor/baseActionEditor.h"
#include "gui/dialogs/actionEditor/sampleActionEditor.h"
+#include "gui/ui.h"
#include "sampleAction.h"
#include "src/core/actions/action.h"
#include "src/core/actions/actions.h"
@@ -38,6 +39,8 @@
#include <FL/fl_draw.H>
#include <cassert>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geSampleActionEditor::geSampleActionEditor(Pixel x, Pixel y, gdBaseActionEditor* b)
@@ -107,9 +110,9 @@ void geSampleActionEditor::draw()
fl_color(G_COLOR_GREY_4);
fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
if (active())
- fl_draw("start/stop", x() + 4, y(), w(), h(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CENTER));
+ fl_draw(g_ui.langMapper.get(LangMap::ACTIONEDITOR_STARTSTOP), x() + 4, y(), w(), h(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CENTER));
else
- fl_draw("start/stop (disabled)", x() + 4, y(), w(), h(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CENTER));
+ fl_draw(g_ui.langMapper.get(LangMap::ACTIONEDITOR_STARTSTOPDISABLED), x() + 4, y(), w(), h(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CENTER));
draw_children();
}
diff --git a/src/gui/elems/actionEditor/velocityEditor.cpp b/src/gui/elems/actionEditor/velocityEditor.cpp
index 60e9033..efc1c7c 100644
--- a/src/gui/elems/actionEditor/velocityEditor.cpp
+++ b/src/gui/elems/actionEditor/velocityEditor.cpp
@@ -30,6 +30,7 @@
#include "envelopePoint.h"
#include "glue/actionEditor.h"
#include "gui/dialogs/actionEditor/baseActionEditor.h"
+#include "gui/ui.h"
#include "src/core/actions/action.h"
#include "utils/log.h"
#include "utils/math.h"
@@ -37,6 +38,8 @@
#include <FL/fl_draw.H>
#include <cassert>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geVelocityEditor::geVelocityEditor(Pixel x, Pixel y, gdBaseActionEditor* b)
@@ -57,7 +60,7 @@ void geVelocityEditor::draw()
fl_color(G_COLOR_GREY_4);
fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
- fl_draw("Velocity", x() + 4, y(), w(), h(), FL_ALIGN_LEFT);
+ fl_draw(g_ui.langMapper.get(LangMap::ACTIONEDITOR_VELOCITY), x() + 4, y(), w(), h(), FL_ALIGN_LEFT);
if (children() == 0)
return;
diff --git a/src/gui/elems/basics/scroll.cpp b/src/gui/elems/basics/scroll.cpp
index 8f4837c..3a26fe2 100644
--- a/src/gui/elems/basics/scroll.cpp
+++ b/src/gui/elems/basics/scroll.cpp
@@ -53,6 +53,13 @@ geScroll::geScroll(int x, int y, int w, int h, int t)
/* -------------------------------------------------------------------------- */
+geScroll::geScroll(int type)
+: geScroll(0, 0, 0, 0, type)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
void geScroll::cb_onScrollV(Fl_Widget* w, void* p)
{
geScroll* s = static_cast<geScroll*>(w->parent());
diff --git a/src/gui/elems/basics/scroll.h b/src/gui/elems/basics/scroll.h
index d13a8e8..b9b8b89 100644
--- a/src/gui/elems/basics/scroll.h
+++ b/src/gui/elems/basics/scroll.h
@@ -37,6 +37,7 @@ class geScroll : public Fl_Scroll
{
public:
geScroll(int x, int y, int w, int h, int type = Fl_Scroll::BOTH);
+ geScroll(int type = Fl_Scroll::BOTH);
int countChildren() const;
diff --git a/src/gui/elems/basics/statusButton.cpp b/src/gui/elems/basics/statusButton.cpp
index ee6733e..8d2df7c 100644
--- a/src/gui/elems/basics/statusButton.cpp
+++ b/src/gui/elems/basics/statusButton.cpp
@@ -42,6 +42,15 @@ geStatusButton::geStatusButton(int x, int y, int w, int h, const char** imgOff,
/* -------------------------------------------------------------------------- */
+geStatusButton::geStatusButton(const char** imgOff, const char** imgOn,
+ const char** imgDisabled)
+: geButton("", imgOff, imgOn, imgDisabled)
+, m_status(false)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
void geStatusButton::draw()
{
if (active())
diff --git a/src/gui/elems/basics/statusButton.h b/src/gui/elems/basics/statusButton.h
index 1c9a917..c1d7e0e 100644
--- a/src/gui/elems/basics/statusButton.h
+++ b/src/gui/elems/basics/statusButton.h
@@ -36,17 +36,20 @@ namespace giada::v
{
class geStatusButton : public geButton
{
- public:
+public:
geStatusButton(int x, int y, int w, int h, const char** imgOff = nullptr,
const char** imgOn = nullptr, const char** imgDisabled = nullptr);
+ geStatusButton(const char** imgOff = nullptr, const char** imgOn = nullptr,
+ const char** imgDisabled = nullptr);
+
void draw() override;
bool getStatus() const;
void setStatus(bool s);
- private:
+private:
bool m_status;
};
} // namespace giada::v
diff --git a/src/gui/elems/config/stringMenu.cpp b/src/gui/elems/config/stringMenu.cpp
new file mode 100644
index 0000000..99e965a
--- /dev/null
+++ b/src/gui/elems/config/stringMenu.cpp
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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/config/stringMenu.h"
+#include "utils/gui.h"
+
+namespace giada::v
+{
+geStringMenu::geStringMenu(const char* l, const std::vector<std::string>& data,
+ const std::string& msgIfNotFound, int labelWidth)
+: geChoice(l, labelWidth)
+{
+ if (data.size() == 0)
+ {
+ addItem(msgIfNotFound.c_str(), 0);
+ showItem(0);
+ deactivate();
+ }
+ else
+ {
+ for (const std::string& d : data)
+ addItem(u::gui::removeFltkChars(d).c_str(), -1); // -1: auto-increment ID
+ }
+}
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/sampleEditor/boostTool.h b/src/gui/elems/config/stringMenu.h
index a01f9c3..99de2ed 100644
--- a/src/gui/elems/sampleEditor/boostTool.h
+++ b/src/gui/elems/config/stringMenu.h
@@ -24,37 +24,20 @@
*
* -------------------------------------------------------------------------- */
-#ifndef GE_BOOST_TOOL_H
-#define GE_BOOST_TOOL_H
+#ifndef GE_STRING_MENU_H
+#define GE_STRING_MENU_H
-#include <FL/Fl_Pack.H>
-
-class geInput;
+#include "gui/elems/basics/choice.h"
+#include <string>
+#include <vector>
namespace giada::v
{
-class geBox;
-class geDial;
-class geButton;
-class geBoostTool : public Fl_Pack
+class geStringMenu : public geChoice
{
public:
- geBoostTool(int x, int y);
-
- void rebuild();
-
-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);
- void cb_setBoost();
- void cb_setBoostNum();
- void cb_normalize();
-
- geBox* label;
- geDial* dial;
- geInput* input;
- geButton* normalize;
+ geStringMenu(const char* l, const std::vector<std::string>& data,
+ const std::string& msgIfNotFound, int labelWidth);
};
} // namespace giada::v
diff --git a/src/gui/elems/config/tabAudio.cpp b/src/gui/elems/config/tabAudio.cpp
index aaac8de..ebe5980 100644
--- a/src/gui/elems/config/tabAudio.cpp
+++ b/src/gui/elems/config/tabAudio.cpp
@@ -33,11 +33,14 @@
#include "gui/elems/basics/choice.h"
#include "gui/elems/basics/flex.h"
#include "gui/elems/basics/input.h"
+#include "gui/ui.h"
#include "utils/string.h"
#include <string>
constexpr int LABEL_WIDTH = 110;
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geTabAudio::geDeviceMenu::geDeviceMenu(const char* l, const std::vector<c::config::AudioDeviceData>& devices)
@@ -45,7 +48,7 @@ geTabAudio::geDeviceMenu::geDeviceMenu(const char* l, const std::vector<c::confi
{
if (devices.size() == 0)
{
- addItem("-- no devices found --", 0);
+ addItem(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_NODEVICESFOUND), 0);
showItem(0);
return;
}
@@ -88,7 +91,7 @@ void geTabAudio::geChannelMenu::rebuild(const c::config::AudioDeviceData& data)
if (m_data.index == -1)
{
- addItem("none", 0);
+ addItem(g_ui.langMapper.get(LangMap::COMMON_NONE), 0);
showItem(0);
return;
}
@@ -113,7 +116,7 @@ void geTabAudio::geChannelMenu::rebuild(const c::config::AudioDeviceData& data)
/* -------------------------------------------------------------------------- */
geTabAudio::geTabAudio(geompp::Rect<int> bounds)
-: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, "Audio")
+: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, g_ui.langMapper.get(LangMap::CONFIG_AUDIO_TITLE))
, m_data(c::config::getAudioData())
, m_initialApi(m_data.api)
{
@@ -121,24 +124,24 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
geFlex* body = new geFlex(bounds.reduced(G_GUI_OUTER_MARGIN), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
{
- soundsys = new geChoice("System", LABEL_WIDTH);
+ soundsys = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_SYSTEM), LABEL_WIDTH);
geFlex* line1 = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- buffersize = new geChoice("Buffer size", LABEL_WIDTH);
- samplerate = new geChoice("Sample rate", LABEL_WIDTH);
+ buffersize = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_BUFFERSIZE), LABEL_WIDTH);
+ samplerate = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_SAMPLERATE), LABEL_WIDTH);
line1->add(buffersize, 180);
line1->add(samplerate, 180);
line1->end();
}
- sounddevOut = new geDeviceMenu("Output device", m_data.outputDevices);
+ sounddevOut = new geDeviceMenu(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_OUTPUTDEVICE), m_data.outputDevices);
geFlex* line2 = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- channelsOut = new geChannelMenu("Output channels", m_data.outputDevice);
- limitOutput = new geCheck(x() + 177, y() + 93, 100, 20, "Limit output");
+ channelsOut = new geChannelMenu(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_OUTPUTCHANNELS), m_data.outputDevice);
+ limitOutput = new geCheck(x() + 177, y() + 93, 100, 20, g_ui.langMapper.get(LangMap::CONFIG_AUDIO_LIMITOUTPUT));
line2->add(channelsOut, 180);
line2->add(limitOutput);
@@ -147,7 +150,7 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
geFlex* line3 = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- sounddevIn = new geDeviceMenu("Input device", m_data.inputDevices);
+ sounddevIn = new geDeviceMenu(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_INPUTDEVICE), m_data.inputDevices);
enableIn = new geCheck(0, 0, 0, 0);
line3->add(sounddevIn);
@@ -157,8 +160,8 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
geFlex* line4 = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- channelsIn = new geChannelMenu("Input channels", m_data.inputDevice);
- recTriggerLevel = new geInput(0, 0, 0, 0, "Rec threshold (dB)");
+ channelsIn = new geChannelMenu(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_INPUTCHANNELS), m_data.inputDevice);
+ recTriggerLevel = new geInput(0, 0, 0, 0, g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RECTHRESHOLD));
line4->add(channelsIn, 180);
line4->add(new geBox(), 132); // TODO - temporary hack for geInput's label
@@ -166,7 +169,7 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
line4->end();
}
- rsmpQuality = new geChoice("Resampling", LABEL_WIDTH);
+ rsmpQuality = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RESAMPLING), LABEL_WIDTH);
body->add(soundsys, 20);
body->add(line1, 20);
@@ -175,7 +178,7 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
body->add(line3, 20);
body->add(line4, 20);
body->add(rsmpQuality, 20);
- body->add(new geBox("Restart Giada for the changes to take effect."));
+ body->add(new geBox(g_ui.langMapper.get(LangMap::CONFIG_RESTARTGIADA)));
body->end();
}
@@ -195,7 +198,7 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
sounddevIn->showItem(m_data.inputDevice.index);
sounddevIn->onChange = [this](ID id) { m_data.setInputDevice(id); fetch(); };
- enableIn->copy_tooltip("Enable Input");
+ enableIn->copy_tooltip(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_ENABLEINPUT));
enableIn->value(m_data.inputDevice.index != -1);
enableIn->onChange = [this](bool b) { m_data.setInputDevice(b ? 0 : -1); fetch(); };
@@ -225,11 +228,11 @@ geTabAudio::geTabAudio(geompp::Rect<int> bounds)
buffersize->showItem(m_data.bufferSize);
buffersize->onChange = [this](ID id) { m_data.bufferSize = id; };
- rsmpQuality->addItem("Sinc best quality (very slow)", 0);
- rsmpQuality->addItem("Sinc medium quality (slow)", 1);
- rsmpQuality->addItem("Sinc basic quality (medium)", 2);
- rsmpQuality->addItem("Zero Order Hold (fast)", 3);
- rsmpQuality->addItem("Linear (very fast)", 4);
+ rsmpQuality->addItem(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RESAMPLING_SINCBEST), 0);
+ rsmpQuality->addItem(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RESAMPLING_SINCMEDIUM), 1);
+ rsmpQuality->addItem(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RESAMPLING_SINCBASIC), 2);
+ rsmpQuality->addItem(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RESAMPLING_ZEROORDER), 3);
+ rsmpQuality->addItem(g_ui.langMapper.get(LangMap::CONFIG_AUDIO_RESAMPLING_LINEAR), 4);
rsmpQuality->showItem(m_data.resampleQuality);
rsmpQuality->onChange = [this](ID id) { m_data.resampleQuality = id; };
diff --git a/src/gui/elems/config/tabBehaviors.cpp b/src/gui/elems/config/tabBehaviors.cpp
index bcf2494..59782f2 100644
--- a/src/gui/elems/config/tabBehaviors.cpp
+++ b/src/gui/elems/config/tabBehaviors.cpp
@@ -30,22 +30,25 @@
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/check.h"
#include "gui/elems/basics/flex.h"
+#include "gui/ui.h"
#include <FL/Fl_Pack.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geTabBehaviors::geTabBehaviors(geompp::Rect<int> bounds, m::Conf::Data& c)
-: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, "Behaviors")
+: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, g_ui.langMapper.get(LangMap::CONFIG_BEHAVIORS_TITLE))
, m_conf(c)
{
end();
geFlex* body = new geFlex(bounds.reduced(G_GUI_OUTER_MARGIN), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
{
- m_chansStopOnSeqHalt = new geCheck(0, 0, 0, 0, "Dynamic channels stop immediately when the sequencer\nis halted");
- m_treatRecsAsLoops = new geCheck(0, 0, 0, 0, "Treat one shot channels with actions as loops");
- m_inputMonitorDefaultOn = new geCheck(0, 0, 0, 0, "New sample channels have input monitor on by default");
- m_overdubProtectionDefaultOn = new geCheck(0, 0, 0, 0, "New sample channels have overdub protection on\nby default");
+ m_chansStopOnSeqHalt = new geCheck(0, 0, 0, 0, g_ui.langMapper.get(LangMap::CONFIG_BEHAVIORS_CHANSSTOPONSEQHALT));
+ m_treatRecsAsLoops = new geCheck(0, 0, 0, 0, g_ui.langMapper.get(LangMap::CONFIG_BEHAVIORS_TREATRECSASLOOPS));
+ m_inputMonitorDefaultOn = new geCheck(0, 0, 0, 0, g_ui.langMapper.get(LangMap::CONFIG_BEHAVIORS_INPUTMONITORDEFAULTON));
+ m_overdubProtectionDefaultOn = new geCheck(0, 0, 0, 0, g_ui.langMapper.get(LangMap::CONFIG_BEHAVIORS_OVERDUBPROTECTIONDEFAULTON));
body->add(m_chansStopOnSeqHalt, 30);
body->add(m_treatRecsAsLoops, 20);
diff --git a/src/gui/elems/config/tabBindings.cpp b/src/gui/elems/config/tabBindings.cpp
index 59c07b5..ebf4352 100644
--- a/src/gui/elems/config/tabBindings.cpp
+++ b/src/gui/elems/config/tabBindings.cpp
@@ -28,22 +28,25 @@
#include "core/const.h"
#include "gui/elems/basics/liquidScroll.h"
#include "gui/elems/keyBinder.h"
+#include "gui/ui.h"
#include "utils/gui.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geTabBindings::geTabBindings(geompp::Rect<int> bounds, m::Conf::Data& conf)
-: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, "Key Bindings")
+: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, g_ui.langMapper.get(LangMap::CONFIG_BINDINGS_TITLE))
{
end();
geFlex* body = new geFlex(bounds.reduced(G_GUI_OUTER_MARGIN), Direction::VERTICAL, G_GUI_INNER_MARGIN);
{
- play = new geKeyBinder("Play", conf.keyBindings.find(m::Conf::KEY_BIND_PLAY)->second);
- rewind = new geKeyBinder("Rewind", conf.keyBindings.find(m::Conf::KEY_BIND_REWIND)->second);
- recordActions = new geKeyBinder("Record actions", conf.keyBindings.find(m::Conf::KEY_BIND_RECORD_ACTIONS)->second);
- recordInput = new geKeyBinder("Record audio", conf.keyBindings.find(m::Conf::KEY_BIND_RECORD_INPUT)->second);
- exit = new geKeyBinder("Exit", conf.keyBindings.find(m::Conf::KEY_BIND_EXIT)->second);
+ play = new geKeyBinder(g_ui.langMapper.get(LangMap::CONFIG_BINDINGS_PLAY), conf.keyBindings[m::Conf::KEY_BIND_PLAY]);
+ rewind = new geKeyBinder(g_ui.langMapper.get(LangMap::CONFIG_BINDINGS_REWIND), conf.keyBindings[m::Conf::KEY_BIND_REWIND]);
+ recordActions = new geKeyBinder(g_ui.langMapper.get(LangMap::CONFIG_BINDINGS_RECORDACTIONS), conf.keyBindings[m::Conf::KEY_BIND_RECORD_ACTIONS]);
+ recordInput = new geKeyBinder(g_ui.langMapper.get(LangMap::CONFIG_BINDINGS_RECORDAUDIO), conf.keyBindings[m::Conf::KEY_BIND_RECORD_INPUT]);
+ exit = new geKeyBinder(g_ui.langMapper.get(LangMap::CONFIG_BINDINGS_EXIT), conf.keyBindings[m::Conf::KEY_BIND_EXIT]);
body->add(play, G_GUI_UNIT);
body->add(rewind, G_GUI_UNIT);
diff --git a/src/gui/elems/config/tabMidi.cpp b/src/gui/elems/config/tabMidi.cpp
index c34e628..027effa 100644
--- a/src/gui/elems/config/tabMidi.cpp
+++ b/src/gui/elems/config/tabMidi.cpp
@@ -28,36 +28,20 @@
#include "core/const.h"
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/check.h"
+#include "gui/elems/basics/choice.h"
+#include "gui/elems/config/stringMenu.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include <string>
constexpr int LABEL_WIDTH = 120;
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
-geTabMidi::geMenu::geMenu(const char* l, const std::vector<std::string>& data,
- const std::string& msgIfNotFound)
-: geChoice(l, LABEL_WIDTH)
-{
- if (data.size() == 0)
- {
- addItem(msgIfNotFound.c_str(), 0);
- showItem(0);
- deactivate();
- }
- else
- {
- for (const std::string& d : data)
- addItem(u::gui::removeFltkChars(d).c_str(), -1); // -1: auto-increment ID
- }
-}
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
geTabMidi::geTabMidi(geompp::Rect<int> bounds)
-: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, "MIDI")
+: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, g_ui.langMapper.get(LangMap::CONFIG_MIDI_TITLE))
, m_data(c::config::getMidiData())
, m_initialApi(m_data.api)
{
@@ -65,11 +49,12 @@ geTabMidi::geTabMidi(geompp::Rect<int> bounds)
geFlex* body = new geFlex(bounds.reduced(G_GUI_OUTER_MARGIN), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
{
- system = new geChoice("System", LABEL_WIDTH);
+ system = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_MIDI_SYSTEM), LABEL_WIDTH);
geFlex* line1 = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- portOut = new geMenu("Output port", m_data.outPorts, "-- no ports found --");
+ portOut = new geStringMenu(g_ui.langMapper.get(LangMap::CONFIG_MIDI_OUTPUTPORT),
+ m_data.outPorts, g_ui.langMapper.get(LangMap::CONFIG_MIDI_NOPORTSFOUND), LABEL_WIDTH);
enableOut = new geCheck(0, 0, 0, 0);
line1->add(portOut);
@@ -79,7 +64,8 @@ geTabMidi::geTabMidi(geompp::Rect<int> bounds)
geFlex* line2 = new geFlex(Direction::HORIZONTAL, G_GUI_OUTER_MARGIN);
{
- portIn = new geMenu("Input port", m_data.inPorts, "-- no ports found --");
+ portIn = new geStringMenu(g_ui.langMapper.get(LangMap::CONFIG_MIDI_INPUTPORT),
+ m_data.inPorts, g_ui.langMapper.get(LangMap::CONFIG_MIDI_NOPORTSFOUND), LABEL_WIDTH);
enableIn = new geCheck(0, 0, 0, 0);
line2->add(portIn);
@@ -87,15 +73,16 @@ geTabMidi::geTabMidi(geompp::Rect<int> bounds)
line2->end();
}
- midiMap = new geMenu("Output Midi Map", m_data.midiMaps, "(no MIDI maps available)");
- sync = new geChoice("Sync", LABEL_WIDTH);
+ midiMap = new geStringMenu(g_ui.langMapper.get(LangMap::CONFIG_MIDI_OUTPUTMIDIMAP),
+ m_data.midiMaps, g_ui.langMapper.get(LangMap::CONFIG_MIDI_NOMIDIMAPSFOUND), LABEL_WIDTH);
+ sync = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_MIDI_SYNC), LABEL_WIDTH);
body->add(system, 20);
body->add(line1, 20);
body->add(line2, 20);
body->add(midiMap, 20);
body->add(sync, 20);
- body->add(new geBox("Restart Giada for the changes to take effect."));
+ body->add(new geBox(g_ui.langMapper.get(LangMap::CONFIG_RESTARTGIADA)));
body->end();
}
@@ -117,7 +104,7 @@ geTabMidi::geTabMidi(geompp::Rect<int> bounds)
if (m_data.inPort == -1)
portIn->deactivate();
- enableOut->copy_tooltip("Enable Output port");
+ enableOut->copy_tooltip(g_ui.langMapper.get(LangMap::CONFIG_MIDI_LABEL_ENABLEOUT));
enableOut->value(m_data.outPort != -1);
enableOut->onChange = [this](bool b) {
if (b)
@@ -132,7 +119,7 @@ geTabMidi::geTabMidi(geompp::Rect<int> bounds)
}
};
- enableIn->copy_tooltip("Enable Input port");
+ enableIn->copy_tooltip(g_ui.langMapper.get(LangMap::CONFIG_MIDI_LABEL_ENABLEIN));
enableIn->value(m_data.inPort != -1);
enableIn->onChange = [this](bool b) {
if (b)
diff --git a/src/gui/elems/config/tabMidi.h b/src/gui/elems/config/tabMidi.h
index 3add0b5..07ece12 100644
--- a/src/gui/elems/config/tabMidi.h
+++ b/src/gui/elems/config/tabMidi.h
@@ -29,32 +29,28 @@
#include "deps/geompp/src/rect.hpp"
#include "glue/config.h"
-#include "gui/elems/basics/choice.h"
#include <FL/Fl_Group.H>
class geCheck;
namespace giada::v
{
+class geStringMenu;
+class geChoice;
class geTabMidi : public Fl_Group
{
public:
- struct geMenu : public geChoice
- {
- geMenu(const char* l, const std::vector<std::string>&, const std::string& msgIfNotFound);
- };
-
geTabMidi(geompp::Rect<int>);
void save() const;
- geChoice* system;
- geMenu* portOut;
- geMenu* portIn;
- geCheck* enableOut;
- geCheck* enableIn;
- geMenu* midiMap;
- geChoice* sync;
+ geChoice* system;
+ geStringMenu* portOut;
+ geStringMenu* portIn;
+ geCheck* enableOut;
+ geCheck* enableIn;
+ geStringMenu* midiMap;
+ geChoice* sync;
private:
void invalidate();
diff --git a/src/gui/elems/config/tabMisc.cpp b/src/gui/elems/config/tabMisc.cpp
index 8cf108e..3f3a04b 100644
--- a/src/gui/elems/config/tabMisc.cpp
+++ b/src/gui/elems/config/tabMisc.cpp
@@ -27,40 +27,54 @@
#include "tabMisc.h"
#include "core/const.h"
#include "gui/elems/basics/choice.h"
+#include "gui/elems/config/stringMenu.h"
+#include "gui/ui.h"
constexpr int LABEL_WIDTH = 120;
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geTabMisc::geTabMisc(geompp::Rect<int> bounds)
-: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, "Misc")
+: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, g_ui.langMapper.get(LangMap::CONFIG_MISC_TITLE))
, m_data(c::config::getMiscData())
{
end();
geFlex* body = new geFlex(bounds.reduced(G_GUI_OUTER_MARGIN), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
{
- m_debugMsg = new geChoice("Debug messages", LABEL_WIDTH);
- m_tooltips = new geChoice("Tooltips", LABEL_WIDTH);
+ m_debugMsg = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_MISC_DEBUGMESSAGES), LABEL_WIDTH);
+ m_tooltips = new geChoice(g_ui.langMapper.get(LangMap::CONFIG_MISC_TOOLTIPS), LABEL_WIDTH);
+ m_langMap = new geStringMenu(g_ui.langMapper.get(LangMap::CONFIG_MISC_LANGUAGE),
+ m_data.langMaps, g_ui.langMapper.get(LangMap::CONFIG_MISC_NOLANGUAGESFOUND), LABEL_WIDTH);
body->add(m_debugMsg, 20);
body->add(m_tooltips, 20);
+ body->add(m_langMap, 20);
body->end();
}
add(body);
resizable(body);
- m_debugMsg->addItem("Disabled");
- m_debugMsg->addItem("To standard output");
- m_debugMsg->addItem("To file");
+ m_debugMsg->addItem(g_ui.langMapper.get(LangMap::CONFIG_MISC_DEBUGMESSAGES_DISABLED));
+ m_debugMsg->addItem(g_ui.langMapper.get(LangMap::CONFIG_MISC_DEBUGMESSAGES_TOSTDOUT));
+ m_debugMsg->addItem(g_ui.langMapper.get(LangMap::CONFIG_MISC_DEBUGMESSAGES_TOFILE));
m_debugMsg->showItem(m_data.logMode);
m_debugMsg->onChange = [this](ID id) { m_data.logMode = id; };
- m_tooltips->addItem("Disabled");
- m_tooltips->addItem("Enabled");
+ m_tooltips->addItem(g_ui.langMapper.get(LangMap::CONFIG_MISC_TOOLTIPS_DISABLED));
+ m_tooltips->addItem(g_ui.langMapper.get(LangMap::CONFIG_MISC_TOOLTIPS_ENABLED));
m_tooltips->showItem(m_data.showTooltips);
m_tooltips->onChange = [this](ID id) { m_data.showTooltips = id; };
+
+ m_langMap->addItem("English (default)");
+ if (m_data.langMap == "")
+ m_langMap->showItem(0);
+ else
+ m_langMap->showItem(m_data.langMap);
+ m_langMap->onChange = [this](ID /*id*/) { m_data.langMap = m_langMap->getSelectedLabel(); };
}
/* -------------------------------------------------------------------------- */
diff --git a/src/gui/elems/config/tabMisc.h b/src/gui/elems/config/tabMisc.h
index f2d3c5a..2d69edf 100644
--- a/src/gui/elems/config/tabMisc.h
+++ b/src/gui/elems/config/tabMisc.h
@@ -34,6 +34,7 @@
namespace giada::v
{
class geChoice;
+class geStringMenu;
class geTabMisc : public Fl_Group
{
public:
@@ -44,8 +45,9 @@ public:
private:
c::config::MiscData m_data;
- geChoice* m_debugMsg;
- geChoice* m_tooltips;
+ geChoice* m_debugMsg;
+ geChoice* m_tooltips;
+ geStringMenu* m_langMap;
};
} // namespace giada::v
diff --git a/src/gui/elems/config/tabPlugins.cpp b/src/gui/elems/config/tabPlugins.cpp
index 43f5507..c527f25 100644
--- a/src/gui/elems/config/tabPlugins.cpp
+++ b/src/gui/elems/config/tabPlugins.cpp
@@ -38,15 +38,19 @@
#include "gui/elems/basics/check.h"
#include "gui/elems/basics/flex.h"
#include "gui/elems/basics/input.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <FL/Fl.H>
+#include <fmt/core.h>
#include <functional>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geTabPlugins::geTabPlugins(geompp::Rect<int> bounds)
-: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, "Plug-ins")
+: Fl_Group(bounds.x, bounds.y, bounds.w, bounds.h, g_ui.langMapper.get(LangMap::CONFIG_PLUGINS_TITLE))
{
end();
@@ -77,7 +81,7 @@ geTabPlugins::geTabPlugins(geompp::Rect<int> bounds)
m_info->hide();
- m_folderPath->label("Plug-ins folder");
+ m_folderPath->label(g_ui.langMapper.get(LangMap::CONFIG_PLUGINS_FOLDER));
m_folderPath->onChange = [this](const std::string& v) {
m_data.pluginPath = v;
};
@@ -88,7 +92,7 @@ geTabPlugins::geTabPlugins(geompp::Rect<int> bounds)
m_scanButton->onClick = [this]() {
std::function<void(float)> callback = [this](float progress) {
- std::string l = "Scan in progress (" + std::to_string((int)(progress * 100)) + "%). Please wait...";
+ std::string l = fmt::format(g_ui.langMapper.get(LangMap::CONFIG_PLUGINS_SCANNING), static_cast<int>(progress * 100));
m_info->label(l.c_str());
Fl::wait();
};
@@ -108,7 +112,7 @@ void geTabPlugins::rebuild()
{
m_data = c::config::getPluginData();
- const std::string scanLabel = "Scan (" + std::to_string(m_data.numAvailablePlugins) + " found)";
+ const std::string scanLabel = fmt::format(g_ui.langMapper.get(LangMap::CONFIG_PLUGINS_SCAN), m_data.numAvailablePlugins);
m_scanButton->copy_label(scanLabel.c_str());
m_folderPath->value(m_data.pluginPath.c_str());
diff --git a/src/gui/elems/fileBrowser.cpp b/src/gui/elems/fileBrowser.cpp
index db021e2..cae48c4 100644
--- a/src/gui/elems/fileBrowser.cpp
+++ b/src/gui/elems/fileBrowser.cpp
@@ -31,9 +31,7 @@
#include "utils/fs.h"
#include "utils/string.h"
-namespace giada
-{
-namespace v
+namespace giada::v
{
geFileBrowser::geFileBrowser(int x, int y, int w, int h)
: Fl_File_Browser(x, y, w, h)
@@ -133,7 +131,7 @@ int geFileBrowser::handle(int e)
std::string geFileBrowser::getCurrentDir()
{
- return normalize(u::fs::getRealPath(m_currentDir));
+ return u::fs::getRealPath(m_currentDir);
}
/* -------------------------------------------------------------------------- */
@@ -141,18 +139,11 @@ std::string geFileBrowser::getCurrentDir()
std::string geFileBrowser::getSelectedItem(bool fullPath)
{
if (!fullPath) // no full path requested? return the selected text
- return normalize(text(value()));
+ return text(value());
else if (value() == 0) // no rows selected? return current directory
- return normalize(m_currentDir);
+ return 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()))));
- }
+ return u::fs::getRealPath(u::fs::join(m_currentDir, text(value())));
}
/* -------------------------------------------------------------------------- */
@@ -162,20 +153,4 @@ 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
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/fileBrowser.h b/src/gui/elems/fileBrowser.h
index 624a86a..c11696b 100644
--- a/src/gui/elems/fileBrowser.h
+++ b/src/gui/elems/fileBrowser.h
@@ -32,9 +32,7 @@
#include <FL/Fl_File_Browser.H>
#include <string>
-namespace giada
-{
-namespace v
+namespace giada::v
{
class geFileBrowser : public Fl_File_Browser
{
@@ -60,16 +58,10 @@ public:
int handle(int e);
- private:
- /* normalize
- Makes sure the std::string never ends with a trailing slash. */
-
- std::string normalize(const std::string& s);
-
+private:
std::string m_currentDir;
bool m_showHiddenFiles;
};
-} // namespace v
-} // namespace giada
+} // namespace giada::v
#endif
diff --git a/src/gui/elems/keyBinder.cpp b/src/gui/elems/keyBinder.cpp
index 93d2c3f..8ae7353 100644
--- a/src/gui/elems/keyBinder.cpp
+++ b/src/gui/elems/keyBinder.cpp
@@ -31,8 +31,11 @@
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/boxtypes.h"
#include "gui/elems/basics/button.h"
+#include "gui/ui.h"
#include "utils/gui.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geKeyBinder::geKeyBinder(const std::string& l, int& keyRef)
@@ -40,8 +43,8 @@ geKeyBinder::geKeyBinder(const std::string& l, int& keyRef)
{
m_labelBox = new geBox(l.c_str());
m_keyBox = new geBox(u::gui::keyToString(keyRef).c_str());
- m_bindBtn = new geButton("Bind");
- m_clearBtn = new geButton("Clear");
+ m_bindBtn = new geButton(g_ui.langMapper.get(LangMap::COMMON_BIND));
+ m_clearBtn = new geButton(g_ui.langMapper.get(LangMap::COMMON_CLEAR));
add(m_labelBox);
add(m_keyBox, 100);
diff --git a/src/gui/elems/mainWindow/keyboard/column.cpp b/src/gui/elems/mainWindow/keyboard/column.cpp
index 237ac61..f6a00a5 100644
--- a/src/gui/elems/mainWindow/keyboard/column.cpp
+++ b/src/gui/elems/mainWindow/keyboard/column.cpp
@@ -24,15 +24,16 @@
*
* -------------------------------------------------------------------------- */
-#include "column.h"
+#include "gui/elems/mainWindow/keyboard/column.h"
#include "core/model/model.h"
#include "glue/channel.h"
#include "gui/dialogs/warnings.h"
#include "gui/elems/basics/boxtypes.h"
#include "gui/elems/basics/resizerBar.h"
-#include "keyboard.h"
-#include "midiChannel.h"
-#include "sampleChannel.h"
+#include "gui/elems/mainWindow/keyboard/keyboard.h"
+#include "gui/elems/mainWindow/keyboard/midiChannel.h"
+#include "gui/elems/mainWindow/keyboard/sampleChannel.h"
+#include "gui/ui.h"
#include "utils/fs.h"
#include "utils/gui.h"
#include "utils/log.h"
@@ -41,8 +42,42 @@
#include <FL/fl_draw.H>
#include <cassert>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
+namespace
+{
+enum class Menu
+{
+ ADD_SAMPLE_CHANNEL = 0,
+ ADD_MIDI_CHANNEL,
+ REMOVE
+};
+
+void MenuCallback(Fl_Widget* w, void* v)
+{
+ const geColumn* column = static_cast<geColumn*>(w);
+
+ switch ((Menu)(intptr_t)v)
+ {
+ case Menu::ADD_SAMPLE_CHANNEL:
+ c::channel::addChannel(column->id, ChannelType::SAMPLE);
+ break;
+ case Menu::ADD_MIDI_CHANNEL:
+ c::channel::addChannel(column->id, ChannelType::MIDI);
+ break;
+ case Menu::REMOVE:
+ static_cast<geKeyboard*>(column->parent())->deleteColumn(column->id);
+ break;
+ }
+}
+} // namespace
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
geColumn::geColumn(int X, int Y, int W, int H, ID id, geResizerBar* b)
: Fl_Group(X, Y, W, H)
, id(id)
@@ -114,16 +149,16 @@ geChannel* geColumn::addChannel(c::channel::Data d)
void geColumn::cb_addChannel()
{
- u::log::print("[geColumn::cb_addChannel] id = %d\n", id);
+ G_DEBUG("Column id: " << id);
Fl_Menu_Item menu[] = {
- u::gui::makeMenuItem("Add Sample channel"),
- u::gui::makeMenuItem("Add MIDI channel"),
- u::gui::makeMenuItem("Remove"),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_COLUMN_BUTTON_ADDSAMPLECHANNEL), MenuCallback, (void*)Menu::ADD_SAMPLE_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_COLUMN_BUTTON_ADDMIDICHANNEL), MenuCallback, (void*)Menu::ADD_MIDI_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_COLUMN_BUTTON_REMOVE), MenuCallback, (void*)Menu::REMOVE),
{}};
if (countChannels() > 0)
- menu[2].deactivate();
+ menu[(int)Menu::REMOVE].deactivate();
Fl_Menu_Button b(0, 0, 100, 50);
b.box(G_CUSTOM_BORDER_BOX);
@@ -132,15 +167,8 @@ void geColumn::cb_addChannel()
b.color(G_COLOR_GREY_2);
const Fl_Menu_Item* m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, &b);
- if (m == nullptr)
- return;
-
- if (strcmp(m->label(), "Add Sample channel") == 0)
- c::channel::addChannel(id, ChannelType::SAMPLE);
- else if (strcmp(m->label(), "Add MIDI channel") == 0)
- c::channel::addChannel(id, ChannelType::MIDI);
- else
- static_cast<geKeyboard*>(parent())->deleteColumn(id);
+ if (m != nullptr)
+ m->do_callback(this, m->user_data());
}
/* -------------------------------------------------------------------------- */
@@ -160,7 +188,7 @@ void geColumn::init()
Fl_Group::clear();
m_channels.clear();
- m_addChannelBtn = new geButton(x(), y(), w(), G_GUI_UNIT, "Edit column");
+ m_addChannelBtn = new geButton(x(), y(), w(), G_GUI_UNIT, g_ui.langMapper.get(LangMap::MAIN_COLUMN_BUTTON));
m_addChannelBtn->callback(cb_addChannel, (void*)this);
add(m_addChannelBtn);
diff --git a/src/gui/elems/mainWindow/keyboard/keyboard.cpp b/src/gui/elems/mainWindow/keyboard/keyboard.cpp
index 4c72ca3..aad98d5 100644
--- a/src/gui/elems/mainWindow/keyboard/keyboard.cpp
+++ b/src/gui/elems/mainWindow/keyboard/keyboard.cpp
@@ -48,8 +48,8 @@ extern giada::v::Ui g_ui;
namespace giada::v
{
-geKeyboard::geKeyboard(int X, int Y, int W, int H)
-: geScroll(X, Y, W, H, Fl_Scroll::BOTH_ALWAYS)
+geKeyboard::geKeyboard()
+: geScroll(Fl_Scroll::BOTH_ALWAYS)
, m_addColumnBtn(nullptr)
{
end();
diff --git a/src/gui/elems/mainWindow/keyboard/keyboard.h b/src/gui/elems/mainWindow/keyboard/keyboard.h
index c5593f8..178b650 100644
--- a/src/gui/elems/mainWindow/keyboard/keyboard.h
+++ b/src/gui/elems/mainWindow/keyboard/keyboard.h
@@ -48,7 +48,7 @@ public:
int width;
};
- geKeyboard(int X, int Y, int W, int H);
+ geKeyboard();
int handle(int e) override;
void draw() override;
diff --git a/src/gui/elems/mainWindow/keyboard/midiActivity.cpp b/src/gui/elems/mainWindow/keyboard/midiActivity.cpp
index 4ced13c..1031f14 100644
--- a/src/gui/elems/mainWindow/keyboard/midiActivity.cpp
+++ b/src/gui/elems/mainWindow/keyboard/midiActivity.cpp
@@ -27,8 +27,11 @@
#include "gui/elems/mainWindow/keyboard/midiActivity.h"
#include "core/const.h"
#include "gui/elems/basics/flex.h"
+#include "gui/ui.h"
#include <FL/fl_draw.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geMidiActivity::geLed::geLed()
@@ -85,7 +88,6 @@ geMidiActivity::geMidiActivity(int x, int y, int w, int h)
add(container);
resizable(container);
- copy_tooltip("MIDI I/O activity\n\nNotifies MIDI messages sent (top) or "
- "received (bottom) by this channel.");
+ copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_MIDIACTIVITY));
}
} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/mainWindow/keyboard/midiChannel.cpp b/src/gui/elems/mainWindow/keyboard/midiChannel.cpp
index 3273c85..d5e449d 100644
--- a/src/gui/elems/mainWindow/keyboard/midiChannel.cpp
+++ b/src/gui/elems/mainWindow/keyboard/midiChannel.cpp
@@ -40,11 +40,14 @@
#include "gui/elems/mainWindow/keyboard/column.h"
#include "gui/elems/mainWindow/keyboard/midiActivity.h"
#include "gui/elems/mainWindow/keyboard/midiChannelButton.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <FL/Fl_Menu_Button.H>
#include <cassert>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
namespace
@@ -128,14 +131,14 @@ geMidiChannel::geMidiChannel(int X, int Y, int W, int H, c::channel::Data d)
resizable(mainButton);
- playButton->copy_tooltip("Play/stop");
- arm->copy_tooltip("Arm for recording");
- mute->copy_tooltip("Mute");
- solo->copy_tooltip("Solo");
+ playButton->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_PLAY));
+ arm->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_ARM));
+ mute->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_MUTE));
+ solo->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_SOLO));
#if defined(WITH_VST)
- fx->copy_tooltip("Plug-ins");
+ fx->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_FX));
#endif
- vol->copy_tooltip("Volume");
+ vol->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_VOLUME));
#ifdef WITH_VST
fx->setStatus(m_channel.plugins.size() > 0);
@@ -183,16 +186,16 @@ void geMidiChannel::cb_playButton()
void geMidiChannel::cb_openMenu()
{
Fl_Menu_Item rclick_menu[] = {
- u::gui::makeMenuItem("Edit actions...", menuCallback, (void*)Menu::EDIT_ACTIONS),
- u::gui::makeMenuItem("Clear actions", menuCallback, (void*)Menu::CLEAR_ACTIONS, FL_SUBMENU),
- u::gui::makeMenuItem("All", menuCallback, (void*)Menu::CLEAR_ACTIONS_ALL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_EDITACTIONS), menuCallback, (void*)Menu::EDIT_ACTIONS),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLEARACTIONS), menuCallback, (void*)Menu::CLEAR_ACTIONS, FL_SUBMENU),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLEARACTIONS_ALL), menuCallback, (void*)Menu::CLEAR_ACTIONS_ALL),
{},
- u::gui::makeMenuItem("Setup keyboard input...", menuCallback, (void*)Menu::SETUP_KEYBOARD_INPUT),
- u::gui::makeMenuItem("Setup MIDI input...", menuCallback, (void*)Menu::SETUP_MIDI_INPUT),
- u::gui::makeMenuItem("Setup MIDI output...", menuCallback, (void*)Menu::SETUP_MIDI_OUTPUT),
- u::gui::makeMenuItem("Rename", menuCallback, (void*)Menu::RENAME_CHANNEL),
- u::gui::makeMenuItem("Clone", menuCallback, (void*)Menu::CLONE_CHANNEL),
- u::gui::makeMenuItem("Delete", menuCallback, (void*)Menu::DELETE_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_KEYBOARDINPUT), menuCallback, (void*)Menu::SETUP_KEYBOARD_INPUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_MIDIINPUT), menuCallback, (void*)Menu::SETUP_MIDI_INPUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_MIDIOUTPUT), menuCallback, (void*)Menu::SETUP_MIDI_OUTPUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_RENAME), menuCallback, (void*)Menu::RENAME_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLONE), menuCallback, (void*)Menu::CLONE_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_DELETE), menuCallback, (void*)Menu::DELETE_CHANNEL),
{}};
/* No 'clear actions' if there are no actions. */
diff --git a/src/gui/elems/mainWindow/keyboard/sampleChannel.cpp b/src/gui/elems/mainWindow/keyboard/sampleChannel.cpp
index f2759e4..1ff1921 100644
--- a/src/gui/elems/mainWindow/keyboard/sampleChannel.cpp
+++ b/src/gui/elems/mainWindow/keyboard/sampleChannel.cpp
@@ -43,8 +43,11 @@
#include "gui/elems/mainWindow/keyboard/keyboard.h"
#include "gui/elems/mainWindow/keyboard/midiActivity.h"
#include "gui/elems/mainWindow/keyboard/sampleChannelButton.h"
+#include "gui/ui.h"
#include "utils/gui.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
namespace
@@ -196,18 +199,17 @@ geSampleChannel::geSampleChannel(int X, int Y, int W, int H, c::channel::Data d)
resizable(mainButton);
- playButton->copy_tooltip("Play/stop");
- arm->copy_tooltip("Arm for recording");
- status->copy_tooltip("Progress bar");
- readActions->copy_tooltip("Read actions\n\nToggles playback of pre-recorded "
- "actions (key press, key release, ...).");
- modeBox->copy_tooltip("Mode");
- mute->copy_tooltip("Mute");
- solo->copy_tooltip("Solo");
+ playButton->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_PLAY));
+ arm->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_ARM));
+ status->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_STATUS));
+ readActions->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_READACTIONS));
+ modeBox->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_MODEBOX));
+ mute->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_MUTE));
+ solo->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_SOLO));
#if defined(WITH_VST)
- fx->copy_tooltip("Plug-ins");
+ fx->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_FX));
#endif
- vol->copy_tooltip("Volume");
+ vol->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_LABEL_VOLUME));
#ifdef WITH_VST
fx->setStatus(m_channel.plugins.size() > 0);
@@ -264,26 +266,26 @@ void geSampleChannel::cb_openMenu()
return;
Fl_Menu_Item rclick_menu[] = {
- u::gui::makeMenuItem("Input monitor", menuCallback, (void*)Menu::INPUT_MONITOR,
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_INPUTMONITOR), menuCallback, (void*)Menu::INPUT_MONITOR,
FL_MENU_TOGGLE | (m_channel.sample->getInputMonitor() ? FL_MENU_VALUE : 0)),
- u::gui::makeMenuItem("Overdub protection", menuCallback, (void*)Menu::OVERDUB_PROTECTION,
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_OVERDUBPROTECTION), menuCallback, (void*)Menu::OVERDUB_PROTECTION,
FL_MENU_TOGGLE | FL_MENU_DIVIDER | (m_channel.sample->getOverdubProtection() ? FL_MENU_VALUE : 0)),
- u::gui::makeMenuItem("Load new sample...", menuCallback, (void*)Menu::LOAD_SAMPLE),
- u::gui::makeMenuItem("Export sample to file...", menuCallback, (void*)Menu::EXPORT_SAMPLE),
- u::gui::makeMenuItem("Setup keyboard input...", menuCallback, (void*)Menu::SETUP_KEYBOARD_INPUT),
- u::gui::makeMenuItem("Setup MIDI input...", menuCallback, (void*)Menu::SETUP_MIDI_INPUT),
- u::gui::makeMenuItem("Setup MIDI output...", menuCallback, (void*)Menu::SETUP_MIDI_OUTPUT),
- u::gui::makeMenuItem("Edit sample...", menuCallback, (void*)Menu::EDIT_SAMPLE),
- u::gui::makeMenuItem("Edit actions...", menuCallback, (void*)Menu::EDIT_ACTIONS),
- u::gui::makeMenuItem("Clear actions", menuCallback, (void*)Menu::CLEAR_ACTIONS, FL_SUBMENU),
- u::gui::makeMenuItem("All", menuCallback, (void*)Menu::CLEAR_ACTIONS_ALL),
- u::gui::makeMenuItem("Volume", menuCallback, (void*)Menu::CLEAR_ACTIONS_VOLUME),
- u::gui::makeMenuItem("Start/Stop", menuCallback, (void*)Menu::CLEAR_ACTIONS_START_STOP),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_LOADSAMPLE), menuCallback, (void*)Menu::LOAD_SAMPLE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_EXPORTSAMPLE), menuCallback, (void*)Menu::EXPORT_SAMPLE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_KEYBOARDINPUT), menuCallback, (void*)Menu::SETUP_KEYBOARD_INPUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_MIDIINPUT), menuCallback, (void*)Menu::SETUP_MIDI_INPUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_MIDIOUTPUT), menuCallback, (void*)Menu::SETUP_MIDI_OUTPUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_EDITSAMPLE), menuCallback, (void*)Menu::EDIT_SAMPLE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_EDITACTIONS), menuCallback, (void*)Menu::EDIT_ACTIONS),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLEARACTIONS), menuCallback, (void*)Menu::CLEAR_ACTIONS, FL_SUBMENU),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLEARACTIONS_ALL), menuCallback, (void*)Menu::CLEAR_ACTIONS_ALL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLEARACTIONS_VOLUME), menuCallback, (void*)Menu::CLEAR_ACTIONS_VOLUME),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLEARACTIONS_STARTSTOP), menuCallback, (void*)Menu::CLEAR_ACTIONS_START_STOP),
{},
- u::gui::makeMenuItem("Rename", menuCallback, (void*)Menu::RENAME_CHANNEL),
- u::gui::makeMenuItem("Clone", menuCallback, (void*)Menu::CLONE_CHANNEL),
- u::gui::makeMenuItem("Free", menuCallback, (void*)Menu::FREE_CHANNEL),
- u::gui::makeMenuItem("Delete", menuCallback, (void*)Menu::DELETE_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_RENAME), menuCallback, (void*)Menu::RENAME_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_CLONE), menuCallback, (void*)Menu::CLONE_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_FREE), menuCallback, (void*)Menu::FREE_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_MENU_DELETE), menuCallback, (void*)Menu::DELETE_CHANNEL),
{}};
if (m_channel.sample->waveId == 0)
diff --git a/src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp b/src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp
index e319ac3..d989742 100644
--- a/src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp
+++ b/src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp
@@ -27,12 +27,15 @@
#include "sampleChannelButton.h"
#include "glue/channel.h"
#include "gui/dialogs/mainWindow.h"
+#include "gui/ui.h"
#include "keyboard.h"
#include "sampleChannel.h"
#include "utils/fs.h"
#include "utils/string.h"
#include <FL/Fl.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geSampleChannelButton::geSampleChannelButton(int x, int y, int w, int h, const c::channel::Data& d)
@@ -42,10 +45,10 @@ geSampleChannelButton::geSampleChannelButton(int x, int y, int w, int h, const c
{
case ChannelStatus::MISSING:
case ChannelStatus::WRONG:
- label("* file not found! *");
+ label(g_ui.langMapper.get(LangMap::MAIN_CHANNEL_SAMPLENOTFOUND));
break;
default:
- label(m_channel.sample->waveId == 0 ? "-- no sample --" : m_channel.name.c_str());
+ label(m_channel.sample->waveId == 0 ? g_ui.langMapper.get(LangMap::MAIN_CHANNEL_NOSAMPLE) : m_channel.name.c_str());
break;
}
}
diff --git a/src/gui/elems/mainWindow/mainIO.cpp b/src/gui/elems/mainWindow/mainIO.cpp
index 8b3fca8..e1783de 100644
--- a/src/gui/elems/mainWindow/mainIO.cpp
+++ b/src/gui/elems/mainWindow/mainIO.cpp
@@ -35,15 +35,18 @@
#include "gui/elems/basics/dial.h"
#include "gui/elems/basics/statusButton.h"
#include "gui/elems/soundMeter.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#ifdef WITH_VST
#include "gui/elems/basics/statusButton.h"
#endif
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
-geMainIO::geMainIO(int x, int y, int w, int h)
-: geFlex(x, y, w, h, Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
+geMainIO::geMainIO()
+: geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
{
m_outMeter = new geSoundMeter(0, 0, 0, 0);
m_inMeter = new geSoundMeter(0, 0, 0, 0);
@@ -68,14 +71,14 @@ geMainIO::geMainIO(int x, int y, int w, int h)
#endif
end();
- 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.");
+ m_outMeter->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_OUTMETER));
+ m_inMeter->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_INMETER));
+ m_outVol->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_OUTVOL));
+ m_inVol->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_INVOL));
+ m_inToOut->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_INTOOUT));
#ifdef WITH_VST
- m_masterFxOut->copy_tooltip("Main output plug-ins");
- m_masterFxIn->copy_tooltip("Main input plug-ins");
+ m_masterFxOut->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_FXOUT));
+ m_masterFxIn->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_IO_LABEL_FXIN));
#endif
m_outVol->onChange = [](float v) {
@@ -87,8 +90,8 @@ geMainIO::geMainIO(int x, int y, int w, int h)
};
m_inToOut->type(FL_TOGGLE_BUTTON);
- m_inToOut->onClick = [v = m_inToOut->value()]() {
- c::main::setInToOut(v);
+ m_inToOut->onClick = [&inToOut = m_inToOut]() {
+ c::main::setInToOut(inToOut->value());
};
#ifdef WITH_VST
diff --git a/src/gui/elems/mainWindow/mainIO.h b/src/gui/elems/mainWindow/mainIO.h
index 9b83ccc..fecb390 100644
--- a/src/gui/elems/mainWindow/mainIO.h
+++ b/src/gui/elems/mainWindow/mainIO.h
@@ -39,7 +39,7 @@ class geStatusButton;
class geMainIO : public geFlex
{
public:
- geMainIO(int x, int y, int w, int h);
+ geMainIO();
void refresh();
void rebuild();
diff --git a/src/gui/elems/mainWindow/mainMenu.cpp b/src/gui/elems/mainWindow/mainMenu.cpp
index 0823313..dece25c 100644
--- a/src/gui/elems/mainWindow/mainMenu.cpp
+++ b/src/gui/elems/mainWindow/mainMenu.cpp
@@ -31,25 +31,94 @@
#include "glue/main.h"
#include "gui/elems/basics/boxtypes.h"
#include "gui/elems/basics/button.h"
+#include "gui/ui.h"
#include "keyboard/keyboard.h"
#include "utils/gui.h"
#include <FL/Fl_Menu_Button.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
-geMainMenu::geMainMenu(int x, int y)
-: gePack(x, y, Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
+namespace
+{
+enum class FileMenu
+{
+ OPEN_PROJECT = 0,
+ SAVE_PROJECT,
+ CLOSE_PROJECT,
+#ifdef G_DEBUG_MODE
+ DEBUG_STATS,
+#endif
+ QUIT
+};
+
+void fileMenuCallback(Fl_Widget* /*w*/, void* v)
+{
+ switch ((FileMenu)(intptr_t)v)
+ {
+ case FileMenu::OPEN_PROJECT:
+ c::layout::openBrowserForProjectLoad();
+ break;
+ case FileMenu::SAVE_PROJECT:
+ c::layout::openBrowserForProjectSave();
+ break;
+ case FileMenu::CLOSE_PROJECT:
+ c::main::closeProject();
+ break;
+#ifdef G_DEBUG_MODE
+ case FileMenu::DEBUG_STATS:
+ c::main::printDebugInfo();
+ break;
+#endif
+ case FileMenu::QUIT:
+ c::main::quitGiada();
+ break;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+enum class EditMenu
+{
+ FREE_SAMPLE_CHANNELS = 0,
+ CLEAR_ALL_ACTIONS,
+ SETUP_MIDI_INPUT
+};
+
+void editMenuCallback(Fl_Widget* /*w*/, void* v)
{
- 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);
+ switch ((EditMenu)(intptr_t)v)
+ {
+ case EditMenu::FREE_SAMPLE_CHANNELS:
+ c::main::clearAllSamples();
+ break;
+ case EditMenu::CLEAR_ALL_ACTIONS:
+ c::main::clearAllActions();
+ break;
+ case EditMenu::SETUP_MIDI_INPUT:
+ c::layout::openMasterMidiInputWindow();
+ break;
+ }
+}
+} // namespace
- resizable(nullptr);
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+geMainMenu::geMainMenu()
+: geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
+{
+ geButton* file = new geButton(g_ui.langMapper.get(LangMap::MAIN_MENU_FILE));
+ geButton* edit = new geButton(g_ui.langMapper.get(LangMap::MAIN_MENU_EDIT));
+ geButton* config = new geButton(g_ui.langMapper.get(LangMap::MAIN_MENU_CONFIG));
+ geButton* about = new geButton(g_ui.langMapper.get(LangMap::MAIN_MENU_ABOUT));
+ add(file, 80);
+ add(edit, 80);
+ add(config, 80);
+ add(about, 80);
+ end();
file->onClick = [this]() { cb_file(); };
edit->onClick = [this]() { cb_edit(); };
@@ -62,13 +131,13 @@ geMainMenu::geMainMenu(int x, int y)
void geMainMenu::cb_file()
{
Fl_Menu_Item menu[] = {
- u::gui::makeMenuItem("Open project..."),
- u::gui::makeMenuItem("Save project..."),
- u::gui::makeMenuItem("Close project"),
-#ifndef NDEBUG
- u::gui::makeMenuItem("Debug stats"),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_FILE_OPENPROJECT), fileMenuCallback, (void*)FileMenu::OPEN_PROJECT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_FILE_SAVEPROJECT), fileMenuCallback, (void*)FileMenu::SAVE_PROJECT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_FILE_CLOSEPROJECT), fileMenuCallback, (void*)FileMenu::CLOSE_PROJECT),
+#ifdef G_DEBUG_MODE
+ u::gui::makeMenuItem("Debug stats", fileMenuCallback, (void*)FileMenu::DEBUG_STATS),
#endif
- u::gui::makeMenuItem("Quit Giada"),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_FILE_QUIT), fileMenuCallback, (void*)FileMenu::QUIT),
{}};
Fl_Menu_Button b(0, 0, 100, 50);
@@ -78,31 +147,8 @@ void geMainMenu::cb_file()
b.color(G_COLOR_GREY_2);
const Fl_Menu_Item* m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, &b);
- if (!m)
- return;
-
- if (strcmp(m->label(), "Open project...") == 0)
- {
- c::layout::openBrowserForProjectLoad();
- }
- else if (strcmp(m->label(), "Save project...") == 0)
- {
- c::layout::openBrowserForProjectSave();
- }
- else if (strcmp(m->label(), "Close project") == 0)
- {
- c::main::closeProject();
- }
-#ifdef G_DEBUG_MODE
- else if (strcmp(m->label(), "Debug stats") == 0)
- {
- c::main::printDebugInfo();
- }
-#endif
- else if (strcmp(m->label(), "Quit Giada") == 0)
- {
- c::main::quitGiada();
- }
+ if (m != nullptr)
+ m->do_callback(this, m->user_data());
}
/* -------------------------------------------------------------------------- */
@@ -112,18 +158,18 @@ void geMainMenu::cb_edit()
c::main::MainMenu menu = c::main::getMainMenu();
Fl_Menu_Item menuItem[] = {
- u::gui::makeMenuItem("Free all Sample channels"),
- u::gui::makeMenuItem("Clear all actions"),
- u::gui::makeMenuItem("Setup global MIDI input..."),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_EDIT_FREEALLSAMPLES), editMenuCallback, (void*)EditMenu::FREE_SAMPLE_CHANNELS),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_EDIT_CLEARALLACTIONS), editMenuCallback, (void*)EditMenu::CLEAR_ALL_ACTIONS),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::MAIN_MENU_EDIT_SETUPMIDIINPUT), editMenuCallback, (void*)EditMenu::SETUP_MIDI_INPUT),
{}};
- menuItem[0].deactivate();
- menuItem[1].deactivate();
+ menuItem[(int)EditMenu::FREE_SAMPLE_CHANNELS].deactivate();
+ menuItem[(int)EditMenu::CLEAR_ALL_ACTIONS].deactivate();
if (menu.hasAudioData)
- menuItem[0].activate();
+ menuItem[(int)EditMenu::FREE_SAMPLE_CHANNELS].activate();
if (menu.hasActions)
- menuItem[1].activate();
+ menuItem[(int)EditMenu::CLEAR_ALL_ACTIONS].activate();
Fl_Menu_Button b(0, 0, 100, 50);
b.box(G_CUSTOM_BORDER_BOX);
@@ -132,14 +178,7 @@ void geMainMenu::cb_edit()
b.color(G_COLOR_GREY_2);
const Fl_Menu_Item* m = menuItem->popup(Fl::event_x(), Fl::event_y(), 0, 0, &b);
- if (!m)
- return;
-
- if (strcmp(m->label(), "Free all Sample channels") == 0)
- c::main::clearAllSamples();
- else if (strcmp(m->label(), "Clear all actions") == 0)
- c::main::clearAllActions();
- else if (strcmp(m->label(), "Setup global MIDI input...") == 0)
- c::layout::openMasterMidiInputWindow();
+ if (m != nullptr)
+ m->do_callback(this, m->user_data());
}
-} // namespace giada::v
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/mainWindow/mainMenu.h b/src/gui/elems/mainWindow/mainMenu.h
index 4ca3823..9b16d0c 100644
--- a/src/gui/elems/mainWindow/mainMenu.h
+++ b/src/gui/elems/mainWindow/mainMenu.h
@@ -27,14 +27,14 @@
#ifndef GE_MAIN_MENU_H
#define GE_MAIN_MENU_H
-#include "gui/elems/basics/pack.h"
+#include "gui/elems/basics/flex.h"
namespace giada::v
{
-class geMainMenu : public gePack
+class geMainMenu : public geFlex
{
public:
- geMainMenu(int x, int y);
+ geMainMenu();
private:
void cb_file();
diff --git a/src/gui/elems/mainWindow/mainTimer.cpp b/src/gui/elems/mainWindow/mainTimer.cpp
index 737b475..7c93a05 100644
--- a/src/gui/elems/mainWindow/mainTimer.cpp
+++ b/src/gui/elems/mainWindow/mainTimer.cpp
@@ -32,39 +32,41 @@
#include "glue/main.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/choice.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
-geMainTimer::geMainTimer(int x, int y)
-: gePack(x, y, Direction::HORIZONTAL)
+geMainTimer::geMainTimer()
+: geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
{
- 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);
- 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 = new geButton();
+ m_meter = new geButton();
+ m_quantizer = new geChoice();
+ m_multiplier = new geButton("", multiplyOff_xpm, multiplyOn_xpm);
+ m_divider = new geButton("", divideOff_xpm, divideOn_xpm);
+ add(m_quantizer, 60);
+ add(m_bpm, 60);
+ add(m_meter, 60);
+ add(m_multiplier, G_GUI_UNIT);
+ add(m_divider, G_GUI_UNIT);
+ end();
+
+ m_bpm->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TIMER_LABEL_BPM));
+ m_meter->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TIMER_LABEL_METER));
+ m_quantizer->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TIMER_LABEL_QUANTIZER));
+ m_multiplier->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TIMER_LABEL_MULTIPLIER));
+ m_divider->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TIMER_LABEL_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(g_ui.langMapper.get(LangMap::COMMON_OFF));
m_quantizer->addItem("1\\/1");
m_quantizer->addItem("1\\/2");
m_quantizer->addItem("1\\/3");
diff --git a/src/gui/elems/mainWindow/mainTimer.h b/src/gui/elems/mainWindow/mainTimer.h
index c1ee8d5..ef53b70 100644
--- a/src/gui/elems/mainWindow/mainTimer.h
+++ b/src/gui/elems/mainWindow/mainTimer.h
@@ -28,16 +28,16 @@
#define GE_MAIN_TIMER_H
#include "glue/main.h"
-#include "gui/elems/basics/pack.h"
+#include "gui/elems/basics/flex.h"
namespace giada::v
{
class geButton;
class geChoice;
-class geMainTimer : public gePack
+class geMainTimer : public geFlex
{
public:
- geMainTimer(int x, int y);
+ geMainTimer();
void refresh();
void rebuild();
diff --git a/src/gui/elems/mainWindow/mainTransport.cpp b/src/gui/elems/mainWindow/mainTransport.cpp
index c0d680a..c60553e 100644
--- a/src/gui/elems/mainWindow/mainTransport.cpp
+++ b/src/gui/elems/mainWindow/mainTransport.cpp
@@ -30,70 +30,71 @@
#include "core/graphics.h"
#include "glue/events.h"
#include "glue/main.h"
+#include "gui/elems/basics/box.h"
+#include "gui/elems/basics/button.h"
+#include "gui/elems/basics/flex.h"
+#include "gui/elems/basics/statusButton.h"
+#include "gui/ui.h"
+
+extern giada::v::Ui g_ui;
namespace giada::v
{
-geMainTransport::geMainTransport(int x, int y)
-: gePack(x, y, Direction::HORIZONTAL)
-, m_rewind(0, 0, 25, 25, "", rewindOff_xpm, rewindOn_xpm)
-, m_play(0, 0, 25, 25, play_xpm, pause_xpm)
-, m_spacer1(0, 0, 10, 25)
-, m_recTriggerMode(0, 0, 15, 25, recTriggerModeOff_xpm, recTriggerModeOn_xpm)
-, m_recAction(0, 0, 25, 25, recOff_xpm, recOn_xpm)
-, m_recInput(0, 0, 25, 25, inputRecOff_xpm, inputRecOn_xpm)
-, m_inputRecMode(0, 0, 15, 25, freeInputRecOff_xpm, freeInputRecOn_xpm)
-, m_spacer2(0, 0, 10, 25)
-, m_metronome(0, 0, 15, 25, metronomeOff_xpm, metronomeOn_xpm)
+geMainTransport::geMainTransport()
+: geFlex(Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
{
- add(&m_rewind);
- add(&m_play);
- add(&m_spacer1);
- add(&m_recTriggerMode);
- add(&m_recAction);
- add(&m_recInput);
- add(&m_inputRecMode);
- add(&m_spacer2);
- add(&m_metronome);
+ m_rewind = new geButton("", rewindOff_xpm, rewindOn_xpm);
+ m_play = new geStatusButton(play_xpm, pause_xpm);
+ m_recTriggerMode = new geStatusButton(recTriggerModeOff_xpm, recTriggerModeOn_xpm);
+ m_recAction = new geStatusButton(recOff_xpm, recOn_xpm);
+ m_recInput = new geStatusButton(inputRecOff_xpm, inputRecOn_xpm);
+ m_inputRecMode = new geStatusButton(freeInputRecOff_xpm, freeInputRecOn_xpm);
+ m_metronome = new geStatusButton(metronomeOff_xpm, metronomeOn_xpm);
+ add(m_rewind, 25);
+ add(m_play, 25);
+ add(new geBox(), 10);
+ add(m_recTriggerMode, 15);
+ add(m_recAction, 25);
+ add(m_recInput, 25);
+ add(m_inputRecMode, 15);
+ add(new geBox(), 10);
+ add(m_metronome, 15);
+ end();
- m_rewind.copy_tooltip("Rewind");
- m_play.copy_tooltip("Play/Stop");
- m_recTriggerMode.copy_tooltip("Record-on-signal mode\n\nIf enabled, action "
- "and audio recording will start only when a signal (key press or audio) "
- "is detected.");
- m_recAction.copy_tooltip("Record actions");
- m_recInput.copy_tooltip("Record audio");
- m_inputRecMode.copy_tooltip("Free loop-length mode\n\nIf enabled, the sequencer "
- "will adjust to the length of your first audio recording. "
- "Available only if there are no other audio samples in the "
- "project.");
- m_metronome.copy_tooltip("Metronome");
+ m_rewind->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_REWIND));
+ m_play->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_PLAY));
+ m_recTriggerMode->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_RECTRIGGERMODE));
+ m_recAction->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_RECACTIONS));
+ m_recInput->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_RECINPUT));
+ m_inputRecMode->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_RECINPUTMODE));
+ m_metronome->copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_TRANSPORT_LABEL_METRONOME));
- m_rewind.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_rewind->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::events::rewindSequencer(Thread::MAIN);
});
- m_play.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_play->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::events::toggleSequencer(Thread::MAIN);
});
- m_recAction.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_recAction->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::events::toggleActionRecording();
});
- m_recInput.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_recInput->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::events::toggleInputRecording();
});
- m_recTriggerMode.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_recTriggerMode->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::main::toggleRecOnSignal();
});
- m_inputRecMode.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_inputRecMode->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::main::toggleFreeInputRec();
});
- m_metronome.type(FL_TOGGLE_BUTTON);
- m_metronome.callback([](Fl_Widget* /*w*/, void* /*v*/) {
+ m_metronome->type(FL_TOGGLE_BUTTON);
+ m_metronome->callback([](Fl_Widget* /*w*/, void* /*v*/) {
c::events::toggleMetronome();
});
}
@@ -104,11 +105,11 @@ void geMainTransport::refresh()
{
c::main::Transport transport = c::main::getTransport();
- m_play.setStatus(transport.isRunning);
- m_recAction.setStatus(transport.isRecordingAction);
- m_recInput.setStatus(transport.isRecordingInput);
- m_metronome.setStatus(transport.isMetronomeOn);
- m_recTriggerMode.setStatus(transport.recTriggerMode == RecTriggerMode::SIGNAL);
- m_inputRecMode.setStatus(transport.inputRecMode == InputRecMode::FREE);
+ m_play->setStatus(transport.isRunning);
+ m_recAction->setStatus(transport.isRecordingAction);
+ m_recInput->setStatus(transport.isRecordingInput);
+ m_metronome->setStatus(transport.isMetronomeOn);
+ m_recTriggerMode->setStatus(transport.recTriggerMode == RecTriggerMode::SIGNAL);
+ m_inputRecMode->setStatus(transport.inputRecMode == InputRecMode::FREE);
}
} // namespace giada::v
diff --git a/src/gui/elems/mainWindow/mainTransport.h b/src/gui/elems/mainWindow/mainTransport.h
index f9e97a4..d752a24 100644
--- a/src/gui/elems/mainWindow/mainTransport.h
+++ b/src/gui/elems/mainWindow/mainTransport.h
@@ -27,30 +27,27 @@
#ifndef GE_MAIN_TRANSPORT_H
#define GE_MAIN_TRANSPORT_H
-#include "gui/elems/basics/box.h"
-#include "gui/elems/basics/button.h"
-#include "gui/elems/basics/pack.h"
-#include "gui/elems/basics/statusButton.h"
+#include "gui/elems/basics/flex.h"
namespace giada::v
{
-class geMainTransport : public gePack
+class geButton;
+class geStatusButton;
+class geMainTransport : public geFlex
{
public:
- geMainTransport(int x, int y);
+ geMainTransport();
void refresh();
private:
- geButton m_rewind;
- geStatusButton m_play;
- geBox m_spacer1;
- geStatusButton m_recTriggerMode;
- geStatusButton m_recAction;
- geStatusButton m_recInput;
- geStatusButton m_inputRecMode;
- geBox m_spacer2;
- geStatusButton m_metronome;
+ geButton* m_rewind;
+ geStatusButton* m_play;
+ geStatusButton* m_recTriggerMode;
+ geStatusButton* m_recAction;
+ geStatusButton* m_recInput;
+ geStatusButton* m_inputRecMode;
+ geStatusButton* m_metronome;
};
} // namespace giada::v
diff --git a/src/gui/elems/mainWindow/sequencer.cpp b/src/gui/elems/mainWindow/sequencer.cpp
index f0e38a5..b9bea8d 100644
--- a/src/gui/elems/mainWindow/sequencer.cpp
+++ b/src/gui/elems/mainWindow/sequencer.cpp
@@ -29,15 +29,18 @@
#include "sequencer.h"
#include "core/const.h"
#include "gui/drawing.h"
+#include "gui/ui.h"
#include "utils/math.h"
#include <FL/fl_draw.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
-geSequencer::geSequencer(int x, int y, int w, int h)
-: Fl_Box(x, y, w, h)
+geSequencer::geSequencer()
+: geBox()
{
- copy_tooltip("Main sequencer");
+ copy_tooltip(g_ui.langMapper.get(LangMap::MAIN_SEQUENCER_LABEL));
}
/* -------------------------------------------------------------------------- */
diff --git a/src/gui/elems/mainWindow/sequencer.h b/src/gui/elems/mainWindow/sequencer.h
index 1d6dab2..0242a04 100644
--- a/src/gui/elems/mainWindow/sequencer.h
+++ b/src/gui/elems/mainWindow/sequencer.h
@@ -32,14 +32,14 @@
#include "core/types.h"
#include "deps/geompp/src/rect.hpp"
#include "glue/main.h"
-#include <FL/Fl_Box.H>
+#include "gui/elems/basics/box.h"
namespace giada::v
{
-class geSequencer : public Fl_Box
+class geSequencer : public geBox
{
public:
- geSequencer(int x, int y, int w, int h);
+ geSequencer();
void draw() override;
diff --git a/src/gui/elems/midiIO/midiLearner.cpp b/src/gui/elems/midiIO/midiLearner.cpp
index e730c23..59c2b82 100644
--- a/src/gui/elems/midiIO/midiLearner.cpp
+++ b/src/gui/elems/midiIO/midiLearner.cpp
@@ -29,9 +29,12 @@
#include "gui/elems/basics/box.h"
#include "gui/elems/basics/boxtypes.h"
#include "gui/elems/basics/button.h"
+#include "gui/ui.h"
#include "utils/string.h"
#include <cassert>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
geMidiLearner::geMidiLearner(int x, int y, int w, int h, std::string l, int param)
@@ -43,7 +46,7 @@ geMidiLearner::geMidiLearner(int x, int y, int w, int h, std::string l, int para
{
m_text = new geBox(l.c_str());
m_valueBtn = new geButton();
- m_button = new geButton("learn");
+ m_button = new geButton(g_ui.langMapper.get(LangMap::COMMON_LEARN));
add(m_text);
add(m_valueBtn, 80);
@@ -77,7 +80,7 @@ geMidiLearner::geMidiLearner(int x, int y, int w, int h, std::string l, int para
void geMidiLearner::update(uint32_t value)
{
- std::string tmp = "(not set)";
+ std::string tmp = g_ui.langMapper.get(LangMap::COMMON_NOTSET);
if (value != 0x0)
{
diff --git a/src/gui/elems/midiIO/midiLearnerPack.cpp b/src/gui/elems/midiIO/midiLearnerPack.cpp
index c79b1ef..989186e 100644
--- a/src/gui/elems/midiIO/midiLearnerPack.cpp
+++ b/src/gui/elems/midiIO/midiLearnerPack.cpp
@@ -30,9 +30,7 @@
#include "gui/elems/basics/box.h"
#include <cassert>
-namespace giada
-{
-namespace v
+namespace giada::v
{
constexpr int LEARNER_WIDTH = 284;
@@ -86,5 +84,4 @@ void geMidiLearnerPack::setEnabled(bool v)
for (auto* l : learners)
l->deactivate();
}
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/midiIO/midiLearnerPack.h b/src/gui/elems/midiIO/midiLearnerPack.h
index 1622150..76129b8 100644
--- a/src/gui/elems/midiIO/midiLearnerPack.h
+++ b/src/gui/elems/midiIO/midiLearnerPack.h
@@ -32,9 +32,7 @@
#include <string>
#include <vector>
-namespace giada
-{
-namespace v
+namespace giada::v
{
class geMidiLearnerPack : public gePack
{
@@ -47,11 +45,10 @@ public:
std::vector<geMidiLearner*> learners;
- private:
+private:
std::function<void(uint32_t)> m_onStartLearn;
std::function<void(uint32_t)> m_onClearLearn;
};
-} // namespace v
-} // namespace giada
+} // namespace giada::v
#endif
diff --git a/src/gui/elems/plugin/pluginBrowser.cpp b/src/gui/elems/plugin/pluginBrowser.cpp
index 2a4d3dd..1f0d8b3 100644
--- a/src/gui/elems/plugin/pluginBrowser.cpp
+++ b/src/gui/elems/plugin/pluginBrowser.cpp
@@ -31,7 +31,11 @@
#include "core/plugins/pluginManager.h"
#include "glue/plugin.h"
#include "gui/elems/basics/boxtypes.h"
-#include <FL/fl_draw.H>
+#include "gui/ui.h"
+#include "utils/gui.h"
+#include <fmt/core.h>
+
+extern giada::v::Ui g_ui;
namespace giada::v
{
@@ -73,7 +77,7 @@ void gePluginBrowser::refresh()
{
clear();
- add("NAME\tMANUFACTURER\tCATEGORY\tFORMAT\tUID");
+ add(g_ui.langMapper.get(LangMap::PLUGINCHOOSER_HEADER));
add("---\t---\t---\t---\t---");
for (m::PluginManager::PluginInfo pi : c::plugin::getPluginsInfo())
@@ -83,11 +87,11 @@ void gePluginBrowser::refresh()
{
std::string m = pi.exists ? "" : "@-";
- s = m + pi.name + "\t" + m + pi.manufacturerName + "\t" + m +
- pi.category + "\t" + m + pi.format + "\t" + m + pi.uid;
+ s = fmt::format("{0}{1}\t{0}{2}\t{0}{3}\t{0}{4}\t{0}{5}",
+ m, pi.name, pi.manufacturerName, pi.category, pi.format, pi.uid);
}
else
- std::string s = "?\t?\t?\t?\t? " + pi.uid + " ?";
+ s = fmt::format("?\t?\t?\t?\t? {} ?", pi.uid);
add(s.c_str());
}
@@ -97,23 +101,20 @@ void gePluginBrowser::refresh()
void gePluginBrowser::computeWidths()
{
- int w0, w1, w3;
+ constexpr int PADDDING = 60;
+
for (m::PluginManager::PluginInfo pi : c::plugin::getPluginsInfo())
{
- w0 = static_cast<int>(fl_width(pi.name.c_str()));
- w1 = static_cast<int>(fl_width(pi.manufacturerName.c_str()));
- w3 = static_cast<int>(fl_width(pi.format.c_str()));
- if (w0 > m_widths[0])
- m_widths[0] = w0;
- if (w1 > m_widths[1])
- m_widths[1] = w1;
- if (w3 > m_widths[3])
- m_widths[3] = w3;
+ // Explicit type std::max<int> to fix MINMAX macro hell on Windows
+ m_widths[0] = std::max<int>(u::gui::getStringRect(pi.name).w, m_widths[0]);
+ m_widths[1] = std::max<int>(u::gui::getStringRect(pi.manufacturerName).w, m_widths[1]);
+ m_widths[2] = std::max<int>(u::gui::getStringRect(pi.category).w, m_widths[2]);
+ m_widths[3] = std::max<int>(u::gui::getStringRect(pi.format).w, m_widths[3]);
}
- m_widths[0] += 60;
- m_widths[1] += 60;
- m_widths[2] = static_cast<int>(fl_width("CATEGORY") + 60);
- m_widths[3] += 60;
+ m_widths[0] += PADDDING;
+ m_widths[1] += PADDDING;
+ m_widths[2] += PADDDING;
+ m_widths[3] += PADDDING;
m_widths[4] = 0;
}
} // namespace giada::v
diff --git a/src/gui/elems/plugin/pluginElement.cpp b/src/gui/elems/plugin/pluginElement.cpp
index 34eecda..43ce016 100644
--- a/src/gui/elems/plugin/pluginElement.cpp
+++ b/src/gui/elems/plugin/pluginElement.cpp
@@ -37,11 +37,14 @@
#include "gui/dialogs/pluginWindowGUI.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/choice.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/log.h"
#include <cassert>
#include <string>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gePluginElement::gePluginElement(int x, int y, c::plugin::Plugin data)
@@ -87,7 +90,8 @@ gePluginElement::gePluginElement(int x, int y, c::plugin::Plugin data)
if (program.countItems() == 0)
{
- program.addItem("-- no programs --\0");
+ program.addItem(g_ui.langMapper.get(LangMap::PLUGINLIST_NOPROGRAMS));
+ program.showItem(0);
program.deactivate();
}
else
diff --git a/src/gui/elems/sampleEditor/boostTool.cpp b/src/gui/elems/sampleEditor/boostTool.cpp
deleted file mode 100644
index 5c8dea0..0000000
--- a/src/gui/elems/sampleEditor/boostTool.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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 "boostTool.h"
-#include "core/const.h"
-#include "core/waveFx.h"
-#include "glue/channel.h"
-#include "gui/dialogs/sampleEditor.h"
-#include "gui/elems/basics/box.h"
-#include "gui/elems/basics/button.h"
-#include "gui/elems/basics/dial.h"
-#include "gui/elems/basics/input.h"
-#include "utils/gui.h"
-#include "utils/math.h"
-#include "utils/string.h"
-#include "waveTools.h"
-#include <FL/Fl.H>
-
-namespace giada::v
-{
-geBoostTool::geBoostTool(int X, int Y)
-: Fl_Pack(X, Y, 220, G_GUI_UNIT)
-{
- type(Fl_Pack::HORIZONTAL);
- spacing(G_GUI_INNER_MARGIN);
-
- begin();
- label = new geBox(0, 0, u::gui::getStringRect("Boost").w, G_GUI_UNIT, "Boost", FL_ALIGN_RIGHT);
- dial = new geDial(0, 0, G_GUI_UNIT, G_GUI_UNIT);
- input = new geInput(0, 0, 70, G_GUI_UNIT);
- normalize = new geButton(0, 0, 70, G_GUI_UNIT, "Normalize");
- end();
-
- dial->range(1.0f, 10.0f);
- dial->callback(cb_setBoost, (void*)this);
- dial->when(FL_WHEN_CHANGED | FL_WHEN_RELEASE);
-
- input->callback(cb_setBoostNum, (void*)this);
-
- normalize->callback(cb_normalize, (void*)this);
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBoostTool::rebuild()
-{
- /*
- const m::SampleChannel* ch = static_cast<gdSampleEditor*>(window())->ch;
-
- input->value(u::string::fToString(u::math::linearToDB(ch->getBoost()), 2).c_str()); // 2 digits
- // A dial greater than it's max value goes crazy
- dial->value(ch->getBoost() <= 10.0f ? ch->getBoost() : 10.0f);*/
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBoostTool::cb_setBoost(Fl_Widget* /*w*/, void* p) { ((geBoostTool*)p)->cb_setBoost(); }
-void geBoostTool::cb_setBoostNum(Fl_Widget* /*w*/, void* p) { ((geBoostTool*)p)->cb_setBoostNum(); }
-void geBoostTool::cb_normalize(Fl_Widget* /*w*/, void* p) { ((geBoostTool*)p)->cb_normalize(); }
-
-/* -------------------------------------------------------------------------- */
-
-void geBoostTool::cb_setBoost()
-{
- /*const m::SampleChannel* ch = static_cast<gdSampleEditor*>(window())->ch;
-
- c::channel::setBoost(ch->id, dial->value());*/
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBoostTool::cb_setBoostNum()
-{
- /*const m::SampleChannel* ch = static_cast<gdSampleEditor*>(window())->ch;
-
- c::channel::setBoost(ch->id, u::math::dBtoLinear(atof(input->value())));*/
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBoostTool::cb_normalize()
-{
-}
-} // namespace giada::v
diff --git a/src/gui/elems/sampleEditor/panTool.cpp b/src/gui/elems/sampleEditor/panTool.cpp
index bcf685b..cee5e7d 100644
--- a/src/gui/elems/sampleEditor/panTool.cpp
+++ b/src/gui/elems/sampleEditor/panTool.cpp
@@ -30,23 +30,24 @@
#include "core/waveFx.h"
#include "glue/events.h"
#include "gui/dialogs/sampleEditor.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/math.h"
#include "utils/string.h"
#include "waveTools.h"
#include <FL/Fl.H>
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
gePanTool::gePanTool(const c::sampleEditor::Data& d, int x, int y)
: gePack(x, y, Direction::HORIZONTAL)
, m_data(nullptr)
-, m_label(0, 0, 60, G_GUI_UNIT, "Pan", FL_ALIGN_LEFT)
+, m_label(0, 0, 60, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_PAN), FL_ALIGN_LEFT)
, m_dial(0, 0, G_GUI_UNIT, G_GUI_UNIT)
, m_input(0, 0, 70, G_GUI_UNIT)
-, m_reset(0, 0, 70, G_GUI_UNIT, "Reset")
+, m_reset(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_RESET))
{
add(&m_label);
add(&m_dial);
@@ -111,5 +112,4 @@ void gePanTool::cb_panReset()
{
c::events::sendChannelPan(m_data->channelId, 0.5f);
}
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/sampleEditor/pitchTool.cpp b/src/gui/elems/sampleEditor/pitchTool.cpp
index 69cad2b..4df2634 100644
--- a/src/gui/elems/sampleEditor/pitchTool.cpp
+++ b/src/gui/elems/sampleEditor/pitchTool.cpp
@@ -35,23 +35,26 @@
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/dial.h"
#include "gui/elems/basics/input.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <FL/Fl.H>
+extern giada::v::Ui g_ui;
+
namespace giada::v
{
gePitchTool::gePitchTool(const c::sampleEditor::Data& d, int x, int y)
: gePack(x, y, Direction::HORIZONTAL)
, m_data(nullptr)
-, m_label(0, 0, 60, G_GUI_UNIT, "Pitch", FL_ALIGN_LEFT)
+, m_label(0, 0, 60, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_PITCH), FL_ALIGN_LEFT)
, m_dial(0, 0, G_GUI_UNIT, G_GUI_UNIT)
, m_input(0, 0, 70, G_GUI_UNIT)
-, m_pitchToBar(0, 0, 70, G_GUI_UNIT, "To bar")
-, m_pitchToSong(0, 0, 70, G_GUI_UNIT, "To song")
+, m_pitchToBar(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_PITCH_TOBAR))
+, m_pitchToSong(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_PITCH_TOSONG))
, m_pitchHalf(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", divideOff_xpm, divideOn_xpm)
, m_pitchDouble(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", multiplyOff_xpm, multiplyOn_xpm)
-, m_pitchReset(0, 0, 70, G_GUI_UNIT, "Reset")
+, m_pitchReset(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_RESET))
{
add(&m_label);
add(&m_dial);
diff --git a/src/gui/elems/sampleEditor/rangeTool.cpp b/src/gui/elems/sampleEditor/rangeTool.cpp
index 8f8e85d..b27a1ac 100644
--- a/src/gui/elems/sampleEditor/rangeTool.cpp
+++ b/src/gui/elems/sampleEditor/rangeTool.cpp
@@ -30,23 +30,24 @@
#include "glue/channel.h"
#include "glue/sampleEditor.h"
#include "gui/dialogs/sampleEditor.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include "waveTools.h"
#include <FL/Fl.H>
#include <cassert>
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
geRangeTool::geRangeTool(const c::sampleEditor::Data& d, int x, int y)
: gePack(x, y, Direction::HORIZONTAL)
, m_data(nullptr)
-, m_label(0, 0, 60, G_GUI_UNIT, "Range", FL_ALIGN_LEFT)
+, m_label(0, 0, 60, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_RANGE), FL_ALIGN_LEFT)
, m_begin(0, 0, 70, G_GUI_UNIT)
, m_end(0, 0, 70, G_GUI_UNIT)
-, m_reset(0, 0, 70, G_GUI_UNIT, "Reset")
+, m_reset(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_RESET))
{
add(&m_label);
add(&m_begin);
@@ -100,6 +101,4 @@ void geRangeTool::cb_resetStartEnd()
{
c::sampleEditor::setBeginEnd(m_data->channelId, 0, m_data->waveSize - 1);
}
-
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/sampleEditor/shiftTool.cpp b/src/gui/elems/sampleEditor/shiftTool.cpp
index f5c56c3..faec3f9 100644
--- a/src/gui/elems/sampleEditor/shiftTool.cpp
+++ b/src/gui/elems/sampleEditor/shiftTool.cpp
@@ -30,21 +30,22 @@
#include "glue/sampleEditor.h"
#include "gui/dialogs/sampleEditor.h"
#include "gui/dialogs/warnings.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/string.h"
#include <cassert>
#include <cstdlib>
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
geShiftTool::geShiftTool(const c::sampleEditor::Data& d, int x, int y)
: gePack(x, y, Direction::HORIZONTAL)
, m_data(nullptr)
-, m_label(0, 0, 60, G_GUI_UNIT, "Shift", FL_ALIGN_LEFT)
+, m_label(0, 0, 60, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_SHIFT), FL_ALIGN_LEFT)
, m_shift(0, 0, 70, G_GUI_UNIT)
-, m_reset(0, 0, 70, G_GUI_UNIT, "Reset")
+, m_reset(0, 0, 70, G_GUI_UNIT, g_ui.langMapper.get(LangMap::COMMON_RESET))
{
add(&m_label);
add(&m_shift);
@@ -99,5 +100,4 @@ void geShiftTool::shift(int f)
{
c::sampleEditor::shift(m_data->channelId, f);
}
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/sampleEditor/volumeTool.cpp b/src/gui/elems/sampleEditor/volumeTool.cpp
index 5fd7d25..08fd433 100644
--- a/src/gui/elems/sampleEditor/volumeTool.cpp
+++ b/src/gui/elems/sampleEditor/volumeTool.cpp
@@ -29,6 +29,7 @@
#include "glue/events.h"
#include "gui/dialogs/sampleEditor.h"
#include "gui/elems/mainWindow/keyboard/channel.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "utils/math.h"
#include "utils/string.h"
@@ -36,14 +37,14 @@
#include <cmath>
#include <cstdlib>
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
geVolumeTool::geVolumeTool(const c::sampleEditor::Data& d, int x, int y)
: gePack(x, y, Direction::HORIZONTAL)
, m_data(nullptr)
-, m_label(0, 0, 60, G_GUI_UNIT, "Volume", FL_ALIGN_LEFT)
+, m_label(0, 0, 60, G_GUI_UNIT, g_ui.langMapper.get(LangMap::SAMPLEEDITOR_VOLUME), FL_ALIGN_LEFT)
, m_dial(0, 0, G_GUI_UNIT, G_GUI_UNIT)
, m_input(0, 0, 70, G_GUI_UNIT)
{
@@ -99,5 +100,4 @@ void geVolumeTool::cb_setVolumeNum()
c::events::setChannelVolume(m_data->channelId, u::math::dBtoLinear(atof(m_input.value())),
Thread::MAIN);
}
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/elems/sampleEditor/waveTools.cpp b/src/gui/elems/sampleEditor/waveTools.cpp
index e271d3c..0a1d51b 100644
--- a/src/gui/elems/sampleEditor/waveTools.cpp
+++ b/src/gui/elems/sampleEditor/waveTools.cpp
@@ -31,15 +31,16 @@
#include "glue/sampleEditor.h"
#include "gui/dialogs/sampleEditor.h"
#include "gui/elems/basics/boxtypes.h"
+#include "gui/ui.h"
#include "utils/gui.h"
#include "waveform.h"
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <cstdint>
-namespace giada
-{
-namespace v
+extern giada::v::Ui g_ui;
+
+namespace giada::v
{
namespace
{
@@ -198,18 +199,18 @@ int geWaveTools::handle(int e)
void geWaveTools::openMenu()
{
Fl_Menu_Item menu[] = {
- u::gui::makeMenuItem("Cut", menuCallback_, (void*)Menu::CUT),
- u::gui::makeMenuItem("Copy", menuCallback_, (void*)Menu::COPY),
- u::gui::makeMenuItem("Paste", menuCallback_, (void*)Menu::PASTE),
- u::gui::makeMenuItem("Trim", menuCallback_, (void*)Menu::TRIM),
- u::gui::makeMenuItem("Silence", menuCallback_, (void*)Menu::SILENCE),
- u::gui::makeMenuItem("Reverse", menuCallback_, (void*)Menu::REVERSE),
- u::gui::makeMenuItem("Normalize", menuCallback_, (void*)Menu::NORMALIZE),
- u::gui::makeMenuItem("Fade in", menuCallback_, (void*)Menu::FADE_IN),
- u::gui::makeMenuItem("Fade out", menuCallback_, (void*)Menu::FADE_OUT),
- u::gui::makeMenuItem("Smooth edges", menuCallback_, (void*)Menu::SMOOTH_EDGES),
- u::gui::makeMenuItem("Set begin/end here", menuCallback_, (void*)Menu::SET_BEGIN_END),
- u::gui::makeMenuItem("Copy to new channel", menuCallback_, (void*)Menu::TO_NEW_CHANNEL),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_CUT), menuCallback_, (void*)Menu::CUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_COPY), menuCallback_, (void*)Menu::COPY),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_PASTE), menuCallback_, (void*)Menu::PASTE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_TRIM), menuCallback_, (void*)Menu::TRIM),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_SILENCE), menuCallback_, (void*)Menu::SILENCE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_REVERSE), menuCallback_, (void*)Menu::REVERSE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_NORMALIZE), menuCallback_, (void*)Menu::NORMALIZE),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_FADE_IN), menuCallback_, (void*)Menu::FADE_IN),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_FADE_OUT), menuCallback_, (void*)Menu::FADE_OUT),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_SMOOTH_EDGES), menuCallback_, (void*)Menu::SMOOTH_EDGES),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_SET_BEGIN_END), menuCallback_, (void*)Menu::SET_BEGIN_END),
+ u::gui::makeMenuItem(g_ui.langMapper.get(LangMap::SAMPLEEDITOR_TOOLS_TO_NEW_CHANNEL), menuCallback_, (void*)Menu::TO_NEW_CHANNEL),
{}};
if (!waveform->isSelected())
@@ -239,6 +240,4 @@ void geWaveTools::openMenu()
return;
}
-
-} // namespace v
-} // namespace giada
+} // namespace giada::v \ No newline at end of file
diff --git a/src/gui/langMapper.cpp b/src/gui/langMapper.cpp
new file mode 100644
index 0000000..d7ceeca
--- /dev/null
+++ b/src/gui/langMapper.cpp
@@ -0,0 +1,388 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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/langMapper.h"
+#include "utils/fs.h"
+#include "utils/log.h"
+#include <filesystem>
+#include <fstream>
+
+namespace nl = nlohmann;
+
+namespace giada::v
+{
+LangMap::LangMap()
+: m_default("[Not set]")
+{
+ m_data[COMMON_OK] = "Ok";
+ m_data[COMMON_CANCEL] = "Cancel";
+ m_data[COMMON_YES] = "Yes";
+ m_data[COMMON_NO] = "No";
+ m_data[COMMON_OFF] = "Off";
+ m_data[COMMON_SELECT] = "Select";
+ m_data[COMMON_LOAD] = "Load";
+ m_data[COMMON_SAVE] = "Save";
+ m_data[COMMON_WARNING] = "Warning";
+ m_data[COMMON_CLOSE] = "Close";
+ m_data[COMMON_ADD] = "Add";
+ m_data[COMMON_CLEAR] = "Clear";
+ m_data[COMMON_RELOAD] = "Reload";
+ m_data[COMMON_RESET] = "Reset";
+ m_data[COMMON_ZOOMIN] = "Zoom in";
+ m_data[COMMON_ZOOMOUT] = "Zoom out";
+ m_data[COMMON_GRIDRES] = "Grid resolution";
+ m_data[COMMON_SNAPTOGRID] = "Snap to grid";
+ m_data[COMMON_BIND] = "Bind";
+ m_data[COMMON_LEARN] = "Learn";
+ m_data[COMMON_NOTSET] = "(not set)";
+ m_data[COMMON_NONE] = "None";
+
+ m_data[MESSAGE_MAIN_FREEALLSAMPLES] = "Free all Sample channels: are you sure?";
+ m_data[MESSAGE_MAIN_CLEARALLACTIONS] = "Clear all actions: are you sure?";
+ m_data[MESSAGE_MAIN_CLEARALLVOLUMEACTIONS] = "Clear all volume actions: are you sure?";
+ m_data[MESSAGE_MAIN_CLEARALLSTARTSTOPACTIONS] = "Clear all start/stop actions: are you sure?";
+ m_data[MESSAGE_MAIN_CLOSEPROJECT] = "Close project: are you sure?";
+
+ m_data[MESSAGE_INIT_WRONGSYSTEM] = "Your soundcard isn't configured correctly.\n"
+ "Check the configuration and restart Giada.";
+ m_data[MESSAGE_INIT_QUITGIADA] = "Quit Giada: are you sure?";
+
+ m_data[MESSAGE_CHANNEL_MULTICHANNOTSUPPORTED] = "Multichannel samples not supported.";
+ m_data[MESSAGE_CHANNEL_CANTREADSAMPLE] = "Unable to read this sample.";
+ m_data[MESSAGE_CHANNEL_PATHTOOLONG] = "File path too long.";
+ m_data[MESSAGE_CHANNEL_NOFILESPECIFIED] = "No file specified.";
+ m_data[MESSAGE_CHANNEL_LOADINGSAMPLES] = "Loading samples...";
+ m_data[MESSAGE_CHANNEL_LOADINGSAMPLESERROR] = "Some files weren't loaded successfully.";
+ m_data[MESSAGE_CHANNEL_DELETE] = "Delete channel: are you sure?";
+ m_data[MESSAGE_CHANNEL_FREE] = "Free channel: are you sure?";
+
+ m_data[MESSAGE_STORAGE_PATCHUNREADABLE] = "This patch is unreadable.";
+ m_data[MESSAGE_STORAGE_PATCHINVALID] = "This patch is not valid.";
+ m_data[MESSAGE_STORAGE_PATCHUNSUPPORTED] = "This patch format is no longer supported.";
+ m_data[MESSAGE_STORAGE_PROJECTEXISTS] = "Project exists: overwrite?";
+ m_data[MESSAGE_STORAGE_LOADINGPROJECT] = "Loading project...";
+ m_data[MESSAGE_STORAGE_LOADINGSAMPLE] = "Loading sample...";
+ m_data[MESSAGE_STORAGE_SAVINGPROJECT] = "Saving project...";
+ m_data[MESSAGE_STORAGE_SAVINGPROJECTERROR] = "Unable to save the project!";
+ m_data[MESSAGE_STORAGE_CHOOSEPROJECTNAME] = "Please choose a project name.";
+ m_data[MESSAGE_STORAGE_CHOOSEFILENAME] = "Please choose a file name.";
+ m_data[MESSAGE_STORAGE_FILEEXISTS] = "File exists: overwrite?";
+ m_data[MESSAGE_STORAGE_SAVINGFILEERROR] = "Unable to save this sample!";
+
+ m_data[MAIN_MENU_FILE] = "File";
+ m_data[MAIN_MENU_FILE_OPENPROJECT] = "Open project...";
+ m_data[MAIN_MENU_FILE_SAVEPROJECT] = "Save project...";
+ m_data[MAIN_MENU_FILE_CLOSEPROJECT] = "Close project";
+ m_data[MAIN_MENU_FILE_QUIT] = "Quit Giada";
+ m_data[MAIN_MENU_EDIT] = "Edit";
+ m_data[MAIN_MENU_EDIT_FREEALLSAMPLES] = "Free all Sample channels";
+ m_data[MAIN_MENU_EDIT_CLEARALLACTIONS] = "Clear all actions";
+ m_data[MAIN_MENU_EDIT_SETUPMIDIINPUT] = "Setup global MIDI input...";
+ m_data[MAIN_MENU_CONFIG] = "Config";
+ m_data[MAIN_MENU_ABOUT] = "About";
+
+ m_data[MAIN_IO_LABEL_OUTMETER] = "Main output meter";
+ m_data[MAIN_IO_LABEL_INMETER] = "Main input meter";
+ m_data[MAIN_IO_LABEL_OUTVOL] = "Main output volume";
+ m_data[MAIN_IO_LABEL_INVOL] = "Main input volume";
+ m_data[MAIN_IO_LABEL_INTOOUT] = "Stream linker\n\nConnects input to output to enable \"hear what you're playing\" mode.";
+ m_data[MAIN_IO_LABEL_FXOUT] = "Main output plug-ins";
+ m_data[MAIN_IO_LABEL_FXIN] = "Main input plug-ins";
+
+ m_data[MAIN_TIMER_LABEL_BPM] = "Beats per minute (BPM)";
+ m_data[MAIN_TIMER_LABEL_METER] = "Beats and bars";
+ m_data[MAIN_TIMER_LABEL_QUANTIZER] = "Live quantizer";
+ m_data[MAIN_TIMER_LABEL_MULTIPLIER] = "Beat multiplier";
+ m_data[MAIN_TIMER_LABEL_DIVIDER] = "Beat divider";
+
+ m_data[MAIN_SEQUENCER_LABEL] = "Main sequencer";
+
+ m_data[MAIN_TRANSPORT_LABEL_REWIND] = "Rewind";
+ m_data[MAIN_TRANSPORT_LABEL_PLAY] = "Play/Stop";
+ m_data[MAIN_TRANSPORT_LABEL_RECTRIGGERMODE] = "Record-on-signal mode\n\nIf enabled, action "
+ "and audio recording will start only when a signal (key press or audio) "
+ "is detected.";
+ m_data[MAIN_TRANSPORT_LABEL_RECACTIONS] = "Record actions";
+ m_data[MAIN_TRANSPORT_LABEL_RECINPUT] = "Record audio";
+ m_data[MAIN_TRANSPORT_LABEL_RECINPUTMODE] = "Free loop-length mode\n\nIf enabled, the sequencer "
+ "will adjust to the length of your first audio recording. "
+ "Available only if there are no other audio samples in the "
+ "project.";
+ m_data[MAIN_TRANSPORT_LABEL_METRONOME] = "Metronome";
+
+ m_data[MAIN_COLUMN_BUTTON] = "Edit column";
+ m_data[MAIN_COLUMN_BUTTON_ADDSAMPLECHANNEL] = "Add Sample channel";
+ m_data[MAIN_COLUMN_BUTTON_ADDMIDICHANNEL] = "Add MIDI channel";
+ m_data[MAIN_COLUMN_BUTTON_REMOVE] = "Remove";
+
+ m_data[MAIN_CHANNEL_NOSAMPLE] = "-- no sample --";
+ m_data[MAIN_CHANNEL_SAMPLENOTFOUND] = "* file not found! *";
+ m_data[MAIN_CHANNEL_LABEL_PLAY] = "Play/stop";
+ m_data[MAIN_CHANNEL_LABEL_ARM] = "Arm for recording";
+ m_data[MAIN_CHANNEL_LABEL_STATUS] = "Progress bar";
+ m_data[MAIN_CHANNEL_LABEL_READACTIONS] = "Read actions\n\nToggles playback of pre-recorded "
+ "actions (key press, key release, ...).";
+ m_data[MAIN_CHANNEL_LABEL_MODEBOX] = "Mode";
+ m_data[MAIN_CHANNEL_LABEL_MUTE] = "Mute";
+ m_data[MAIN_CHANNEL_LABEL_SOLO] = "Solo";
+ m_data[MAIN_CHANNEL_LABEL_FX] = "Plug-ins";
+ m_data[MAIN_CHANNEL_LABEL_VOLUME] = "Volume";
+ m_data[MAIN_CHANNEL_LABEL_MIDIACTIVITY] = "MIDI I/O activity\n\nNotifies MIDI messages sent (top) or "
+ "received (bottom) by this channel.";
+
+ m_data[MAIN_CHANNEL_MENU_INPUTMONITOR] = "Input monitor";
+ m_data[MAIN_CHANNEL_MENU_OVERDUBPROTECTION] = "Overdub protection";
+ m_data[MAIN_CHANNEL_MENU_LOADSAMPLE] = "Load new sample...";
+ m_data[MAIN_CHANNEL_MENU_EXPORTSAMPLE] = "Export sample to file...";
+ m_data[MAIN_CHANNEL_MENU_KEYBOARDINPUT] = "Setup keyboard input...";
+ m_data[MAIN_CHANNEL_MENU_MIDIINPUT] = "Setup MIDI input...";
+ m_data[MAIN_CHANNEL_MENU_MIDIOUTPUT] = "Setup MIDI output...";
+ m_data[MAIN_CHANNEL_MENU_EDITSAMPLE] = "Edit sample...";
+ m_data[MAIN_CHANNEL_MENU_EDITACTIONS] = "Edit actions...";
+ m_data[MAIN_CHANNEL_MENU_CLEARACTIONS] = "Clear actions";
+ m_data[MAIN_CHANNEL_MENU_CLEARACTIONS_ALL] = "All";
+ m_data[MAIN_CHANNEL_MENU_CLEARACTIONS_VOLUME] = "Volume";
+ m_data[MAIN_CHANNEL_MENU_CLEARACTIONS_STARTSTOP] = "Start/Stop";
+ m_data[MAIN_CHANNEL_MENU_RENAME] = "Rename";
+ m_data[MAIN_CHANNEL_MENU_CLONE] = "Clone";
+ m_data[MAIN_CHANNEL_MENU_FREE] = "Free";
+ m_data[MAIN_CHANNEL_MENU_DELETE] = "Delete";
+
+ m_data[MISSINGASSETS_INTRO] = "This project contains missing assets.";
+ m_data[MISSINGASSETS_AUDIOFILES] = "Audio files not found in the project folder:";
+ m_data[MISSINGASSETS_PLUGINS] = "Audio plug-ins not found globally:";
+
+ m_data[PLUGINCHOOSER_TITLE] = "Available plugins";
+ m_data[PLUGINCHOOSER_HEADER] = "NAME\tMANUFACTURER\tCATEGORY\tFORMAT\tUID";
+ m_data[PLUGINCHOOSER_SORTBY] = "Sort by";
+ m_data[PLUGINCHOOSER_SORTBY_NAME] = "Name";
+ m_data[PLUGINCHOOSER_SORTBY_CATEGORY] = "Category";
+ m_data[PLUGINCHOOSER_SORTBY_MANIFACTURER] = "Manifacturer";
+ m_data[PLUGINCHOOSER_SORTBY_FORMAT] = "Format";
+
+ m_data[PLUGINLIST_TITLE_MASTEROUT] = "Master Out Plug-ins";
+ m_data[PLUGINLIST_TITLE_MASTERIN] = "Master In Plug-ins";
+ m_data[PLUGINLIST_TITLE_CHANNEL] = "Channel Plug-ins";
+ m_data[PLUGINLIST_ADDPLUGIN] = "-- add new plugin --";
+ m_data[PLUGINLIST_NOPROGRAMS] = "-- no programs --";
+
+ m_data[CHANNELNAME_TITLE] = "New channel name";
+
+ m_data[KEYGRABBER_TITLE] = "Key configuration";
+ m_data[KEYGRABBER_BODY] = "Press a key.\n\nCurrent binding: ";
+
+ m_data[SAMPLEEDITOR_TITLE] = "Sample Editor";
+ m_data[SAMPLEEDITOR_RELOAD] = "Reload";
+ m_data[SAMPLEEDITOR_LOOP] = "Loop";
+ m_data[SAMPLEEDITOR_INFO] = "File: {}\nSize: {} frames\nDuration {} seconds\nBit depth: {}\nFrequency: {} Hz";
+ m_data[SAMPLEEDITOR_PAN] = "Pan";
+ m_data[SAMPLEEDITOR_PITCH] = "Pitch";
+ m_data[SAMPLEEDITOR_PITCH_TOBAR] = "To bar";
+ m_data[SAMPLEEDITOR_PITCH_TOSONG] = "To song";
+ m_data[SAMPLEEDITOR_RANGE] = "Range";
+ m_data[SAMPLEEDITOR_SHIFT] = "Shift";
+ m_data[SAMPLEEDITOR_VOLUME] = "Volume";
+ m_data[SAMPLEEDITOR_TOOLS_CUT] = "Cut";
+ m_data[SAMPLEEDITOR_TOOLS_COPY] = "Copy";
+ m_data[SAMPLEEDITOR_TOOLS_PASTE] = "Paste";
+ m_data[SAMPLEEDITOR_TOOLS_TRIM] = "Trim";
+ m_data[SAMPLEEDITOR_TOOLS_SILENCE] = "Silence";
+ m_data[SAMPLEEDITOR_TOOLS_REVERSE] = "Reverse";
+ m_data[SAMPLEEDITOR_TOOLS_NORMALIZE] = "Normalize";
+ m_data[SAMPLEEDITOR_TOOLS_FADE_IN] = "Fade in";
+ m_data[SAMPLEEDITOR_TOOLS_FADE_OUT] = "Fade out";
+ m_data[SAMPLEEDITOR_TOOLS_SMOOTH_EDGES] = "Smooth edges";
+ m_data[SAMPLEEDITOR_TOOLS_SET_BEGIN_END] = "Set begin/end here";
+ m_data[SAMPLEEDITOR_TOOLS_TO_NEW_CHANNEL] = "Copy to new channel";
+
+ m_data[ACTIONEDITOR_TITLE] = "Action Editor";
+ m_data[ACTIONEDITOR_VOLUME] = "Volume";
+ m_data[ACTIONEDITOR_KEYPRESS] = "Key press";
+ m_data[ACTIONEDITOR_KEYRELEASE] = "Key release";
+ m_data[ACTIONEDITOR_STOPSAMPLE] = "Stop sample";
+ m_data[ACTIONEDITOR_STARTSTOP] = "Start/stop";
+ m_data[ACTIONEDITOR_STARTSTOPDISABLED] = "Start/stop (disabled)";
+ m_data[ACTIONEDITOR_VELOCITY] = "Velocity";
+ m_data[ACTIONEDITOR_LABEL_ACTIONTYPE] = "Action type to add";
+
+ m_data[BROWSER_SHOWHIDDENFILES] = "Show hidden files";
+ m_data[BROWSER_OPENPROJECT] = "Open project";
+ m_data[BROWSER_SAVEPROJECT] = "Save project";
+ m_data[BROWSER_OPENSAMPLE] = "Open sample";
+ m_data[BROWSER_SAVESAMPLE] = "Save sample";
+ m_data[BROWSER_OPENPLUGINSDIR] = "Open plug-ins directory";
+
+ m_data[MIDIINPUT_MASTER_TITLE] = "MIDI Input Setup (global)";
+ m_data[MIDIINPUT_MASTER_ENABLE] = "Enable MIDI input";
+ m_data[MIDIINPUT_MASTER_LEARN_REWIND] = "Rewind";
+ m_data[MIDIINPUT_MASTER_LEARN_PLAYSTOP] = "Play/stop";
+ m_data[MIDIINPUT_MASTER_LEARN_ACTIONREC] = "Action recording";
+ m_data[MIDIINPUT_MASTER_LEARN_INPUTREC] = "Input recording";
+ m_data[MIDIINPUT_MASTER_LEARN_METRONOME] = "metronome";
+ m_data[MIDIINPUT_MASTER_LEARN_INVOLUME] = "Input volume";
+ m_data[MIDIINPUT_MASTER_LEARN_OUTVOLUME] = "Output volume";
+ m_data[MIDIINPUT_MASTER_LEARN_SEQDOUBLE] = "Sequencer ×2";
+ m_data[MIDIINPUT_MASTER_LEARN_SEQHALF] = "Sequencer ÷2";
+
+ m_data[MIDIINPUT_CHANNEL_TITLE] = "MIDI Input Setup";
+ m_data[MIDIINPUT_CHANNEL_ENABLE] = "Enable MIDI input";
+ m_data[MIDIINPUT_CHANNEL_VELOCITYDRIVESVOL] = "Velocity drives volume (Sample Channels)";
+ m_data[MIDIINPUT_CHANNEL_LEARN_CHANNEL] = "Channel";
+ m_data[MIDIINPUT_CHANNEL_LEARN_KEYPRESS] = "Key press";
+ m_data[MIDIINPUT_CHANNEL_LEARN_KEYREL] = "Key release";
+ m_data[MIDIINPUT_CHANNEL_LEARN_KEYKILL] = "Key kill";
+ m_data[MIDIINPUT_CHANNEL_LEARN_ARM] = "Arm";
+ m_data[MIDIINPUT_CHANNEL_LEARN_MUTE] = "Mute";
+ m_data[MIDIINPUT_CHANNEL_LEARN_SOLO] = "Solo";
+ m_data[MIDIINPUT_CHANNEL_LEARN_VOLUME] = "Volume";
+ m_data[MIDIINPUT_CHANNEL_LEARN_PITCH] = "Pitch";
+ m_data[MIDIINPUT_CHANNEL_LEARN_READACTIONS] = "Read actions";
+
+ m_data[MIDIOUTPUT_CHANNEL_TITLE] = "Midi Output Setup";
+ m_data[MIDIOUTPUT_CHANNEL_ENABLE] = "Enable MIDI output";
+ m_data[MIDIOUTPUT_CHANNEL_ENABLE_LIGHTNING] = "Enable MIDI lightning output";
+ m_data[MIDIOUTPUT_CHANNEL_LEARN_PLAYING] = "Playing";
+ m_data[MIDIOUTPUT_CHANNEL_LEARN_MUTE] = "Mute";
+ m_data[MIDIOUTPUT_CHANNEL_LEARN_SOLO] = "Solo";
+
+ m_data[ABOUT_TITLE] = "About Giada";
+ m_data[ABOUT_BODY] = "Version {} ({} build) {}\n\n"
+ "Developed by Monocasual Laboratories\n\n"
+ "Released under the terms of the GNU General\n"
+ "Public License (GPL v3)\n\n"
+ "News, infos, contacts and documentation:\n"
+ "www.giadamusic.com";
+ m_data[ABOUT_BODY_VST] = "VST Plug-In Technology by Steinberg\n"
+ "VST is a trademark of Steinberg\nMedia Technologies GmbH";
+
+ m_data[CONFIG_TITLE] = "Configuration";
+ m_data[CONFIG_RESTARTGIADA] = "Restart Giada for the changes to take effect.";
+
+ m_data[CONFIG_AUDIO_TITLE] = "Audio";
+ m_data[CONFIG_AUDIO_SYSTEM] = "System";
+ m_data[CONFIG_AUDIO_BUFFERSIZE] = "Buffer size";
+ m_data[CONFIG_AUDIO_SAMPLERATE] = "Sample rate";
+ m_data[CONFIG_AUDIO_OUTPUTDEVICE] = "Output device";
+ m_data[CONFIG_AUDIO_OUTPUTCHANNELS] = "Output channels";
+ m_data[CONFIG_AUDIO_LIMITOUTPUT] = "Limit output";
+ m_data[CONFIG_AUDIO_INPUTDEVICE] = "Input device";
+ m_data[CONFIG_AUDIO_INPUTCHANNELS] = "Input channels";
+ m_data[CONFIG_AUDIO_RECTHRESHOLD] = "Rec threshold (dB)";
+ m_data[CONFIG_AUDIO_ENABLEINPUT] = "Enable Input";
+ m_data[CONFIG_AUDIO_RESAMPLING] = "Resampling";
+ m_data[CONFIG_AUDIO_RESAMPLING_SINCBEST] = "Sinc best quality (very slow)";
+ m_data[CONFIG_AUDIO_RESAMPLING_SINCMEDIUM] = "Sinc medium quality (slow)";
+ m_data[CONFIG_AUDIO_RESAMPLING_SINCBASIC] = "Sinc basic quality (medium)";
+ m_data[CONFIG_AUDIO_RESAMPLING_ZEROORDER] = "Zero Order Hold (fast)";
+ m_data[CONFIG_AUDIO_RESAMPLING_LINEAR] = "Linear (very fast)";
+ m_data[CONFIG_AUDIO_NODEVICESFOUND] = "-- no devices found --";
+
+ m_data[CONFIG_MIDI_TITLE] = "MIDI";
+ m_data[CONFIG_MIDI_SYSTEM] = "System";
+ m_data[CONFIG_MIDI_OUTPUTPORT] = "Output port";
+ m_data[CONFIG_MIDI_INPUTPORT] = "Input port";
+ m_data[CONFIG_MIDI_NOPORTSFOUND] = "-- no ports found --";
+ m_data[CONFIG_MIDI_OUTPUTMIDIMAP] = "Output MIDI Map";
+ m_data[CONFIG_MIDI_NOMIDIMAPSFOUND] = "(no MIDI maps available)";
+ m_data[CONFIG_MIDI_SYNC] = "Sync";
+ m_data[CONFIG_MIDI_LABEL_ENABLEOUT] = "Enable Output port";
+ m_data[CONFIG_MIDI_LABEL_ENABLEIN] = "Enable Input port";
+
+ m_data[CONFIG_BEHAVIORS_TITLE] = "Behaviors";
+ m_data[CONFIG_BEHAVIORS_CHANSSTOPONSEQHALT] = "Dynamic channels stop immediately when the sequencer is halted";
+ m_data[CONFIG_BEHAVIORS_TREATRECSASLOOPS] = "Treat one shot channels with actions as loops";
+ m_data[CONFIG_BEHAVIORS_INPUTMONITORDEFAULTON] = "New sample channels have input monitor on by default";
+ m_data[CONFIG_BEHAVIORS_OVERDUBPROTECTIONDEFAULTON] = "New sample channels have overdub protection on by default";
+
+ m_data[CONFIG_BINDINGS_TITLE] = "Key Bindings";
+ m_data[CONFIG_BINDINGS_PLAY] = "Play";
+ m_data[CONFIG_BINDINGS_REWIND] = "Rewind";
+ m_data[CONFIG_BINDINGS_RECORDACTIONS] = "Record actions";
+ m_data[CONFIG_BINDINGS_RECORDAUDIO] = "Record audio";
+ m_data[CONFIG_BINDINGS_EXIT] = "Exit";
+
+ m_data[CONFIG_MISC_TITLE] = "Misc";
+ m_data[CONFIG_MISC_DEBUGMESSAGES] = "Debug messages";
+ m_data[CONFIG_MISC_DEBUGMESSAGES_DISABLED] = "Disabled";
+ m_data[CONFIG_MISC_DEBUGMESSAGES_TOSTDOUT] = "To standard output";
+ m_data[CONFIG_MISC_DEBUGMESSAGES_TOFILE] = "To file";
+ m_data[CONFIG_MISC_TOOLTIPS] = "Tooltips";
+ m_data[CONFIG_MISC_TOOLTIPS_DISABLED] = "Disabled";
+ m_data[CONFIG_MISC_TOOLTIPS_ENABLED] = "Enabled";
+ m_data[CONFIG_MISC_LANGUAGE] = "Language file";
+ m_data[CONFIG_MISC_NOLANGUAGESFOUND] = "-- no language files found --";
+
+ m_data[CONFIG_PLUGINS_TITLE] = "Plug-ins";
+ m_data[CONFIG_PLUGINS_FOLDER] = "Plug-ins folder";
+ m_data[CONFIG_PLUGINS_SCANNING] = "Scan in progress ({}%). Please wait...";
+ m_data[CONFIG_PLUGINS_SCAN] = "Scan ({} found)";
+ m_data[CONFIG_PLUGINS_INVALIDPATH] = "Invalid path.";
+}
+
+const char* LangMap::get(const std::string& key) const
+{
+ if (m_data.count(key) == 0)
+ return m_default.c_str();
+ return m_data.at(key).c_str();
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+LangMapper::LangMapper()
+{
+ m_mapsPath = u::fs::getLangMapsPath();
+}
+
+/* -------------------------------------------------------------------------- */
+
+void LangMapper::init()
+{
+ Mapper::init();
+ u::log::print("[LangMapper::init] total langmaps found: %d\n", m_mapFiles.size());
+}
+
+/* -------------------------------------------------------------------------- */
+
+int LangMapper::read(const std::string& file)
+{
+ std::optional<nl::json> res = Mapper::read(file);
+ if (!res)
+ return G_FILE_UNREADABLE;
+
+ m_map.m_data = res.value().get<LangMap::Data>();
+
+ return G_FILE_OK;
+}
+
+/* -------------------------------------------------------------------------- */
+
+const char* LangMapper::get(const std::string& s) const
+{
+ return m_map.get(s);
+}
+} // namespace giada::v
diff --git a/src/gui/langMapper.h b/src/gui/langMapper.h
new file mode 100644
index 0000000..da97b60
--- /dev/null
+++ b/src/gui/langMapper.h
@@ -0,0 +1,375 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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 G_LANGMAPPER_H
+#define G_LANGMAPPER_H
+
+#include "mapper.h"
+#include <nlohmann/json.hpp>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace giada::v
+{
+class LangMap
+{
+public:
+ friend class LangMapper;
+
+ using Data = std::unordered_map<std::string, std::string>;
+
+ static constexpr auto COMMON_OK = "common_ok";
+ static constexpr auto COMMON_CANCEL = "common_cancel";
+ static constexpr auto COMMON_YES = "common_yes";
+ static constexpr auto COMMON_NO = "common_no";
+ static constexpr auto COMMON_OFF = "common_off";
+ static constexpr auto COMMON_SELECT = "common_select";
+ static constexpr auto COMMON_LOAD = "common_load";
+ static constexpr auto COMMON_SAVE = "common_save";
+ static constexpr auto COMMON_WARNING = "common_warning";
+ static constexpr auto COMMON_CLOSE = "common_close";
+ static constexpr auto COMMON_ADD = "common_add";
+ static constexpr auto COMMON_CLEAR = "common_clear";
+ static constexpr auto COMMON_RELOAD = "common_reload";
+ static constexpr auto COMMON_RESET = "common_reset";
+ static constexpr auto COMMON_ZOOMIN = "common_zoomIn";
+ static constexpr auto COMMON_ZOOMOUT = "common_zoomOut";
+ static constexpr auto COMMON_GRIDRES = "common_gridRes";
+ static constexpr auto COMMON_SNAPTOGRID = "common_snapToGrid";
+ static constexpr auto COMMON_BIND = "common_bind";
+ static constexpr auto COMMON_LEARN = "common_learn";
+ static constexpr auto COMMON_NOTSET = "common_notSet";
+ static constexpr auto COMMON_NONE = "common_none";
+
+ static constexpr auto MESSAGE_MAIN_FREEALLSAMPLES = "message_main_freeAllSamples";
+ static constexpr auto MESSAGE_MAIN_CLEARALLACTIONS = "message_main_clearAllActions";
+ static constexpr auto MESSAGE_MAIN_CLEARALLVOLUMEACTIONS = "message_main_clearAllVolumeActions";
+ static constexpr auto MESSAGE_MAIN_CLEARALLSTARTSTOPACTIONS = "message_main_clearAllStartStopActions";
+ static constexpr auto MESSAGE_MAIN_CLOSEPROJECT = "message_main_closeProject";
+
+ static constexpr auto MESSAGE_INIT_WRONGSYSTEM = "message_init_wrongSystem";
+ static constexpr auto MESSAGE_INIT_QUITGIADA = "message_init_quitGiada";
+
+ static constexpr auto MESSAGE_CHANNEL_MULTICHANNOTSUPPORTED = "message_channel_multiChanNotSupported";
+ static constexpr auto MESSAGE_CHANNEL_CANTREADSAMPLE = "message_channel_cantReadSample";
+ static constexpr auto MESSAGE_CHANNEL_PATHTOOLONG = "message_channel_pathTooLong";
+ static constexpr auto MESSAGE_CHANNEL_NOFILESPECIFIED = "message_channel_noFileSpecified";
+ static constexpr auto MESSAGE_CHANNEL_LOADINGSAMPLES = "message_channel_loadingSamples";
+ static constexpr auto MESSAGE_CHANNEL_LOADINGSAMPLESERROR = "message_channel_loadingSamplesError";
+ static constexpr auto MESSAGE_CHANNEL_DELETE = "message_channel_delete";
+ static constexpr auto MESSAGE_CHANNEL_FREE = "message_channel_free";
+
+ static constexpr auto MESSAGE_STORAGE_PATCHUNREADABLE = "message_storage_patchUnreadable";
+ static constexpr auto MESSAGE_STORAGE_PATCHINVALID = "message_storage_patchInvalid";
+ static constexpr auto MESSAGE_STORAGE_PATCHUNSUPPORTED = "message_storage_patchUnsupported";
+ static constexpr auto MESSAGE_STORAGE_PROJECTEXISTS = "message_storage_projectExists";
+ static constexpr auto MESSAGE_STORAGE_LOADINGPROJECT = "message_storage_loadingProject";
+ static constexpr auto MESSAGE_STORAGE_LOADINGSAMPLE = "message_storage_loadingSample";
+ static constexpr auto MESSAGE_STORAGE_SAVINGPROJECT = "message_storage_savingProject";
+ static constexpr auto MESSAGE_STORAGE_SAVINGPROJECTERROR = "message_storage_savingProjectError";
+ static constexpr auto MESSAGE_STORAGE_CHOOSEPROJECTNAME = "message_storage_chooseProjectName";
+ static constexpr auto MESSAGE_STORAGE_CHOOSEFILENAME = "message_storage_chooseFileName";
+ static constexpr auto MESSAGE_STORAGE_FILEEXISTS = "message_storage_fileExists";
+ static constexpr auto MESSAGE_STORAGE_SAVINGFILEERROR = "message_storage_savingFileError";
+
+ static constexpr auto MAIN_MENU_FILE = "main_menu_file";
+ static constexpr auto MAIN_MENU_FILE_OPENPROJECT = "main_menu_file_openProject";
+ static constexpr auto MAIN_MENU_FILE_SAVEPROJECT = "main_menu_file_saveProject";
+ static constexpr auto MAIN_MENU_FILE_CLOSEPROJECT = "main_menu_file_closeProject";
+ static constexpr auto MAIN_MENU_FILE_QUIT = "main_menu_file_quit";
+ static constexpr auto MAIN_MENU_EDIT = "main_menu_edit";
+ static constexpr auto MAIN_MENU_EDIT_FREEALLSAMPLES = "main_menu_edit_freeAllSamples";
+ static constexpr auto MAIN_MENU_EDIT_CLEARALLACTIONS = "main_menu_edit_clearAllActions";
+ static constexpr auto MAIN_MENU_EDIT_SETUPMIDIINPUT = "main_menu_edit_setupMidiInput";
+ static constexpr auto MAIN_MENU_CONFIG = "main_menu_config";
+ static constexpr auto MAIN_MENU_ABOUT = "main_menu_about";
+
+ static constexpr auto MAIN_IO_LABEL_OUTMETER = "main_IO_label_outMeter";
+ static constexpr auto MAIN_IO_LABEL_INMETER = "main_IO_label_inMeter";
+ static constexpr auto MAIN_IO_LABEL_OUTVOL = "main_IO_label_outVol";
+ static constexpr auto MAIN_IO_LABEL_INVOL = "main_IO_label_inVol";
+ static constexpr auto MAIN_IO_LABEL_INTOOUT = "main_IO_label_inToOut";
+ static constexpr auto MAIN_IO_LABEL_FXOUT = "main_IO_label_fxOut";
+ static constexpr auto MAIN_IO_LABEL_FXIN = "main_IO_label_fxIn";
+
+ static constexpr auto MAIN_TIMER_LABEL_BPM = "main_mainTimer_label_bpm";
+ static constexpr auto MAIN_TIMER_LABEL_METER = "main_mainTimer_label_meter";
+ static constexpr auto MAIN_TIMER_LABEL_QUANTIZER = "main_mainTimer_label_quantizer";
+ static constexpr auto MAIN_TIMER_LABEL_MULTIPLIER = "main_mainTimer_label_multiplier";
+ static constexpr auto MAIN_TIMER_LABEL_DIVIDER = "main_mainTimer_label_divider";
+
+ static constexpr auto MAIN_SEQUENCER_LABEL = "main_sequencer_label";
+
+ static constexpr auto MAIN_TRANSPORT_LABEL_REWIND = "main_transport_label_rewind";
+ static constexpr auto MAIN_TRANSPORT_LABEL_PLAY = "main_transport_label_play";
+ static constexpr auto MAIN_TRANSPORT_LABEL_RECTRIGGERMODE = "main_transport_label_recTriggerMode";
+ static constexpr auto MAIN_TRANSPORT_LABEL_RECACTIONS = "main_transport_label_recActions";
+ static constexpr auto MAIN_TRANSPORT_LABEL_RECINPUT = "main_transport_label_recInput";
+ static constexpr auto MAIN_TRANSPORT_LABEL_RECINPUTMODE = "main_transport_label_recInputMode";
+ static constexpr auto MAIN_TRANSPORT_LABEL_METRONOME = "main_transport_label_metronome";
+
+ static constexpr auto MAIN_COLUMN_BUTTON = "main_column_button";
+ static constexpr auto MAIN_COLUMN_BUTTON_ADDSAMPLECHANNEL = "main_column_button_addSampleChannel";
+ static constexpr auto MAIN_COLUMN_BUTTON_ADDMIDICHANNEL = "main_column_button_addMidiChannel";
+ static constexpr auto MAIN_COLUMN_BUTTON_REMOVE = "main_column_button_remove";
+
+ static constexpr auto MAIN_CHANNEL_NOSAMPLE = "main_channel_noSample";
+ static constexpr auto MAIN_CHANNEL_SAMPLENOTFOUND = "main_channel_sampleNotFound";
+ static constexpr auto MAIN_CHANNEL_LABEL_PLAY = "main_channel_label_play";
+ static constexpr auto MAIN_CHANNEL_LABEL_ARM = "main_channel_label_arm";
+ static constexpr auto MAIN_CHANNEL_LABEL_STATUS = "main_channel_label_status";
+ static constexpr auto MAIN_CHANNEL_LABEL_READACTIONS = "main_channel_label_readActions";
+ static constexpr auto MAIN_CHANNEL_LABEL_MODEBOX = "main_channel_label_modeBox";
+ static constexpr auto MAIN_CHANNEL_LABEL_MUTE = "main_channel_label_mute";
+ static constexpr auto MAIN_CHANNEL_LABEL_SOLO = "main_channel_label_solo";
+ static constexpr auto MAIN_CHANNEL_LABEL_FX = "main_channel_label_fx";
+ static constexpr auto MAIN_CHANNEL_LABEL_VOLUME = "main_channel_label_volume";
+ static constexpr auto MAIN_CHANNEL_LABEL_MIDIACTIVITY = "main_channel_label_midiActivity";
+
+ static constexpr auto MAIN_CHANNEL_MENU_INPUTMONITOR = "main_channel_menu_inputMonitor";
+ static constexpr auto MAIN_CHANNEL_MENU_OVERDUBPROTECTION = "main_channel_menu_overdubProtection";
+ static constexpr auto MAIN_CHANNEL_MENU_LOADSAMPLE = "main_channel_menu_loadSample";
+ static constexpr auto MAIN_CHANNEL_MENU_EXPORTSAMPLE = "main_channel_menu_exportSample";
+ static constexpr auto MAIN_CHANNEL_MENU_KEYBOARDINPUT = "main_channel_menu_keyboardInput";
+ static constexpr auto MAIN_CHANNEL_MENU_MIDIINPUT = "main_channel_menu_midiInput";
+ static constexpr auto MAIN_CHANNEL_MENU_MIDIOUTPUT = "main_channel_menu_midiOutput";
+ static constexpr auto MAIN_CHANNEL_MENU_EDITSAMPLE = "main_channel_menu_editSample";
+ static constexpr auto MAIN_CHANNEL_MENU_EDITACTIONS = "main_channel_menu_editActions";
+ static constexpr auto MAIN_CHANNEL_MENU_CLEARACTIONS = "main_channel_menu_clearActions";
+ static constexpr auto MAIN_CHANNEL_MENU_CLEARACTIONS_ALL = "main_channel_menu_clearActions_all";
+ static constexpr auto MAIN_CHANNEL_MENU_CLEARACTIONS_VOLUME = "main_channel_menu_clearActions_volume";
+ static constexpr auto MAIN_CHANNEL_MENU_CLEARACTIONS_STARTSTOP = "main_channel_menu_clearActions_startStop";
+ static constexpr auto MAIN_CHANNEL_MENU_RENAME = "main_channel_menu_rename";
+ static constexpr auto MAIN_CHANNEL_MENU_CLONE = "main_channel_menu_clone";
+ static constexpr auto MAIN_CHANNEL_MENU_FREE = "main_channel_menu_free";
+ static constexpr auto MAIN_CHANNEL_MENU_DELETE = "main_channel_menu_delete";
+
+ static constexpr auto MISSINGASSETS_INTRO = "missingAssets_intro";
+ static constexpr auto MISSINGASSETS_AUDIOFILES = "missingAssets_audioFiles";
+ static constexpr auto MISSINGASSETS_PLUGINS = "missingAssets_plugIns";
+
+ static constexpr auto PLUGINCHOOSER_TITLE = "pluginChooser_title";
+ static constexpr auto PLUGINCHOOSER_HEADER = "pluginChooser_header";
+ static constexpr auto PLUGINCHOOSER_SORTBY = "pluginChooser_sortBy";
+ static constexpr auto PLUGINCHOOSER_SORTBY_NAME = "pluginChooser_sortBy_name";
+ static constexpr auto PLUGINCHOOSER_SORTBY_CATEGORY = "pluginChooser_sortBy_category";
+ static constexpr auto PLUGINCHOOSER_SORTBY_MANIFACTURER = "pluginChooser_sortBy_manifacturer";
+ static constexpr auto PLUGINCHOOSER_SORTBY_FORMAT = "pluginChooser_sortBy_format";
+
+ static constexpr auto PLUGINLIST_TITLE_MASTEROUT = "pluginList_title_masterOut";
+ static constexpr auto PLUGINLIST_TITLE_MASTERIN = "pluginList_title_masterIn";
+ static constexpr auto PLUGINLIST_TITLE_CHANNEL = "pluginList_title_channel";
+ static constexpr auto PLUGINLIST_ADDPLUGIN = "pluginList_addPlugin";
+ static constexpr auto PLUGINLIST_NOPROGRAMS = "pluginList_noPrograms";
+
+ static constexpr auto CHANNELNAME_TITLE = "channelName_title";
+
+ static constexpr auto KEYGRABBER_TITLE = "keyGrabber_title";
+ static constexpr auto KEYGRABBER_BODY = "keyGrabber_body";
+
+ static constexpr auto SAMPLEEDITOR_TITLE = "sampleEditor_title";
+ static constexpr auto SAMPLEEDITOR_RELOAD = "sampleEditor_reload";
+ static constexpr auto SAMPLEEDITOR_LOOP = "sampleEditor_loop";
+ static constexpr auto SAMPLEEDITOR_INFO = "sampleEditor_info";
+ static constexpr auto SAMPLEEDITOR_PAN = "sampleEditor_pan";
+ static constexpr auto SAMPLEEDITOR_PITCH = "sampleEditor_pitch";
+ static constexpr auto SAMPLEEDITOR_PITCH_TOBAR = "sampleEditor_pitch_toBar";
+ static constexpr auto SAMPLEEDITOR_PITCH_TOSONG = "sampleEditor_pitch_toSong";
+ static constexpr auto SAMPLEEDITOR_RANGE = "sampleEditor_range";
+ static constexpr auto SAMPLEEDITOR_SHIFT = "sampleEditor_shift";
+ static constexpr auto SAMPLEEDITOR_VOLUME = "sampleEditor_volume";
+ static constexpr auto SAMPLEEDITOR_TOOLS_CUT = "sampleEditor_tools_cut";
+ static constexpr auto SAMPLEEDITOR_TOOLS_COPY = "sampleEditor_tools_copy";
+ static constexpr auto SAMPLEEDITOR_TOOLS_PASTE = "sampleEditor_tools_paste";
+ static constexpr auto SAMPLEEDITOR_TOOLS_TRIM = "sampleEditor_tools_trim";
+ static constexpr auto SAMPLEEDITOR_TOOLS_SILENCE = "sampleEditor_tools_silence";
+ static constexpr auto SAMPLEEDITOR_TOOLS_REVERSE = "sampleEditor_tools_reverse";
+ static constexpr auto SAMPLEEDITOR_TOOLS_NORMALIZE = "sampleEditor_tools_normalize";
+ static constexpr auto SAMPLEEDITOR_TOOLS_FADE_IN = "sampleEditor_tools_fadeIn";
+ static constexpr auto SAMPLEEDITOR_TOOLS_FADE_OUT = "sampleEditor_tools_fadeOut";
+ static constexpr auto SAMPLEEDITOR_TOOLS_SMOOTH_EDGES = "sampleEditor_tools_smoothEdgdes";
+ static constexpr auto SAMPLEEDITOR_TOOLS_SET_BEGIN_END = "sampleEditor_tools_setBeginEnd";
+ static constexpr auto SAMPLEEDITOR_TOOLS_TO_NEW_CHANNEL = "sampleEditor_tools_toNewChannel";
+
+ static constexpr auto ACTIONEDITOR_TITLE = "actionEditor_title";
+ static constexpr auto ACTIONEDITOR_VOLUME = "actionEditor_volume";
+ static constexpr auto ACTIONEDITOR_KEYPRESS = "actionEditor_keyPress";
+ static constexpr auto ACTIONEDITOR_KEYRELEASE = "actionEditor_keyRelease";
+ static constexpr auto ACTIONEDITOR_STOPSAMPLE = "actionEditor_stopSample";
+ static constexpr auto ACTIONEDITOR_STARTSTOP = "actionEditor_startStop";
+ static constexpr auto ACTIONEDITOR_STARTSTOPDISABLED = "actionEditor_startStopDisabled";
+ static constexpr auto ACTIONEDITOR_VELOCITY = "actionEditor_velocity";
+ static constexpr auto ACTIONEDITOR_LABEL_ACTIONTYPE = "actionEditor_label_actionType";
+
+ static constexpr auto BROWSER_SHOWHIDDENFILES = "browser_showHiddenFiles";
+ static constexpr auto BROWSER_OPENPROJECT = "browser_openProject";
+ static constexpr auto BROWSER_SAVEPROJECT = "browser_saveProject";
+ static constexpr auto BROWSER_OPENSAMPLE = "browser_openSample";
+ static constexpr auto BROWSER_SAVESAMPLE = "browser_saveSample";
+ static constexpr auto BROWSER_OPENPLUGINSDIR = "browser_openPluginsDir";
+
+ static constexpr auto MIDIINPUT_MASTER_TITLE = "midiInput_master_title";
+ static constexpr auto MIDIINPUT_MASTER_ENABLE = "midiInput_master_enable";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_REWIND = "midiInput_master_learn_rewind";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_PLAYSTOP = "midiInput_master_learn_playStop";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_ACTIONREC = "midiInput_master_learn_actionRec";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_INPUTREC = "midiInput_master_learn_inputRec";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_METRONOME = "midiInput_master_learn_metronome";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_INVOLUME = "midiInput_master_learn_inVolume";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_OUTVOLUME = "midiInput_master_learn_outVolume";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_SEQDOUBLE = "midiInput_master_learn_seqDouble";
+ static constexpr auto MIDIINPUT_MASTER_LEARN_SEQHALF = "midiInput_master_learn_seqHalf";
+
+ static constexpr auto MIDIINPUT_CHANNEL_TITLE = "midiInput_channel_title";
+ static constexpr auto MIDIINPUT_CHANNEL_ENABLE = "midiInput_channel_enable";
+ static constexpr auto MIDIINPUT_CHANNEL_VELOCITYDRIVESVOL = "midiInput_channel_learn_velocityDrivesVol";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_CHANNEL = "midiInput_channel_learn_channel";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_KEYPRESS = "midiInput_channel_learn_keyPress";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_KEYREL = "midiInput_channel_learn_keyRel";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_KEYKILL = "midiInput_channel_learn_keyKill";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_ARM = "midiInput_channel_learn_arm";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_MUTE = "midiInput_channel_learn_mute";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_SOLO = "midiInput_channel_learn_solo";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_VOLUME = "midiInput_channel_learn_volume";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_PITCH = "midiInput_channel_learn_pitch";
+ static constexpr auto MIDIINPUT_CHANNEL_LEARN_READACTIONS = "midiInput_channel_learn_readActions";
+
+ static constexpr auto MIDIOUTPUT_CHANNEL_TITLE = "midiOutput_channel_title";
+ static constexpr auto MIDIOUTPUT_CHANNEL_ENABLE = "midiOutput_channel_enable";
+ static constexpr auto MIDIOUTPUT_CHANNEL_ENABLE_LIGHTNING = "midiOutput_channel_enableLightning";
+ static constexpr auto MIDIOUTPUT_CHANNEL_LEARN_PLAYING = "midiOutput_channel_learn_playing";
+ static constexpr auto MIDIOUTPUT_CHANNEL_LEARN_MUTE = "midiOutput_channel_learn_mute";
+ static constexpr auto MIDIOUTPUT_CHANNEL_LEARN_SOLO = "midiOutput_channel_learn_solo";
+
+ static constexpr auto ABOUT_TITLE = "about_title";
+ static constexpr auto ABOUT_BODY = "about_body";
+ static constexpr auto ABOUT_BODY_VST = "about_body_vst";
+
+ static constexpr auto CONFIG_TITLE = "config_title";
+ static constexpr auto CONFIG_RESTARTGIADA = "config_restartGiada";
+
+ static constexpr auto CONFIG_AUDIO_TITLE = "config_audio_title";
+ static constexpr auto CONFIG_AUDIO_SYSTEM = "config_audio_system";
+ static constexpr auto CONFIG_AUDIO_BUFFERSIZE = "config_audio_bufferSize";
+ static constexpr auto CONFIG_AUDIO_SAMPLERATE = "config_audio_sampleRate";
+ static constexpr auto CONFIG_AUDIO_OUTPUTDEVICE = "config_audio_outputDevice";
+ static constexpr auto CONFIG_AUDIO_OUTPUTCHANNELS = "config_audio_outputChannels";
+ static constexpr auto CONFIG_AUDIO_LIMITOUTPUT = "config_audio_limitOutput";
+ static constexpr auto CONFIG_AUDIO_INPUTDEVICE = "config_audio_inputDevice";
+ static constexpr auto CONFIG_AUDIO_INPUTCHANNELS = "config_audio_inputChannels";
+ static constexpr auto CONFIG_AUDIO_RECTHRESHOLD = "config_audio_recThreshold";
+ static constexpr auto CONFIG_AUDIO_ENABLEINPUT = "config_audio_enableInput";
+ static constexpr auto CONFIG_AUDIO_RESAMPLING = "config_audio_reseampling";
+ static constexpr auto CONFIG_AUDIO_RESAMPLING_SINCBEST = "config_audio_reseampling_sincBest";
+ static constexpr auto CONFIG_AUDIO_RESAMPLING_SINCMEDIUM = "config_audio_reseampling_sincMedium";
+ static constexpr auto CONFIG_AUDIO_RESAMPLING_SINCBASIC = "config_audio_reseampling_sincBasic";
+ static constexpr auto CONFIG_AUDIO_RESAMPLING_ZEROORDER = "config_audio_reseampling_zeroOrder";
+ static constexpr auto CONFIG_AUDIO_RESAMPLING_LINEAR = "config_audio_reseampling_linear";
+ static constexpr auto CONFIG_AUDIO_NODEVICESFOUND = "config_audio_noDevicesFound";
+
+ static constexpr auto CONFIG_MIDI_TITLE = "config_midi_title";
+ static constexpr auto CONFIG_MIDI_SYSTEM = "config_midi_system";
+ static constexpr auto CONFIG_MIDI_OUTPUTPORT = "config_midi_outputPort";
+ static constexpr auto CONFIG_MIDI_INPUTPORT = "config_midi_inputPort";
+ static constexpr auto CONFIG_MIDI_NOPORTSFOUND = "config_midi_noPortsFound";
+ static constexpr auto CONFIG_MIDI_OUTPUTMIDIMAP = "config_midi_outputMidiMap";
+ static constexpr auto CONFIG_MIDI_NOMIDIMAPSFOUND = "config_midi_noMidiMapsFound";
+ static constexpr auto CONFIG_MIDI_SYNC = "config_midi_sync";
+ static constexpr auto CONFIG_MIDI_LABEL_ENABLEOUT = "config_midi_label_enableOut";
+ static constexpr auto CONFIG_MIDI_LABEL_ENABLEIN = "config_midi_label_enableIn";
+
+ static constexpr auto CONFIG_BEHAVIORS_TITLE = "config_behaviors_title";
+ static constexpr auto CONFIG_BEHAVIORS_CHANSSTOPONSEQHALT = "config_behaviors_chansStopOnSeqHalt";
+ static constexpr auto CONFIG_BEHAVIORS_TREATRECSASLOOPS = "config_behaviors_treatRecsAsLoops";
+ static constexpr auto CONFIG_BEHAVIORS_INPUTMONITORDEFAULTON = "config_behaviors_inputMonitorDefaultOn";
+ static constexpr auto CONFIG_BEHAVIORS_OVERDUBPROTECTIONDEFAULTON = "config_behaviors_overdubProtectionDefaultOn";
+
+ static constexpr auto CONFIG_BINDINGS_TITLE = "config_bindings_title";
+ static constexpr auto CONFIG_BINDINGS_PLAY = "config_bindings_play";
+ static constexpr auto CONFIG_BINDINGS_REWIND = "config_bindings_rewind";
+ static constexpr auto CONFIG_BINDINGS_RECORDACTIONS = "config_bindings_recordActions";
+ static constexpr auto CONFIG_BINDINGS_RECORDAUDIO = "config_bindings_recordAudio";
+ static constexpr auto CONFIG_BINDINGS_EXIT = "config_bindings_exit";
+
+ static constexpr auto CONFIG_MISC_TITLE = "config_misc_title";
+ static constexpr auto CONFIG_MISC_DEBUGMESSAGES = "config_misc_debugMessages";
+ static constexpr auto CONFIG_MISC_DEBUGMESSAGES_DISABLED = "config_misc_debugMessages_disabled";
+ static constexpr auto CONFIG_MISC_DEBUGMESSAGES_TOSTDOUT = "config_misc_debugMessages_toStdOut";
+ static constexpr auto CONFIG_MISC_DEBUGMESSAGES_TOFILE = "config_misc_debugMessages_toFile";
+ static constexpr auto CONFIG_MISC_TOOLTIPS = "config_misc_tooltips";
+ static constexpr auto CONFIG_MISC_TOOLTIPS_DISABLED = "config_misc_tooltips_disabled";
+ static constexpr auto CONFIG_MISC_TOOLTIPS_ENABLED = "config_misc_tooltips_enabled";
+ static constexpr auto CONFIG_MISC_LANGUAGE = "config_misc_language";
+ static constexpr auto CONFIG_MISC_NOLANGUAGESFOUND = "config_misc_noLanguagesFound";
+
+ static constexpr auto CONFIG_PLUGINS_TITLE = "config_plugins_title";
+ static constexpr auto CONFIG_PLUGINS_FOLDER = "config_plugins_folder";
+ static constexpr auto CONFIG_PLUGINS_SCANNING = "config_plugins_scanning";
+ static constexpr auto CONFIG_PLUGINS_SCAN = "config_plugins_scan";
+ static constexpr auto CONFIG_PLUGINS_INVALIDPATH = "config_plugins_invalidPath";
+
+ LangMap();
+
+ const char* get(const std::string&) const;
+
+private:
+ Data m_data;
+ std::string m_default;
+};
+
+/* -------------------------------------------------------------------------- */
+
+class LangMapper final : public Mapper
+{
+public:
+ LangMapper();
+
+ /* get
+ Gets a key from the currently loaded langmap file. */
+
+ const char* get(const std::string&) const;
+
+ /* init
+ Parses the langmap folders and find the available langmaps. */
+
+ void init();
+
+ /* read
+ Reads a langmap from file 'file' and sets it as the current one. */
+
+ int read(const std::string& file);
+
+private:
+ /* maps
+ The current langmap selected and loaded. It might be the default one (En_US)
+ if no langmaps have been found. */
+
+ LangMap m_map;
+};
+} // namespace giada::v
+
+#endif
diff --git a/src/gui/ui.cpp b/src/gui/ui.cpp
index 1b1e732..02f845c 100644
--- a/src/gui/ui.cpp
+++ b/src/gui/ui.cpp
@@ -96,6 +96,9 @@ void Ui::init(int argc, char** argv, m::Engine& engine)
XInitThreads();
#endif
+ langMapper.init();
+ langMapper.read(engine.conf.data.langMap);
+
mainWindow = std::make_unique<gdMainWindow>(G_MIN_GUI_WIDTH, G_MIN_GUI_HEIGHT, "", argc, argv, engine.conf.data);
mainWindow->resize(engine.conf.data.mainWindowX, engine.conf.data.mainWindowY, engine.conf.data.mainWindowW,
engine.conf.data.mainWindowH);
diff --git a/src/gui/ui.h b/src/gui/ui.h
index 116eaf0..e47f90b 100644
--- a/src/gui/ui.h
+++ b/src/gui/ui.h
@@ -31,6 +31,7 @@
#include "core/patch.h"
#include "gui/dialogs/mainWindow.h"
#include "gui/dispatcher.h"
+#include "gui/langMapper.h"
#include "gui/updater.h"
#include <memory>
#include <string>
@@ -123,6 +124,7 @@ public:
std::unique_ptr<gdMainWindow> mainWindow;
Dispatcher dispatcher;
+ LangMapper langMapper;
private:
static constexpr int BLINK_RATE = G_GUI_FPS / 2;
diff --git a/src/mapper.cpp b/src/mapper.cpp
new file mode 100644
index 0000000..adb232e
--- /dev/null
+++ b/src/mapper.cpp
@@ -0,0 +1,73 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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 "mapper.h"
+#include "utils/fs.h"
+#include <filesystem>
+#include <fstream>
+
+namespace nl = nlohmann;
+
+namespace giada
+{
+void Mapper::init()
+{
+ if (!std::filesystem::exists(m_mapsPath))
+ return;
+
+ for (const auto& d : std::filesystem::directory_iterator(m_mapsPath))
+ {
+ if (!d.is_regular_file()) // TODO - better mechanism to check if it's a valid map
+ continue;
+ m_mapFiles.push_back(d.path().filename().string());
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+std::optional<nlohmann::json> Mapper::read(const std::string& file) const
+{
+ if (file.empty())
+ return {};
+
+ std::ifstream ifs(u::fs::join(m_mapsPath, file));
+ if (!ifs.good())
+ return {};
+
+ nl::json j = nl::json::parse(ifs, nullptr, /*exceptions=*/false);
+ if (j.is_discarded())
+ return {};
+
+ return {j};
+}
+
+/* -------------------------------------------------------------------------- */
+
+const std::vector<std::string>& Mapper::getMapFilesFound() const
+{
+ return m_mapFiles;
+}
+} // namespace giada
diff --git a/src/mapper.h b/src/mapper.h
new file mode 100644
index 0000000..c22f13f
--- /dev/null
+++ b/src/mapper.h
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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 G_MAPPER_H
+#define G_MAPPER_H
+
+#include <nlohmann/json.hpp>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace giada
+{
+class Mapper
+{
+public:
+ /* getMapFilesFound
+ Returns a reference to the list of maps found. */
+
+ const std::vector<std::string>& getMapFilesFound() const;
+
+ /* init
+ Parses the map folder m_mapsPath and find the available maps. */
+
+ void init();
+
+protected:
+ /* read
+ Reads a map from file 'file' as a JSON object. */
+
+ std::optional<nlohmann::json> read(const std::string& file) const;
+
+ /* m_mapsPath
+ Path to folder containing map files, different between OSes. */
+
+ std::string m_mapsPath;
+
+ /* m_mapFiles
+ The available map files. Each element of the vector represents a map file
+ found in the map folder. */
+
+ std::vector<std::string> m_mapFiles;
+};
+} // namespace giada
+
+#endif
diff --git a/src/utils/fs.cpp b/src/utils/fs.cpp
index 6f19795..eec222f 100644
--- a/src/utils/fs.cpp
+++ b/src/utils/fs.cpp
@@ -173,6 +173,20 @@ std::string getHomePath()
/* -------------------------------------------------------------------------- */
+std::string getMidiMapsPath()
+{
+ auto out = stdfs::path(getHomePath()) / "midimaps";
+ return out.string();
+}
+
+std::string getLangMapsPath()
+{
+ auto out = stdfs::path(getHomePath()) / "langmaps";
+ return out.string();
+}
+
+/* -------------------------------------------------------------------------- */
+
bool isRootDir(const std::string& s)
{
return stdfs::current_path().root_directory() == s;
@@ -192,4 +206,12 @@ std::string getUpDir(const std::string& s)
return stdfs::path(s).parent_path().string();
}
+
+/* -------------------------------------------------------------------------- */
+
+std::string join(const std::string& a, const std::string& b)
+{
+ auto out = stdfs::path(a) / stdfs::path(b);
+ return out.string();
+}
} // namespace giada::u::fs \ No newline at end of file
diff --git a/src/utils/fs.h b/src/utils/fs.h
index b1f608e..1fb7523 100644
--- a/src/utils/fs.h
+++ b/src/utils/fs.h
@@ -46,6 +46,8 @@ bool isProject(const std::string& s);
bool mkdir(const std::string& s);
std::string getCurrentPath();
std::string getHomePath();
+std::string getMidiMapsPath();
+std::string getLangMapsPath();
/* getRealPath
Expands all symbolic links and resolves references to /./, /../ and extra /
@@ -80,6 +82,11 @@ Returns the upper directory:
/path/to/my/directory -> /path/to/my/ */
std::string getUpDir(const std::string& s);
+
+/* join
+Joins two string paths using the correct separator. */
+
+std::string join(const std::string& a, const std::string& b);
} // namespace giada::u::fs
#endif
diff --git a/src/utils/log.cpp b/src/utils/log.cpp
index 42a1d0f..c223369 100644
--- a/src/utils/log.cpp
+++ b/src/utils/log.cpp
@@ -38,7 +38,7 @@ int init(int m)
stat = true;
if (mode == LOG_MODE_FILE)
{
- std::string fpath = fs::getHomePath() + G_SLASH + "giada.log";
+ std::string fpath = u::fs::join(fs::getHomePath(), "giada.log");
f = std::fopen(fpath.c_str(), "a");
if (!f)
{
diff --git a/vcpkg.json b/vcpkg.json
new file mode 100644
index 0000000..e9a4c34
--- /dev/null
+++ b/vcpkg.json
@@ -0,0 +1,34 @@
+{
+ "name": "giada",
+ "version-string": "1.0",
+ "builtin-baseline": "af2287382b1991dbdcb7e5112d236f3323b9dd7a",
+ "dependencies": [
+ {
+ "name": "rtmidi",
+ "version>=": "5.0.0"
+ },
+ {
+ "name": "fmt",
+ "version>=": "8.1.1"
+ },
+ {
+ "name": "fltk",
+ "version>=": "1.3.8"
+ },
+ {
+ "name": "catch2",
+ "version>=": "2.13.8"
+ },
+ {
+ "name": "libsamplerate",
+ "version>=": "0.2.2"
+ },
+ {
+ "name": "libsndfile",
+ "version>=": "1.0.31",
+ "features": [
+ "external-libs"
+ ]
+ }
+ ]
+} \ No newline at end of file