diff options
author | Dennis Braun <d_braun@kabelmail.de> | 2022-06-13 22:45:45 +0200 |
---|---|---|
committer | Dennis Braun <d_braun@kabelmail.de> | 2022-06-13 22:45:45 +0200 |
commit | ed972b70dcba4055781085ac5599730321b4ccdd (patch) | |
tree | e4c61b228ac66b83e30577e41d5b04f9bfae72e4 | |
parent | 6be2fd4da5ca72688c5363886c6d0842c9edb54e (diff) |
New upstream version 0.22.0
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) @@ -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 |