make -j 2
make rename
-make check -j 2
\ No newline at end of file
+
+if [[ $TRAVIS_OS_NAME == 'linux' ]]; then
+
+ xvfb-run make check -j 2
+
+else
+
+ make check -j 2
+
+fi
\ No newline at end of file
--------------------------------------------------------------------------------
+0.14.6 --- 2018 . 03 . 15
+- MIDI velocity drives volume for one-shot sample channels
+- FLAC and Ogg support
+- Ability to use system-provided Catch library (GitHub #151)
+- Update Catch to version 2
+- Fix unreadable tabs title in Configuration Window (GitHub #168)
+- Fix crash on opening About window
+- Fix 'read actions' button behavior during ending and waiting statuses
+- Fix sound card initialization on MacOS
+- [Windows] Fix UI stuck on top-right corner
+- [Windows] Fix browsing for directories
+
+
0.14.5 --- 2018 . 01 . 15
- OS X builds on Travis CI
- AppImage executable for Linux
src/deps/juce/modules/juce_gui_extra/juce_gui_extra.cpp
cppFlags += \
- -I./src/deps/juce/modules \
- -I./src/deps/vst \
- -I/usr/include \
- -I/usr/include/freetype2 \
- -DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1 \
- -DJUCE_STANDALONE_APPLICATION=1 \
- -DJUCE_PLUGINHOST_VST=1 \
- -DJUCE_PLUGINHOST_VST3=0 \
- -DJUCE_PLUGINHOST_AU=0 \
+ -I$(top_srcdir)/src/deps/juce/modules \
+ -I$(top_srcdir)/src/deps/vst \
+ -I/usr/include \
+ -I/usr/include/freetype2 \
+ -DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1 \
+ -DJUCE_STANDALONE_APPLICATION=1 \
+ -DJUCE_PLUGINHOST_VST=1 \
+ -DJUCE_PLUGINHOST_VST3=0 \
+ -DJUCE_PLUGINHOST_AU=0 \
-DJUCE_WEB_BROWSER=0
endif
+if !WITH_SYSTEM_CATCH
+
+cppFlags += -I$(top_srcdir)/tests/catch2/single_include
+
+endif
+
if WINDOWS
extraSources += \
resource.rc
cppFlags += \
- -I./src/deps/rtaudio-mod/include \
- -D__WINDOWS_ASIO__ \
- -D__WINDOWS_WASAPI__ \
+ -I$(top_srcdir)/src/deps/rtaudio-mod/include \
+ -D__WINDOWS_ASIO__ \
+ -D__WINDOWS_WASAPI__ \
-D__WINDOWS_DS__
cxxFlags += -Wno-error
ldAdd += -ldsound -lwsock32 -lm -lfltk -lwininet -lgdi32 -lshell32 -lvfw32 \
-lrpcrt4 -luuid -lcomctl32 -lole32 -lws2_32 -lsndfile -lsamplerate -lrtmidi \
-lwinmm -lsetupapi -lksuser -ljansson -limm32 -lglu32 -lshell32 -lversion \
- -lopengl32 -loleaut32 -lshlwapi -lcomdlg32
+ -lopengl32 -loleaut32 -lshlwapi -lcomdlg32 -lflac -lvorbis -logg -lvorbisenc
# Generate a GUI application (-mwindows), make the build static (-static).
ldFlags += -mwindows -static
extraSources += src/utils/cocoa.mm src/utils/cocoa.h
+# Add preprocessor flags to enable CoreAudio in RtAudio.
+cppFlags += -D__MACOSX_CORE__
+
# -ObjC++: Juce requires to build some Objective C code
cxxFlags += -ObjC++ -Wno-auto-var-id
[AM_CONDITIONAL(WITH_VST, false)]
)
+# ------------------------------------------------------------------------------
+
+# --enable-system-catch. If enabled, use the system-provided Catch. Use bundled
+# version otherwise (default mode).
+
+AC_ARG_ENABLE(
+ [system-catch],
+ AS_HELP_STRING([--enable-system-catch], [use system-provided Catch library]),
+ [AC_DEFINE(WITH_SYSTEM_CATCH) AM_CONDITIONAL(WITH_SYSTEM_CATCH, true)],
+ [AM_CONDITIONAL(WITH_SYSTEM_CATCH, false)]
+)
# ------------------------------------------------------------------------------
midiInFilter (-1),
previewMode (G_PREVIEW_NONE),
pan (0.5f),
+ volume (G_DEFAULT_VOL),
+ volume_i (1.0f),
+ volume_d (0.0f),
armed (false),
type (type),
status (status),
key (0),
- volume (G_DEFAULT_VOL),
- volume_i (1.0f),
- volume_d (0.0f),
mute_i (false),
mute_s (false),
mute (false),
/* -------------------------------------------------------------------------- */
+void Channel::setVolume(float v)
+{
+ volume = v;
+}
+
+
+void Channel::setVolumeI(float v)
+{
+ volume_i = v;
+}
+
+
+float Channel::getVolume() const
+{
+ return volume;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
float Channel::calcPanning(int ch)
{
if (pan == 0.5f) // center: nothing to do
int previewMode;
float pan;
+ float volume; // global volume
+ float volume_i; // internal volume
+ float volume_d; // delta volume (for envelope)
bool armed;
std::string name;
virtual void rewind() = 0;
/* clear
- Clears all memory buffers. This is actually useful to sample channels only. */
+ Clears all memory buffers. This is actually useful to sample channels only.
+ TODO - please rename it to clearBuffers. */
virtual void clear() = 0;
bool isPlaying() const;
float getPan() const;
+ float getVolume() const;
bool isArmed() const;
std::string getName() const;
bool isPreview() const;
void sendMidiLplay();
void setPan(float v);
+ void setVolume(float v);
+ void setVolumeI(float v);
void setArmed(bool b);
void setName(const std::string& s);
void setPreviewMode(int m);
int type; // midi or sample
int status; // status: see const.h
int key; // keyboard button
- float volume; // global volume
- float volume_i; // internal volume
- float volume_d; // delta volume (for envelope)
bool mute_i; // internal mute
bool mute_s; // previous mute status after being solo'd
bool mute; // global mute
#include <string>
+#include <FL/Fl.H>
#include "../utils/fs.h"
#include "../utils/log.h"
#include "storager.h"
string patchPath = "";
string samplePath = "";
-int mainWindowX = 0;
-int mainWindowY = 0;
-int mainWindowW = G_GUI_WIDTH;
-int mainWindowH = G_GUI_HEIGHT;
+int mainWindowX = (Fl::w() / 2) - (G_MIN_GUI_WIDTH / 2);
+int mainWindowY = (Fl::h() / 2) - (G_MIN_GUI_HEIGHT / 2);
+int mainWindowW = G_MIN_GUI_WIDTH;
+int mainWindowH = G_MIN_GUI_HEIGHT;
int browserX = 0;
int browserY = 0;
/* -- version --------------------------------------------------------------- */
#define G_APP_NAME "Giada"
-#define G_VERSION_STR "0.14.5"
+#define G_VERSION_STR "0.14.6"
#define G_VERSION_MAJOR 0
#define G_VERSION_MINOR 14
-#define G_VERSION_PATCH 5
+#define G_VERSION_PATCH 6
#define CONF_FILENAME "giada.conf"
/* -- GUI ------------------------------------------------------------------- */
-#ifdef G_OS_WINDOWS
- #define G_GUI_SLEEP 1000/24
-#else
- #define G_GUI_SLEEP 1000000/24 // == 1.000.000 / 24 == 1/24 sec == 24 Hz
-#endif
-#define G_GUI_WIDTH 816
-#define G_GUI_HEIGHT 510
-#define G_GUI_PLUGIN_RATE 0.05 // refresh rate for plugin GUIs
+#define G_GUI_REFRESH_RATE 1000/24
+#define G_GUI_PLUGIN_RATE 0.05 // refresh rate for plugin GUI
#define G_GUI_FONT_SIZE_BASE 12
#define G_GUI_INNER_MARGIN 4
#define G_GUI_OUTER_MARGIN 8
#define G_MAX_GRID_VAL 64
#define G_MIN_BUF_SIZE 8
#define G_MAX_BUF_SIZE 4096
+#define G_MIN_GUI_WIDTH 816
+#define G_MIN_GUI_HEIGHT 510
#define PATCH_KEY_CHANNEL_VOLUME "volume"
#define PATCH_KEY_CHANNEL_PAN "pan"
#define PATCH_KEY_CHANNEL_MIDI_IN "midi_in"
+#define PATCH_KEY_CHANNEL_MIDI_IN_VELO_AS_VOL "midi_in_velo_as_vol"
#define PATCH_KEY_CHANNEL_MIDI_IN_KEYPRESS "midi_in_keypress"
#define PATCH_KEY_CHANNEL_MIDI_IN_KEYREL "midi_in_keyrel"
#define PATCH_KEY_CHANNEL_MIDI_IN_KILL "midi_in_kill"
time (&t);
gu_log("[init] Giada " G_VERSION_STR " - %s", ctime(&t));
- conf::init();
conf::read();
patch::init();
void init_startGUI(int argc, char** argv)
{
- G_MainWin = new gdMainWindow(G_GUI_WIDTH, G_GUI_HEIGHT, "", argc, argv);
+ G_MainWin = new gdMainWindow(G_MIN_GUI_WIDTH, G_MIN_GUI_HEIGHT, "", argc, argv);
G_MainWin->resize(conf::mainWindowX, conf::mainWindowY, conf::mainWindowW,
conf::mainWindowH);
{
namespace
{
-RtAudio *rtSystem = nullptr;
-bool status = false;
-unsigned numDevs = 0;
-bool inputEnabled = false;
-unsigned realBufsize = 0; // reale bufsize from the soundcard
-int api = 0;
+RtAudio* rtSystem = nullptr;
+bool status = false;
+unsigned numDevs = 0;
+bool inputEnabled = false;
+unsigned realBufsize = 0; // reale bufsize from the soundcard
+int api = 0;
#ifdef __linux__
JackState jackState;
-jack_client_t *jackGetHandle()
+jack_client_t* jackGetHandle()
{
return static_cast<jack_client_t*>(rtSystem->rtapi_->__HACK__getJackClient());
}
if (pure == ch->midiInKeyPress) {
gu_log(" >>> keyPress, ch=%d (pure=0x%X)\n", ch->index, pure);
- glue_keyPress(ch, false, false);
+ c::io::keyPress(ch, false, false, midiEvent.getVelocity());
}
else if (pure == ch->midiInKeyRel) {
gu_log(" >>> keyRel ch=%d (pure=0x%X)\n", ch->index, pure);
- glue_keyRelease(ch, false, false);
+ c::io::keyRelease(ch, false, false);
}
else if (pure == ch->midiInMute) {
gu_log(" >>> mute ch=%d (pure=0x%X)\n", ch->index, pure);
- glue_toggleMute(ch, false);
+ c::channel::toggleMute(ch, false);
}
else if (pure == ch->midiInKill) {
gu_log(" >>> kill ch=%d (pure=0x%X)\n", ch->index, pure);
- glue_kill(ch);
+ c::channel::kill(ch);
}
else if (pure == ch->midiInArm) {
gu_log(" >>> arm ch=%d (pure=0x%X)\n", ch->index, pure);
- glue_toggleArm(ch, false);
+ c::channel::toggleArm(ch, false);
}
else if (pure == ch->midiInSolo) {
gu_log(" >>> solo ch=%d (pure=0x%X)\n", ch->index, pure);
- glue_toggleSolo(ch, false);
+ c::channel::toggleSolo(ch, false);
}
else if (pure == ch->midiInVolume) {
float vf = midiEvent.getVelocity() / 127.0f;
gu_log(" >>> volume ch=%d (pure=0x%X, value=%d, float=%f)\n",
ch->index, pure, midiEvent.getVelocity(), vf);
- glue_setVolume(ch, vf, false);
+ c::channel::setVolume(ch, vf, false);
}
else {
SampleChannel* sch = static_cast<SampleChannel*>(ch);
float vf = midiEvent.getVelocity() / (127/4.0f); // [0-127] ~> [0.0-4.0]
gu_log(" >>> pitch ch=%d (pure=0x%X, value=%d, float=%f)\n",
sch->index, pure, midiEvent.getVelocity(), vf);
- glue_setPitch(sch, vf);
+ c::channel::setPitch(sch, vf);
}
else
if (pure == sch->midiInReadActions) {
gu_log(" >>> toggle read actions ch=%d (pure=0x%X)\n", sch->index, pure);
- glue_toggleReadingRecs(sch, false);
+ c::channel::toggleReadingRecs(sch, false);
}
}
}
else if (pure == conf::midiInActionRec) {
gu_log(" >>> actionRec (master) (pure=0x%X)\n", pure);
- glue_startStopActionRec(false);
+ c::io::startStopActionRec(false);
}
else if (pure == conf::midiInInputRec) {
gu_log(" >>> inputRec (master) (pure=0x%X)\n", pure);
- glue_startStopInputRec(false);
+ c::io::startStopInputRec(false);
}
else if (pure == conf::midiInMetronome) {
gu_log(" >>> metronome (master) (pure=0x%X)\n", pure);
if (!storager::setFloat (jChannel, PATCH_KEY_CHANNEL_VOLUME, channel.volume)) return 0;
if (!storager::setFloat (jChannel, PATCH_KEY_CHANNEL_PAN, channel.pan)) return 0;
if (!storager::setBool (jChannel, PATCH_KEY_CHANNEL_MIDI_IN, channel.midiIn)) return 0;
+ if (!storager::setBool (jChannel, PATCH_KEY_CHANNEL_MIDI_IN_VELO_AS_VOL, channel.midiInVeloAsVol)) return 0;
if (!storager::setUint32(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_KEYPRESS, channel.midiInKeyPress)) return 0;
if (!storager::setUint32(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_KEYREL, channel.midiInKeyRel)) return 0;
if (!storager::setUint32(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_KILL, channel.midiInKill)) return 0;
json_object_set_new(jChannel, PATCH_KEY_CHANNEL_VOLUME, json_real(channel.volume));
json_object_set_new(jChannel, PATCH_KEY_CHANNEL_PAN, json_real(channel.pan));
json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_IN, json_boolean(channel.midiIn));
+ json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_VELO_AS_VOL, json_boolean(channel.midiInVeloAsVol));
json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_KEYPRESS, json_integer(channel.midiInKeyPress));
json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_KEYREL, json_integer(channel.midiInKeyRel));
json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_KILL, json_integer(channel.midiInKill));
#include <string>
#include <vector>
-#ifdef __APPLE__ // our Clang still doesn't know about cstdint (c++11 stuff)
- #include <stdint.h>
-#else
- #include <cstdint>
-#endif
+#include <cstdint>
namespace giada {
float volume;
float pan;
bool midiIn;
+ bool midiInVeloAsVol;
uint32_t midiInKeyPress;
uint32_t midiInKeyRel;
uint32_t midiInKill;
extern std::string header;
extern std::string version;
-extern int versionMajor;
-extern int versionMinor;
-extern int versionPatch;
+extern int versionMajor;
+extern int versionMinor;
+extern int versionPatch;
extern std::string name;
-extern float bpm;
-extern int bars;
-extern int beats;
-extern int quantize;
-extern float masterVolIn;
-extern float masterVolOut;
-extern int metronome;
-extern int lastTakeId;
-extern int samplerate; // original samplerate when the patch was saved
+extern float bpm;
+extern int bars;
+extern int beats;
+extern int quantize;
+extern float masterVolIn;
+extern float masterVolOut;
+extern int metronome;
+extern int lastTakeId;
+extern int samplerate; // original samplerate when the patch was saved
extern std::vector<column_t> columns;
extern std::vector<channel_t> channels;
void SampleChannel::sum(int frame, bool running)
{
+ // TODO - Opaque channels' processing
+ // TODO - Opaque channels' processing
+ // TODO - Opaque channels' processing
+
if (wave == nullptr || status & ~(STATUS_PLAY | STATUS_ENDING))
return;
}
-float SampleChannel::getBoost()
+float SampleChannel::getBoost() const
{
return boost;
}
/* -------------------------------------------------------------------------- */
-void SampleChannel::setReadActions(bool v, bool recsStopOnChanHalt)
+void SampleChannel::setReadActions(bool v, bool killOnFalse)
{
readActions = v;
- if (!readActions && recsStopOnChanHalt)
+ if (!readActions && killOnFalse)
kill(0); /// FIXME - wrong frame value
}
pluginHost::processStack(vChan, pluginHost::CHANNEL, this);
#endif
+ // TODO - Opaque channels' processing
for (int j=0; j<bufferSize; j+=2) {
outBuffer[j] += vChan[j] * volume * calcPanning(0) * boost;
outBuffer[j+1] += vChan[j+1] * volume * calcPanning(1) * boost;
else
trackerPreview = fillChan(vChanPreview, trackerPreview, 0, false);
+ // TODO - Opaque channels' processing
for (int j=0; j<bufferSize; j+=2) {
outBuffer[j] += vChanPreview[j] * volume * calcPanning(0) * boost;
outBuffer[j+1] += vChanPreview[j+1] * volume * calcPanning(1) * boost;
boost = pch->boost;
readActions = pch->recActive;
recStatus = readActions ? REC_READING : REC_STOPPED;
+ midiInVeloAsVol = pch->midiInVeloAsVol;
midiInReadActions = pch->midiInReadActions;
midiInPitch = pch->midiInPitch;
inputMonitor = pch->inputMonitor;
}
}
else {
-
+ // TODO - Opaque channels count
rsmp_data.data_in = wave->getData()+start; // source data
rsmp_data.input_frames = (end-start)/2; // how many readable bytes
rsmp_data.data_out = dest+offset; // destination (processed data)
int getTrackerPreview() const;
int getShift() const;
+ float getBoost() const;
+
void setShift(int s);
void reset(int frame);
void hardStop(int frame);
/* setReadActions
- * if enabled (v == true), recorder will read actions from this channel. If
- * recsStopOnChanHalt == true, stop reading actions right away. */
+ If enabled (v == true), recorder will read actions from this channel. If
+ killOnFalse == true and disabled, will also kill the channel. */
- void setReadActions(bool v, bool recsStopOnChanHalt);
+ void setReadActions(bool v, bool killOnFalse);
void setBoost(float v);
- float getBoost();
void setOnEndPreviewCb(std::function<void()> f);
/* midi stuff */
+ bool midiInVeloAsVol;
uint32_t midiInReadActions;
uint32_t midiInPitch;
private:
float* m_data;
- int m_size; // Wave size in bytes (size in stereo: size / 2)
+ int m_size; // Wave size in bytes (size in frames: m_size / m_channels)
int m_channels;
int m_rate;
int m_bits;
~Wave();
Wave(const Wave& other);
- void setRate(int v);
- void setChannels(int v);
- void setData(float* data, int size);
- void setLogical(bool l);
- void setEdited(bool e);
-
/* setPath
Sets new path 'p'. If 'id' != -1 inserts a numeric id next to the file
extension, e.g. : /path/to/sample-[id].wav */
std::string getPath() const;
int getBits() const;
float* getData() const;
- int getSize() const; // with channels count
+ int getSize() const; // in frames
int getDuration() const;
bool isLogical() const;
bool isEdited() const;
+ void setRate(int v);
+ void setChannels(int v);
+ void setData(float* data, int size);
+ void setLogical(bool l);
+ void setEdited(bool e);
+
/* clear
Resets Wave to init state. */
using std::string;
-using namespace giada::m;
-static bool __soloSession__ = false;
+namespace giada {
+namespace c {
+namespace channel
+{
+namespace
+{
+bool soloSession__ = false;
+} // {anonymous}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
-int glue_loadChannel(SampleChannel* ch, const string& fname)
+
+int loadChannel(SampleChannel* ch, const string& fname)
{
+ using namespace giada::m;
+
/* Always stop a channel before loading a new sample in it. This will prevent
issues if tracker is outside the boundaries of the new sample -> segfault. */
return result;
if (wave->getRate() != conf::samplerate) {
- gu_log("[glue_loadChannel] input rate (%d) != system rate (%d), conversion needed\n",
+ gu_log("[loadChannel] input rate (%d) != system rate (%d), conversion needed\n",
wave->getRate(), conf::samplerate);
result = waveManager::resample(wave, conf::rsmpQuality, conf::samplerate);
if (result != G_RES_OK) {
/* -------------------------------------------------------------------------- */
-Channel* glue_addChannel(int column, int type, int size)
+Channel* addChannel(int column, int type, int size)
{
- Channel* ch = mh::addChannel(type);
+ Channel* ch = m::mh::addChannel(type);
geChannel* gch = G_MainWin->keyboard->addChannel(column, ch, size);
ch->guiChannel = gch;
return ch;
/* -------------------------------------------------------------------------- */
-void glue_deleteChannel(Channel* ch)
+void deleteChannel(Channel* ch)
{
+ using namespace giada::m;
+
if (!gdConfirmWin("Warning", "Delete channel: are you sure?"))
return;
recorder::clearChan(ch->index);
/* -------------------------------------------------------------------------- */
-void glue_freeChannel(Channel* ch)
+void freeChannel(Channel* ch)
{
if (ch->status == STATUS_PLAY) {
if (!gdConfirmWin("Warning", "This action will stop the channel: are you sure?"))
return;
G_MainWin->keyboard->freeChannel(ch->guiChannel);
- recorder::clearChan(ch->index);
+ m::recorder::clearChan(ch->index);
ch->hasActions = false;
ch->empty();
/* -------------------------------------------------------------------------- */
-void glue_toggleArm(Channel* ch, bool gui)
+void toggleArm(Channel* ch, bool gui)
{
ch->setArmed(!ch->isArmed());
if (!gui)
/* -------------------------------------------------------------------------- */
-void glue_toggleInputMonitor(Channel* ch)
+void toggleInputMonitor(Channel* ch)
{
SampleChannel* sch = static_cast<SampleChannel*>(ch);
sch->inputMonitor = !sch->inputMonitor;
/* -------------------------------------------------------------------------- */
-int glue_cloneChannel(Channel* src)
+int cloneChannel(Channel* src)
{
+ using namespace giada::m;
+
Channel* ch = mh::addChannel(src->type);
geChannel* gch = G_MainWin->keyboard->addChannel(src->guiChannel->getColumnIndex(),
ch, src->guiChannel->getSize());
/* -------------------------------------------------------------------------- */
-void glue_setVolume(Channel* ch, float v, bool gui, bool editor)
+void setVolume(Channel* ch, float v, bool gui, bool editor)
{
- ch->volume = v;
+ ch->setVolume(v);
/* Changing channel volume? Update wave editor (if it's shown). */
if (!editor) {
- gdSampleEditor *gdEditor = (gdSampleEditor*) gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR);
+ gdSampleEditor* gdEditor = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
if (gdEditor) {
Fl::lock();
gdEditor->volumeTool->refresh();
/* -------------------------------------------------------------------------- */
-void glue_setPitch(SampleChannel* ch, float val)
+void setPitch(SampleChannel* ch, float val)
{
ch->setPitch(val);
gdSampleEditor* gdEditor = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
/* -------------------------------------------------------------------------- */
-void glue_setPanning(SampleChannel* ch, float val)
+void setPanning(SampleChannel* ch, float val)
{
ch->setPan(val);
gdSampleEditor* gdEditor = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
/* -------------------------------------------------------------------------- */
-void glue_toggleMute(Channel* ch, bool gui)
+void toggleMute(Channel* ch, bool gui)
{
+ using namespace giada::m;
+
if (recorder::active && recorder::canRec(ch, clock::isRunning(), mixer::recording)) {
if (!ch->mute) {
recorder::startOverdub(ch->index, G_ACTION_MUTES, clock::getCurrentFrame(),
/* -------------------------------------------------------------------------- */
-void glue_toggleSolo(Channel* ch, bool gui)
+void toggleSolo(Channel* ch, bool gui)
{
- ch->solo ? glue_setSoloOn(ch, gui) : glue_setSoloOff(ch, gui);
+ ch->solo ? setSoloOn(ch, gui) : setSoloOff(ch, gui);
}
/* -------------------------------------------------------------------------- */
-void glue_kill(Channel* ch)
+void kill(Channel* ch)
{
ch->kill(0); // on frame 0: it's a user-generated event
}
/* -------------------------------------------------------------------------- */
-void glue_setSoloOn(Channel* ch, bool gui)
+void setSoloOn(Channel* ch, bool gui)
{
+ using namespace giada::m;
+
/* if there's no solo session, store mute configuration of all chans
* and start the session */
- if (!__soloSession__) {
+ if (!soloSession__) {
for (unsigned i=0; i<mixer::channels.size(); i++) {
Channel *och = mixer::channels.at(i);
och->mute_s = och->mute;
}
- __soloSession__ = true;
+ soloSession__ = true;
}
ch->solo = !ch->solo;
/* -------------------------------------------------------------------------- */
-void glue_setSoloOff(Channel* ch, bool gui)
+void setSoloOff(Channel* ch, bool gui)
{
+ using namespace giada::m;
+
/* if this is uniqueSolo, stop solo session and restore mute status,
* else mute this */
if (mh::uniqueSolo(ch)) {
- __soloSession__ = false;
+ soloSession__ = false;
for (unsigned i=0; i<mixer::channels.size(); i++) {
Channel *och = mixer::channels.at(i);
if (och->mute_s) {
/* -------------------------------------------------------------------------- */
-void glue_setBoost(SampleChannel* ch, float val)
+void setBoost(SampleChannel* ch, float val)
{
ch->setBoost(val);
gdSampleEditor *gdEditor = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
/* -------------------------------------------------------------------------- */
-void glue_setName(Channel* ch, const string& name)
+void setName(Channel* ch, const string& name)
{
ch->setName(name);
ch->guiChannel->update();
/* -------------------------------------------------------------------------- */
-void glue_toggleReadingRecs(SampleChannel* ch, bool gui)
+void toggleReadingRecs(SampleChannel* ch, bool gui)
{
- /* When you call glue_startReadingRecs with conf::treatRecsAsLoops, the
+
+ /* When you call startReadingRecs with conf::treatRecsAsLoops, the
member value ch->readActions actually is not set to true immediately, because
the channel is in wait mode (REC_WAITING). ch->readActions will become true on
the next first beat. So a 'stop rec' command should occur also when
then you press 'R' again to undo the status. */
if (ch->readActions || (!ch->readActions && ch->recStatus == REC_WAITING))
- glue_stopReadingRecs(ch, gui);
+ stopReadingRecs(ch, gui);
else
- glue_startReadingRecs(ch, gui);
+ startReadingRecs(ch, gui);
}
/* -------------------------------------------------------------------------- */
-void glue_startReadingRecs(SampleChannel* ch, bool gui)
+void startReadingRecs(SampleChannel* ch, bool gui)
{
+ using namespace giada::m;
+
if (conf::treatRecsAsLoops)
ch->recStatus = REC_WAITING;
else
ch->setReadActions(true, conf::recsStopOnChanHalt);
if (!gui) {
Fl::lock();
- ((geSampleChannel*)ch->guiChannel)->readActions->value(1);
+ static_cast<geSampleChannel*>(ch->guiChannel)->readActions->value(1);
Fl::unlock();
}
}
/* -------------------------------------------------------------------------- */
-void glue_stopReadingRecs(SampleChannel* ch, bool gui)
+void stopReadingRecs(SampleChannel* ch, bool gui)
{
- /* First of all, if the mixer is not running just stop and disable everything.
+ using namespace giada::m;
+
+ /* First of all, if the clock is not running just stop and disable everything.
Then if "treatRecsAsLoop" wait until the sequencer reaches beat 0, so put the
channel in REC_ENDING status. */
if (!clock::isRunning()) {
ch->recStatus = REC_STOPPED;
- ch->readActions = false;
+ ch->setReadActions(false, false);
}
else
+ if (ch->recStatus == REC_WAITING)
+ ch->recStatus = REC_STOPPED;
+ else
+ if (ch->recStatus == REC_ENDING)
+ ch->recStatus = REC_READING;
+ else
if (conf::treatRecsAsLoops)
ch->recStatus = REC_ENDING;
else
if (!gui) {
Fl::lock();
- ((geSampleChannel*)ch->guiChannel)->readActions->value(0);
+ static_cast<geSampleChannel*>(ch->guiChannel)->readActions->value(0);
Fl::unlock();
}
}
+
+}}}; // giada::c::channel::
\ No newline at end of file
class SampleChannel;
class gdSampleEditor;
-
+namespace giada {
+namespace c {
+namespace channel
+{
/* addChannel
- * add an empty new channel to the stack. Returns the new channel. */
+Adds an empty new channel to the stack. Returns the new channel. */
-Channel* glue_addChannel(int column, int type, int size);
+Channel* addChannel(int column, int type, int size);
/* loadChannel
- * fill an existing channel with a wave. */
+Fills an existing channel with a wave. */
-int glue_loadChannel(SampleChannel* ch, const std::string& fname);
+int loadChannel(SampleChannel* ch, const std::string& fname);
/* deleteChannel
- * Remove a channel from Mixer. */
+Removes a channel from Mixer. */
-void glue_deleteChannel(Channel* ch);
+void deleteChannel(Channel* ch);
/* freeChannel
- * Unload the sample from a sample channel. */
+Unloads the sample from a sample channel. */
-void glue_freeChannel(Channel* ch);
+void freeChannel(Channel* ch);
/* cloneChannel
- * Make an exact copy of Channel *ch. */
+Makes an exact copy of Channel *ch. */
-int glue_cloneChannel(Channel* ch);
+int cloneChannel(Channel* ch);
/* toggle/set*
Toggles or set several channel properties. If gui == true the signal comes from
a manual interaction on the GUI, otherwise it's a MIDI/Jack/external signal. */
-void glue_toggleArm(Channel* ch, bool gui=true);
-void glue_toggleInputMonitor(Channel* ch);
-void glue_kill(Channel* ch);
-void glue_toggleMute(Channel* ch, bool gui=true);
-void glue_setSoloOn(Channel* ch, bool gui=true);
-void glue_setSoloOff(Channel* ch, bool gui=true);
-void glue_toggleSolo(Channel* ch, bool gui=true);
-void glue_setVolume(Channel* ch, float v, bool gui=true, bool editor=false);
-void glue_setName(Channel* ch, const std::string& name);
-void glue_setPitch(SampleChannel* ch, float val);
-void glue_setPanning(SampleChannel* ch, float val);
-void glue_setBoost(SampleChannel* ch, float val);
+void toggleArm(Channel* ch, bool gui=true);
+void toggleInputMonitor(Channel* ch);
+void kill(Channel* ch);
+void toggleMute(Channel* ch, bool gui=true);
+void setSoloOn(Channel* ch, bool gui=true);
+void setSoloOff(Channel* ch, bool gui=true);
+void toggleSolo(Channel* ch, bool gui=true);
+void setVolume(Channel* ch, float v, bool gui=true, bool editor=false);
+void setName(Channel* ch, const std::string& name);
+void setPitch(SampleChannel* ch, float val);
+void setPanning(SampleChannel* ch, float val);
+void setBoost(SampleChannel* ch, float val);
/* toggleReadingRecs
Handles the 'R' button. If gui == true the signal comes from an user interaction
on the GUI, otherwise it's a MIDI/Jack/external signal. */
-void glue_toggleReadingRecs(SampleChannel* ch, bool gui=true);
-void glue_startReadingRecs(SampleChannel* ch, bool gui=true);
-void glue_stopReadingRecs(SampleChannel* ch, bool gui=true);
+void toggleReadingRecs(SampleChannel* ch, bool gui=true);
+void startReadingRecs(SampleChannel* ch, bool gui=true);
+void stopReadingRecs(SampleChannel* ch, bool gui=true);
+
+}}}; // giada::c::channel::
#endif
#include "../gui/elems/mainWindow/keyboard/sampleChannel.h"
#include "../utils/gui.h"
#include "../utils/log.h"
+#include "../utils/math.h"
#include "../core/recorder.h"
#include "../core/kernelAudio.h"
#include "../core/mixer.h"
#include "io.h"
-extern gdMainWindow *G_MainWin;
+extern gdMainWindow* G_MainWin;
-using namespace giada::m;
+namespace giada {
+namespace c {
+namespace io
+{
+namespace
+{
+void ctrlPress(SampleChannel* ch)
+{
+ c::channel::toggleMute(ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void shiftPress(SampleChannel* ch)
+{
+ /* action recording on:
+ if sequencer is running, rec a killchan
+ action recording off:
+ if chan has recorded events:
+ | if seq is playing OR channel 'c' is stopped, de/activate recs
+ | else kill chan
+ else kill chan. */
+
+ if (m::recorder::active) {
+ if (!m::clock::isRunning())
+ return;
+ ch->kill(0); // on frame 0: user-generated event
+ if (m::recorder::canRec(ch, m::clock::isRunning(), m::mixer::recording) &&
+ !(ch->mode & LOOP_ANY))
+ { // don't record killChan actions for LOOP channels
+ m::recorder::rec(ch->index, G_ACTION_KILL, m::clock::getCurrentFrame());
+ ch->hasActions = true;
+ }
+ }
+ else {
+ if (ch->hasActions) {
+ if (m::clock::isRunning() || ch->status == STATUS_OFF)
+ ch->readActions ? c::channel::stopReadingRecs(ch) : c::channel::startReadingRecs(ch);
+ else
+ ch->kill(0); // on frame 0: user-generated event
+ }
+ else
+ ch->kill(0); // on frame 0: user-generated event
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void cleanPress(SampleChannel* ch, int velocity)
+{
+ /* Record now if the quantizer is off, otherwise let mixer to handle it when a
+ quantoWait has passed. Moreover, KEYPRESS and KEYREL are meaningless for loop
+ modes. */
+
+ if (m::clock::getQuantize() == 0 &&
+ m::recorder::canRec(ch, m::clock::isRunning(), m::mixer::recording) &&
+ !(ch->mode & LOOP_ANY))
+ {
+ if (ch->mode == SINGLE_PRESS) {
+ m::recorder::startOverdub(ch->index, G_ACTION_KEYS, m::clock::getCurrentFrame(),
+ m::kernelAudio::getRealBufSize());
+ ch->readActions = false; // don't read actions while overdubbing
+ }
+ else {
+ m::recorder::rec(ch->index, G_ACTION_KEYPRESS, m::clock::getCurrentFrame());
+ ch->hasActions = true;
+
+ /* Why return here? You record an action and then you call ch->start:
+ Mixer, which is on another thread, reads your newly recorded action if you
+ have readActions == true, and then ch->start kicks in right after it.
+ The result: Mixer plays the channel (due to the new action) but ch->start
+ kills it right away (because the sample is playing). Fix: call ch->start
+ only if you are not recording anything, i.e. let Mixer play it. */
+
+ if (ch->readActions)
+ return;
+ }
+ }
+
+ /* This is a user-generated event, so it's on frame 0. For one-shot modes,
+ velocity drives the internal volume. */
+ if (ch->mode & SINGLE_ANY && ch->midiInVeloAsVol)
+ ch->setVolumeI(u::math::map((float)velocity, 0.0f, 127.0f, 0.0f, 1.0f));
-void glue_keyPress(Channel *ch, bool ctrl, bool shift)
+ ch->start(0, true, m::clock::getQuantize(), m::clock::isRunning(), false, true);
+}
+
+} // {anonymous}
+
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+
+void keyPress(Channel* ch, bool ctrl, bool shift, int velocity)
{
if (ch->type == CHANNEL_SAMPLE)
- glue_keyPress((SampleChannel*)ch, ctrl, shift);
+ keyPress(static_cast<SampleChannel*>(ch), ctrl, shift, velocity);
else
- glue_keyPress((MidiChannel*)ch, ctrl, shift);
+ keyPress(static_cast<MidiChannel*>(ch), ctrl, shift);
}
/* -------------------------------------------------------------------------- */
-void glue_keyRelease(Channel *ch, bool ctrl, bool shift)
+void keyRelease(Channel* ch, bool ctrl, bool shift)
{
if (ch->type == CHANNEL_SAMPLE)
- glue_keyRelease((SampleChannel*)ch, ctrl, shift);
+ keyRelease(static_cast<SampleChannel*>(ch), ctrl, shift);
}
/* -------------------------------------------------------------------------- */
-void glue_keyPress(MidiChannel *ch, bool ctrl, bool shift)
+void keyPress(MidiChannel* ch, bool ctrl, bool shift)
{
if (ctrl)
- glue_toggleMute(ch);
+ c::channel::toggleMute(ch);
else
if (shift)
ch->kill(0); // on frame 0: user-generated event
else
- ch->start(0, true, clock::getQuantize(), clock::isRunning(), false, true); // on frame 0: user-generated event
+ ch->start(0, true, m::clock::getQuantize(), m::clock::isRunning(), false, true); // on frame 0: user-generated event
}
/* -------------------------------------------------------------------------- */
-void glue_keyPress(SampleChannel *ch, bool ctrl, bool shift)
+void keyPress(SampleChannel* ch, bool ctrl, bool shift, int velocity)
{
- /* case CTRL */
-
if (ctrl)
- glue_toggleMute(ch);
-
- /* case SHIFT
- *
- * action recording on:
- * if seq is playing, rec a killchan
- * action recording off:
- * if chan has recorded events:
- * | if seq is playing OR channel 'c' is stopped, de/activate recs
- * | else kill chan
- * else kill chan */
-
+ ctrlPress(ch);
+ else if (shift)
+ shiftPress(ch);
else
- if (shift) {
- if (recorder::active) {
- if (clock::isRunning()) {
- ch->kill(0); // on frame 0: user-generated event
- if (recorder::canRec(ch, clock::isRunning(), mixer::recording) &&
- !(ch->mode & LOOP_ANY))
- { // don't record killChan actions for LOOP channels
- recorder::rec(ch->index, G_ACTION_KILL, clock::getCurrentFrame());
- ch->hasActions = true;
- }
- }
- }
- else {
- if (ch->hasActions) {
- if (clock::isRunning() || ch->status == STATUS_OFF)
- ch->readActions ? glue_stopReadingRecs(ch) : glue_startReadingRecs(ch);
- else
- ch->kill(0); // on frame 0: user-generated event
- }
- else
- ch->kill(0); // on frame 0: user-generated event
- }
- }
- else { /* case no modifier */
-
- /* record now if the quantizer is off, otherwise let mixer to handle it
- * when a quantoWait has passed. Moreover, KEYPRESS and KEYREL are
- * meaningless for loop modes */
-
- if (clock::getQuantize() == 0 &&
- recorder::canRec(ch, clock::isRunning(), mixer::recording) &&
- !(ch->mode & LOOP_ANY))
- {
- if (ch->mode == SINGLE_PRESS) {
- recorder::startOverdub(ch->index, G_ACTION_KEYS, clock::getCurrentFrame(),
- kernelAudio::getRealBufSize());
- ch->readActions = false; // don't read actions while overdubbing
- }
- else {
- recorder::rec(ch->index, G_ACTION_KEYPRESS, clock::getCurrentFrame());
- ch->hasActions = true;
-
- /* Why return here? You record an action (as done on line 148) and then
- you call ch->start (line 165): Mixer, which is on another thread, reads
- your newly recorded action if you have readActions == true, and then
- ch->start kicks in right after it (as done on line 165).
- The result: Mixer plays the channel (due to the new action) but ch->start
- kills it right away (because the sample is playing). Fix: call ch->start
- only if you are not recording anything, i.e. let Mixer play it. */
-
- if (ch->readActions)
- return;
- }
- }
-
- /* This is a user-generated event, so it's on frame 0 */
-
- ch->start(0, true, clock::getQuantize(), clock::isRunning(), false, true);
- }
-
- /* the GUI update is done by gui_refresh() */
+ cleanPress(ch, velocity);
}
/* -------------------------------------------------------------------------- */
-void glue_keyRelease(SampleChannel *ch, bool ctrl, bool shift)
+void keyRelease(SampleChannel* ch, bool ctrl, bool shift)
{
+ using namespace giada::m;
+
if (ctrl || shift)
return;
if (ch->mode == SINGLE_PRESS && recorder::canRec(ch, clock::isRunning(), mixer::recording))
recorder::stopOverdub(clock::getCurrentFrame(), clock::getTotalFrames(),
- &mixer::mutex_recs);
+ &mixer::mutex_recs);
/* the GUI update is done by gui_refresh() */
/* -------------------------------------------------------------------------- */
-void glue_startStopActionRec(bool gui)
+void startStopActionRec(bool gui)
{
- recorder::active ? glue_stopActionRec(gui) : glue_startActionRec(gui);
+ m::recorder::active ? stopActionRec(gui) : startActionRec(gui);
}
/* -------------------------------------------------------------------------- */
-void glue_startActionRec(bool gui)
+void startActionRec(bool gui)
{
+ using namespace giada::m;
+
if (kernelAudio::getStatus() == false)
return;
/* -------------------------------------------------------------------------- */
-void glue_stopActionRec(bool gui)
+void stopActionRec(bool gui)
{
/* stop the recorder and sort new actions */
- recorder::active = false;
- recorder::sortActions();
+ m::recorder::active = false;
+ m::recorder::sortActions();
- for (unsigned i=0; i<mixer::channels.size(); i++)
+ for (Channel* ch : m::mixer::channels)
{
- if (mixer::channels.at(i)->type == CHANNEL_MIDI)
+ if (ch->type == CHANNEL_MIDI)
continue;
- SampleChannel *ch = (SampleChannel*) mixer::channels.at(i);
- G_MainWin->keyboard->setChannelWithActions((geSampleChannel*)ch->guiChannel);
- if (!ch->readActions && ch->hasActions)
- glue_startReadingRecs(ch, false);
+ SampleChannel* sch = static_cast<SampleChannel*>(ch);
+ G_MainWin->keyboard->setChannelWithActions(static_cast<geSampleChannel*>(sch->guiChannel));
+ if (!sch->readActions && sch->hasActions)
+ c::channel::startReadingRecs(sch, false);
}
if (!gui) {
/* -------------------------------------------------------------------------- */
-void glue_startStopInputRec(bool gui)
+void startStopInputRec(bool gui)
{
- if (mixer::recording)
- glue_stopInputRec(gui);
+ if (m::mixer::recording)
+ stopInputRec(gui);
else
- if (!glue_startInputRec(gui))
+ if (!startInputRec(gui))
gdAlert("No channels armed/available for audio recording.");
}
/* -------------------------------------------------------------------------- */
-int glue_startInputRec(bool gui)
+int startInputRec(bool gui)
{
+ using namespace giada::m;
+
if (kernelAudio::getStatus() == false)
return false;
if (!mh::startInputRec()) {
- Fl::lock();
- G_MainWin->mainTransport->updateRecInput(0); // set it off, anyway
+ Fl::lock();
+ G_MainWin->mainTransport->updateRecInput(0); // set it off, anyway
Fl::unlock();
return false;
}
if (!clock::isRunning())
glue_startSeq(false); // update gui anyway
- Fl::lock();
- if (!gui)
- G_MainWin->mainTransport->updateRecInput(1);
- G_MainWin->mainTimer->setLock(true);
- Fl::unlock();
+ Fl::lock();
+ if (!gui)
+ G_MainWin->mainTransport->updateRecInput(1);
+ G_MainWin->mainTimer->setLock(true);
+ Fl::unlock();
- /* Update sample name inside sample channels' main button. This is useless for
- midi channel, but let's do it anyway. */
+ /* Update sample name inside sample channels' main button. This is useless for
+ midi channel, but let's do it anyway. */
- for (unsigned i=0; i<mixer::channels.size(); i++)
- mixer::channels.at(i)->guiChannel->update();
+ for (Channel* ch : m::mixer::channels)
+ ch->guiChannel->update();
return true;
}
/* -------------------------------------------------------------------------- */
-int glue_stopInputRec(bool gui)
+int stopInputRec(bool gui)
{
+ using namespace giada::m;
+
mh::stopInputRec();
/* Start all sample channels in loop mode that were armed, i.e. that were
recording stuff and not yet in play. They are also started in force mode, i.e.
- they must start playing right away at the current frame, not at the next first
- beat. */
+ they must start playing right away at the current frame, not at the next first
+ beat. */
for (Channel* ch : mixer::channels) {
if (ch->type == CHANNEL_MIDI)
SampleChannel* sch = static_cast<SampleChannel*>(ch);
if (sch->mode & (LOOP_ANY) && sch->status == STATUS_OFF && sch->isArmed())
sch->start(clock::getCurrentFrame(), true, clock::getQuantize(),
- clock::isRunning(), true, true);
+ clock::isRunning(), true, true);
}
- Fl::lock();
- if (!gui)
- G_MainWin->mainTransport->updateRecInput(0);
- G_MainWin->mainTimer->setLock(false);
- Fl::unlock();
+ Fl::lock();
+ if (!gui)
+ G_MainWin->mainTransport->updateRecInput(0);
+ G_MainWin->mainTimer->setLock(false);
+ Fl::unlock();
return 1;
}
+
+}}} // giada::c::io::
\ No newline at end of file
#define G_GLUE_IO_H
+class Channel;
+class SampleChannel;
+class MidiChannel;
+
+namespace giada {
+namespace c {
+namespace io
+{
/* keyPress / keyRelease
* handle the key pressure, either via mouse/keyboard or MIDI. If gui
* is true it means that the event comes from the main window (mouse,
* keyb or MIDI), otherwise the event comes from the action recorder. */
-void glue_keyPress (class Channel *ch, bool ctrl=0, bool shift=0);
-void glue_keyPress (class SampleChannel *ch, bool ctrl=0, bool shift=0);
-void glue_keyPress (class MidiChannel *ch, bool ctrl=0, bool shift=0);
-void glue_keyRelease(class Channel *ch, bool ctrl=0, bool shift=0);
-void glue_keyRelease(class SampleChannel *ch, bool ctrl=0, bool shift=0);
+void keyPress (Channel* ch, bool ctrl, bool shift, int velocity);
+void keyPress (SampleChannel* ch, bool ctrl, bool shift, int velocity);
+void keyPress (MidiChannel* ch, bool ctrl, bool shift);
+void keyRelease(Channel* ch, bool ctrl, bool shift);
+void keyRelease(SampleChannel* ch, bool ctrl, bool shift);
/* start/stopActionRec
Handles the action recording. If gui == true the signal comes from an user
interaction, otherwise it's a MIDI/Jack/external signal. */
-void glue_startStopActionRec(bool gui=true);
-void glue_startActionRec(bool gui=true);
-void glue_stopActionRec(bool gui=true);
+void startStopActionRec(bool gui=true);
+void startActionRec(bool gui=true);
+void stopActionRec(bool gui=true);
/* start/stopInputRec
Handles the input recording (take). If gui == true the signal comes from an
internal interaction on the GUI, otherwise it's a MIDI/Jack/external signal. */
-void glue_startStopInputRec(bool gui=true);
-int glue_startInputRec (bool gui=true);
-int glue_stopInputRec (bool gui=true);
+void startStopInputRec(bool gui=true);
+int startInputRec (bool gui=true);
+int stopInputRec (bool gui=true);
+}}} // giada::c::io::
#endif
extern gdMainWindow *G_MainWin;
-using namespace giada::m;
-
-
namespace giada {
namespace c {
namespace sampleEditor
void cut(SampleChannel* ch, int a, int b)
{
copy(ch, a, b);
- if (!wfx::cut(ch->wave, a, b)) {
+ if (!m::wfx::cut(ch->wave, a, b)) {
gdAlert("Unable to cut the sample!");
return;
}
if (m_waveBuffer != nullptr)
delete m_waveBuffer;
- int result = waveManager::createFromWave(ch->wave, a, b, &m_waveBuffer);
+ int result = m::waveManager::createFromWave(ch->wave, a, b, &m_waveBuffer);
if (result != G_RES_OK) {
gu_log("[sampleEditor::copy] unable to create wave buffer!\n");
return;
return;
}
- wfx::paste(m_waveBuffer, ch->wave, a);
+ m::wfx::paste(m_waveBuffer, ch->wave, a);
/* Shift begin/end points to keep the previous position. */
void silence(SampleChannel* ch, int a, int b)
{
- wfx::silence(ch->wave, a, b);
+ m::wfx::silence(ch->wave, a, b);
gdSampleEditor* gdEditor = getSampleEditorWindow();
gdEditor->waveTools->waveform->refresh();
}
void fade(SampleChannel* ch, int a, int b, int type)
{
- wfx::fade(ch->wave, a, b, type);
+ m::wfx::fade(ch->wave, a, b, type);
gdSampleEditor* gdEditor = getSampleEditorWindow();
gdEditor->waveTools->waveform->refresh();
}
void smoothEdges(SampleChannel* ch, int a, int b)
{
- wfx::smooth(ch->wave, a, b);
+ m::wfx::smooth(ch->wave, a, b);
gdSampleEditor* gdEditor = getSampleEditorWindow();
gdEditor->waveTools->waveform->refresh();
}
void reverse(SampleChannel* ch, int a, int b)
{
- wfx::reverse(ch->wave, a, b);
+ m::wfx::reverse(ch->wave, a, b);
gdSampleEditor* gdEditor = getSampleEditorWindow();
gdEditor->waveTools->waveform->refresh();
}
void normalizeHard(SampleChannel* ch, int a, int b)
{
- wfx::normalizeHard(ch->wave, a, b);
+ m::wfx::normalizeHard(ch->wave, a, b);
gdSampleEditor* gdEditor = getSampleEditorWindow();
gdEditor->waveTools->waveform->refresh();
}
void trim(SampleChannel* ch, int a, int b)
{
- if (!wfx::trim(ch->wave, a, b)) {
+ if (!m::wfx::trim(ch->wave, a, b)) {
gdAlert("Unable to trim the sample!");
return;
}
void toNewChannel(SampleChannel* ch, int a, int b)
{
- SampleChannel* newCh = static_cast<SampleChannel*>(glue_addChannel(
+ SampleChannel* newCh = static_cast<SampleChannel*>(c::channel::addChannel(
ch->guiChannel->getColumnIndex(), CHANNEL_SAMPLE, G_GUI_CHANNEL_H_1));
Wave* wave = nullptr;
- int result = waveManager::createFromWave(ch->wave, a, b, &wave);
+ int result = m::waveManager::createFromWave(ch->wave, a, b, &wave);
if (result != G_RES_OK) {
gdAlert("Unable to copy to new channel!");
return;
void shift(SampleChannel* ch, int offset)
{
- wfx::shift(ch->wave, offset - ch->getShift());
+ m::wfx::shift(ch->wave, offset - ch->getShift());
ch->setShift(offset);
gdSampleEditor* gdEditor = getSampleEditorWindow();
gdEditor->shiftTool->refresh();
using std::string;
using std::vector;
-using namespace giada::m;
+using namespace giada;
#ifdef WITH_VST
-static void glue_fillPatchGlobalsPlugins__(vector <Plugin *> *host, vector<patch::plugin_t> *patch)
+static void glue_fillPatchGlobalsPlugins__(vector <Plugin*>* host, vector<m::patch::plugin_t>* patch)
{
+ using namespace giada::m;
+
for (unsigned i=0; i<host->size(); i++) {
Plugin *pl = host->at(i);
patch::plugin_t ppl;
static void glue_fillPatchColumns__()
{
+ using namespace giada::m;
+
for (unsigned i=0; i<G_MainWin->keyboard->getTotalColumns(); i++) {
geColumn *gCol = G_MainWin->keyboard->getColumn(i);
patch::column_t pCol;
static void glue_fillPatchChannels__(bool isProject)
{
+ using namespace giada::m;
+
for (unsigned i=0; i<mixer::channels.size(); i++) {
mixer::channels.at(i)->writePatch(i, isProject);
}
static void glue_fillPatchGlobals__(const string &name)
{
+ using namespace giada::m;
+
patch::version = G_VERSION_STR;
patch::versionMajor = G_VERSION_MAJOR;
patch::versionMinor = G_VERSION_MINOR;
static bool glue_savePatch__(const string &fullPath, const string &name,
bool isProject)
{
+ using namespace giada::m;
+
patch::init();
glue_fillPatchGlobals__(name);
static string glue_makeUniqueSamplePath__(const string& base, const SampleChannel* ch)
{
+ using namespace giada::m;
+
string path = base + G_SLASH + ch->wave->getBasename(true);
if (mh::uniqueSamplePath(ch, path))
return path;
return;
if (glue_savePatch__(fullPath, name, false)) { // false == not a project
- conf::patchPath = gu_dirname(fullPath);
+ m::conf::patchPath = gu_dirname(fullPath);
browser->do_callback();
}
else
void glue_loadPatch(void* data)
{
+ using namespace giada::m;
+
gdBrowserLoad* browser = (gdBrowserLoad*) data;
string fullPath = browser->getSelectedItem();
bool isProject = gu_isProject(browser->getSelectedItem());
unsigned k = 0;
for (const patch::channel_t& pch : patch::channels) {
if (pch.column == col.index) {
- Channel* ch = glue_addChannel(pch.column, pch.type, pch.size);
+ Channel* ch = c::channel::addChannel(pch.column, pch.type, pch.size);
ch->readPatch(basePath, k, &mixer::mutex_plugins, conf::samplerate,
conf::rsmpQuality);
}
void glue_saveProject(void* data)
{
+ using namespace giada::m;
+
gdBrowserSave* browser = (gdBrowserSave*) data;
string name = gu_stripExt(browser->getName());
string folderPath = browser->getCurrentPath();
if (fullPath.empty())
return;
- int res = glue_loadChannel(static_cast<SampleChannel*>(browser->getChannel()),
+ int res = c::channel::loadChannel(static_cast<SampleChannel*>(browser->getChannel()),
fullPath);
if (res == G_RES_OK) {
- conf::samplePath = gu_dirname(fullPath);
+ m::conf::samplePath = gu_dirname(fullPath);
browser->do_callback();
G_MainWin->delSubWindow(WID_SAMPLE_EDITOR); // if editor is open
}
void glue_saveSample(void *data)
{
+ using namespace giada::m;
+
gdBrowserSave* browser = (gdBrowserSave*) data;
string name = browser->getName();
string folderPath = browser->getCurrentPath();
conf::browserW = w();
conf::browserH = h();
conf::browserPosition = browser->position();
- conf::browserLastPath = gu_dirname(browser->getSelectedItem());
+ conf::browserLastPath = browser->getCurrentDir();
conf::browserLastValue = browser->value();
}
void gdBrowserBase::cb_up()
{
- string dir = browser->getCurrentDir();
-
- /* Take 'dir' path and remove all chars up to the next slash, e.g.:
- /path/to/my/dir -> /path/to/my
- Make sure not to remove the leading '/' (OS X/Linux only). */
-
- dir = dir.substr(0, dir.find_last_of(G_SLASH_STR));
-
-#if defined(G_OS_MAC) || defined(G_OS_LINUX)
-
- if (dir.empty())
- dir = G_SLASH_STR;
-
-#endif
-
- browser->loadDir(dir);
+ browser->loadDir(gu_getUpDir(browser->getCurrentDir()));
where->value(browser->getCurrentDir().c_str());
}
#include "channelNameInput.h"
-using namespace giada::m;
+using namespace giada;
gdChannelNameInput::gdChannelNameInput(Channel* ch)
: gdWindow(400, 64, "New channel name"),
m_ch (ch)
{
+ using namespace giada::m;
+
if (conf::nameX)
resize(conf::nameX, conf::nameY, w(), h());
gdChannelNameInput::~gdChannelNameInput()
{
- conf::nameX = x();
- conf::nameY = y();
+ m::conf::nameX = x();
+ m::conf::nameY = y();
}
void gdChannelNameInput::cb_update()
{
- glue_setName(m_ch, m_name->value());
+ c::channel::setName(m_ch, m_name->value());
do_callback();
}
extern gdMainWindow *G_MainWin;
-gdMainWindow::gdMainWindow(int W, int H, const char *title, int argc, char **argv)
+gdMainWindow::gdMainWindow(int W, int H, const char* title, int argc, char** argv)
: gdWindow(W, H, title)
{
Fl::visible_focus(0);
Fl::set_boxtype(FL_UP_BOX, G_CUSTOM_UP_BOX);
Fl::set_boxtype(FL_DOWN_BOX, G_CUSTOM_DOWN_BOX);
- size_range(G_GUI_WIDTH, G_GUI_HEIGHT);
+ size_range(G_MIN_GUI_WIDTH, G_MIN_GUI_HEIGHT);
mainMenu = new geMainMenu(8, -1);
mainIO = new geMainIO(412, 8);
/* zone 1 - menus, and I/O tools */
- Fl_Group *zone1 = new Fl_Group(8, 8, W-16, 20);
+ Fl_Group* zone1 = new Fl_Group(8, 8, W-16, 20);
zone1->add(mainMenu);
zone1->resizable(new Fl_Box(300, 8, 80, 20));
zone1->add(mainIO);
/* zone 2 - mainTransport and timing tools */
- Fl_Group *zone2 = new Fl_Group(8, mainTransport->y(), W-16, mainTransport->h());
+ 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, beatMeter->y(), W-16, beatMeter->h());
+ Fl_Group* zone3 = new Fl_Group(8, beatMeter->y(), W-16, beatMeter->h());
zone3->add(beatMeter);
/* zone 4 - the keyboard (Fl_Group is unnecessary here, keyboard is
/* -------------------------------------------------------------------------- */
-void gdMainWindow::cb_endprogram(Fl_Widget *v, void *p) { G_MainWin->__cb_endprogram(); }
+void gdMainWindow::cb_endprogram(Fl_Widget* v, void* p) { G_MainWin->cb_endprogram(); }
/* -------------------------------------------------------------------------- */
-void gdMainWindow::__cb_endprogram()
+void gdMainWindow::cb_endprogram()
{
if (!gdConfirmWin("Warning", "Quit Giada: are you sure?"))
return;
{
private:
- static void cb_endprogram (Fl_Widget *v, void *p);
- inline void __cb_endprogram();
+ static void cb_endprogram(Fl_Widget* v, void* p);
+ inline void cb_endprogram();
public:
- geKeyboard *keyboard;
- geBeatMeter *beatMeter;
- geMainMenu *mainMenu;
- geMainIO *mainIO;
- geMainTimer *mainTimer;
- geMainTransport *mainTransport;
+ geKeyboard* keyboard;
+ geBeatMeter* beatMeter;
+ geMainMenu* mainMenu;
+ geMainIO* mainIO;
+ geMainTimer* mainTimer;
+ geMainTransport* mainTransport;
- gdMainWindow(int w, int h, const char *title, int argc, char **argv);
+ gdMainWindow(int w, int h, const char* title, int argc, char** argv);
};
label(title.c_str());
size_range(G_DEFAULT_MIDI_INPUT_UI_W, G_DEFAULT_MIDI_INPUT_UI_H);
- Fl_Group* groupHeader = new Fl_Group(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, w(), 20);
+ int extra = ch->type == CHANNEL_SAMPLE ? 28 : 0;
+
+ Fl_Group* groupHeader = new Fl_Group(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, w(), 20 + extra);
groupHeader->begin();
enable = new geCheck(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, 120, G_GUI_UNIT,
- "enable MIDI input");
+ "Enable MIDI input");
channel = new geChoice(enable->x()+enable->w()+44, G_GUI_OUTER_MARGIN, 120, G_GUI_UNIT);
+ veloAsVol = new geCheck(G_GUI_OUTER_MARGIN, enable->y()+enable->h()+G_GUI_OUTER_MARGIN , 120, G_GUI_UNIT,
+ "Velocity drives volume (one-shot only)");
groupHeader->resizable(nullptr);
groupHeader->end();
- container = new geScroll(G_GUI_OUTER_MARGIN, enable->y()+enable->h()+G_GUI_OUTER_MARGIN,
- w()-16, h()-76);
+ container = new geScroll(G_GUI_OUTER_MARGIN, groupHeader->y()+groupHeader->h()+G_GUI_OUTER_MARGIN,
+ w()-16, h()-72-extra);
container->begin();
addChannelLearners();
enable->value(ch->midiIn);
enable->callback(cb_enable, (void*)this);
+ if (ch->type == CHANNEL_SAMPLE) {
+ veloAsVol->value(static_cast<SampleChannel*>(ch)->midiInVeloAsVol);
+ veloAsVol->callback(cb_veloAsVol, (void*)this);
+ }
+ else
+ veloAsVol->hide();
+
channel->add("Channel (any)");
channel->add("Channel 1");
channel->add("Channel 2");
void gdMidiInputChannel::cb_enable(Fl_Widget* w, void* p) { ((gdMidiInputChannel*)p)->cb_enable(); }
void gdMidiInputChannel::cb_setChannel(Fl_Widget* w, void* p) { ((gdMidiInputChannel*)p)->cb_setChannel(); }
+void gdMidiInputChannel::cb_veloAsVol(Fl_Widget* w, void* p) { ((gdMidiInputChannel*)p)->cb_veloAsVol(); }
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
+void gdMidiInputChannel::cb_veloAsVol()
+{
+ static_cast<SampleChannel*>(ch)->midiInVeloAsVol = veloAsVol->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
void gdMidiInputChannel::cb_setChannel()
{
ch->setMidiInFilter(channel->value() == 0 ? -1 : channel->value() - 1);
geScroll* container;
geCheck* enable;
+ geCheck* veloAsVol;
geChoice* channel;
static void cb_enable(Fl_Widget* w, void* p);
static void cb_setChannel(Fl_Widget* w, void* p);
+ static void cb_veloAsVol(Fl_Widget* w, void* p);
void cb_enable();
void cb_setChannel();
+ void cb_veloAsVol();
void addChannelLearners();
/* -------------------------------------------------------------------------- */
-void gdMidiOutputSampleCh::cb_close(Fl_Widget *w, void *p) { ((gdMidiOutputSampleCh*)p)->__cb_close(); }
+void gdMidiOutputSampleCh::cb_close(Fl_Widget* w, void* p) { ((gdMidiOutputSampleCh*)p)->cb_close(); }
/* -------------------------------------------------------------------------- */
-void gdMidiOutputSampleCh::__cb_close()
+void gdMidiOutputSampleCh::cb_close()
{
ch->midiOutL = enableLightning->value();
do_callback();
{
private:
- SampleChannel *ch;
+ SampleChannel* ch;
- /* __cb_close
- override parent method, we need to do more stuff on close. */
+ /* cb_close
+ Override parent method, we need to do more stuff on close. */
- static void cb_close (Fl_Widget *w, void *p);
- inline void __cb_close();
+ static void cb_close(Fl_Widget* w, void* p);
+ inline void cb_close();
public:
- gdMidiOutputSampleCh(SampleChannel *ch);
+ gdMidiOutputSampleCh(SampleChannel* ch);
};
#endif
using std::string;
-using namespace giada::m;
-using namespace giada::c;
+using namespace giada;
gdSampleEditor::gdSampleEditor(SampleChannel* ch)
: gdWindow(640, 480),
ch(ch)
{
+ using namespace giada::m;
+
Fl_Group* upperBar = createUpperBar();
waveTools = new geWaveTools(G_GUI_OUTER_MARGIN, upperBar->y()+upperBar->h()+G_GUI_OUTER_MARGIN,
gdSampleEditor::~gdSampleEditor()
{
- conf::sampleEditorX = x();
- conf::sampleEditorY = y();
- conf::sampleEditorW = w();
- conf::sampleEditorH = h();
- conf::sampleEditorGridVal = atoi(grid->text());
- conf::sampleEditorGridOn = snap->value();
- sampleEditor::setPreview(ch, G_PREVIEW_NONE);
+ m::conf::sampleEditorX = x();
+ m::conf::sampleEditorY = y();
+ m::conf::sampleEditorW = w();
+ m::conf::sampleEditorH = h();
+ m::conf::sampleEditorGridVal = atoi(grid->text());
+ m::conf::sampleEditorGridOn = snap->value();
+ c::sampleEditor::setPreview(ch, G_PREVIEW_NONE);
}
Fl_Group* gdSampleEditor::createUpperBar()
{
+ using namespace giada::m;
+
Fl_Group* g = new Fl_Group(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, w()-16, G_GUI_UNIT);
g->begin();
grid = new geChoice(g->x(), g->y(), 50, G_GUI_UNIT);
void gdSampleEditor::cb_togglePreview()
{
+ using namespace giada::c;
+
if (play->value())
sampleEditor::setPreview(ch, G_PREVIEW_NONE);
else
void gdSampleEditor::cb_rewindPreview()
{
- sampleEditor::rewindPreview(ch);
+ c::sampleEditor::rewindPreview(ch);
}
void gdSampleEditor::cb_reload()
{
+ using namespace giada::c;
+
/* TODO - move to glue::sampleEditor */
if (!gdConfirmWin("Warning", "Reload sample: are you sure?"))
return;
- if (glue_loadChannel(ch, ch->wave->getPath()) != G_RES_OK)
+ if (channel::loadChannel(ch, ch->wave->getPath()) != G_RES_OK)
return;
- glue_setBoost(ch, G_DEFAULT_BOOST);
- glue_setPitch(ch, G_DEFAULT_PITCH);
- glue_setPanning(ch, 0.5f);
+ channel::setBoost(ch, G_DEFAULT_BOOST);
+ channel::setPitch(ch, G_DEFAULT_PITCH);
+ channel::setPanning(ch, 0.5f);
panTool->refresh();
boostTool->refresh();
#include "../../core/const.h"
#include "../../utils/string.h"
+#include "../../utils/fs.h"
#include "../dialogs/browser/browserBase.h"
#include "basics/boxtypes.h"
#include "browser.h"
geBrowser::geBrowser(int x, int y, int w, int h)
: Fl_File_Browser(x, y, w, h),
- showHiddenFiles(false)
+ m_showHiddenFiles(false)
{
box(G_CUSTOM_BORDER_BOX);
textsize(G_GUI_FONT_SIZE_BASE);
void geBrowser::toggleHiddenFiles()
{
- showHiddenFiles = !showHiddenFiles;
- loadDir(currentDir);
+ m_showHiddenFiles = !m_showHiddenFiles;
+ loadDir(m_currentDir);
}
/* -------------------------------------------------------------------------- */
-void geBrowser::loadDir(const string &dir)
+void geBrowser::loadDir(const string& dir)
{
- currentDir = dir;
- load(currentDir.c_str());
+ m_currentDir = dir;
+ load(m_currentDir.c_str());
/* Clean up unwanted elements. Hide "../" first, it just screws up things.
Also remove hidden files, if requested. */
for (int i=size(); i>=0; i--) {
if (text(i) == nullptr)
continue;
- if (strcmp(text(i), "../") == 0 || (!showHiddenFiles && strncmp(text(i), ".", 1) == 0))
+ if (strcmp(text(i), "../") == 0 || (!m_showHiddenFiles && strncmp(text(i), ".", 1) == 0))
remove(i);
}
}
select(value() - 1);
else
if (Fl::event_key(FL_Enter))
- ((gdBrowserBase*) parent())->fireCallback();
+ static_cast<gdBrowserBase*>(parent())->fireCallback();
ret = 1;
break;
case FL_PUSH: // mouse
if (Fl::event_clicks() > 0) // double click
- ((gdBrowserBase*) parent())->fireCallback();
+ static_cast<gdBrowserBase*>(parent())->fireCallback();
ret = 1;
break;
case FL_RELEASE: // mouse
string geBrowser::getCurrentDir()
{
- return normalize(gu_getRealPath(currentDir));
+ return normalize(gu_getRealPath(m_currentDir));
}
return normalize(text(value()));
else
if (value() == 0) // no rows selected? return current directory
- return normalize(currentDir);
- else
- return normalize(gu_getRealPath(currentDir + G_SLASH + normalize(text(value()))));
+ return normalize(m_currentDir);
+ else {
+#ifdef G_OS_WINDOWS
+ string sep = m_currentDir != "" ? G_SLASH_STR : "";
+#else
+ string sep = G_SLASH_STR;
+#endif
+ return normalize(gu_getRealPath(m_currentDir + sep + normalize(text(value()))));
+ }
}
/* -------------------------------------------------------------------------- */
-string geBrowser::normalize(const string &s)
+string geBrowser::normalize(const string& s)
{
string out = s;
- /* If string ends with G_SLASH, remove it. Don't do it if has length > 1, it
- means that the string is just '/'. Note: our crappy version of Clang doesn't
- seem to support std::string::back() */
-
-#ifdef __APPLE__
- if (out[out.length() - 1] == G_SLASH && out.length() > 1)
-#else
- if (out.back() == G_SLASH && out.length() > 1)
-#endif
+ /* If 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 && !gu_isRootDir(s))
out = out.substr(0, out.size()-1);
return out;
}
{
private:
- std::string currentDir;
- bool showHiddenFiles;
+ std::string m_currentDir;
+ bool m_showHiddenFiles;
/* normalize
- * Make sure the std::string never ends with a trailing slash. */
+ Makes sure the std::string never ends with a trailing slash. */
std::string normalize(const std::string &s);
void toggleHiddenFiles();
/* init
- * Initialize browser and show 'dir' as initial directory. */
+ Initializes browser and show 'dir' as initial directory. */
void loadDir(const std::string &dir);
/* getSelectedItem
- * Return the full path or just the displayed name of the i-th selected item.
- * Always with the trailing slash! */
+ Returns the full path or just the displayed name of the i-th selected item.
+ Always with the trailing slash! */
std::string getSelectedItem(bool fullPath=true);
new geBox(x(), rsmpQuality->y()+rsmpQuality->h()+8, w(), 92,
"Restart Giada for the changes to take effect.");
end();
+
labelsize(G_GUI_FONT_SIZE_BASE);
+ selection_color(G_COLOR_GREY_4);
soundsys->add("(none)");
end();
labelsize(G_GUI_FONT_SIZE_BASE);
+ selection_color(G_COLOR_GREY_4);
conf::recsStopOnChanHalt == 1 ? recsStopOnChanHalt_1->value(1) : recsStopOnChanHalt_0->value(1);
conf::chansStopOnSeqHalt == 1 ? chansStopOnSeqHalt_1->value(1) : chansStopOnSeqHalt_0->value(1);
end();
labelsize(G_GUI_FONT_SIZE_BASE);
+ selection_color(G_COLOR_GREY_4);
system->callback(cb_changeSystem, (void*)this);
debugMsg->add("To file");
labelsize(G_GUI_FONT_SIZE_BASE);
+ selection_color(G_COLOR_GREY_4);
switch (conf::logMode) {
case LOG_MODE_MUTE:
end();
labelsize(G_GUI_FONT_SIZE_BASE);
+ selection_color(G_COLOR_GREY_4);
m_info->label("Scan in progress. Please wait...");
m_info->hide();
extern gdMainWindow* G_MainWin;
-using namespace giada::m;
+using namespace giada;
geChannel::geChannel(int X, int Y, int W, int H, int type, Channel* ch)
void geChannel::cb_arm()
{
- glue_toggleArm(ch, true);
+ c::channel::toggleArm(ch, true);
}
void geChannel::cb_mute()
{
- glue_toggleMute(ch);
+ c::channel::toggleMute(ch);
}
void geChannel::cb_solo()
{
- solo->value() ? glue_setSoloOn(ch) : glue_setSoloOff(ch);
+ solo->value() ? c::channel::setSoloOn(ch) : c::channel::setSoloOff(ch);
}
void geChannel::cb_changeVol()
{
- glue_setVolume(ch, vol->value());
+ c::channel::setVolume(ch, vol->value());
}
#ifdef WITH_VST
void geChannel::cb_openFxWindow()
{
- gu_openSubWindow(G_MainWin, new gdPluginList(pluginHost::CHANNEL, ch), WID_FX_LIST);
+ gu_openSubWindow(G_MainWin, new gdPluginList(m::pluginHost::CHANNEL, ch), WID_FX_LIST);
}
#endif
using std::vector;
using std::string;
+using namespace giada;
geColumn::geColumn(int X, int Y, int W, int H, int index, geKeyboard* parent)
int result = 0;
for (string& path : paths) {
gu_log("[geColumn::handle] loading %s...\n", path.c_str());
- SampleChannel* c = static_cast<SampleChannel*>(glue_addChannel(
+ SampleChannel* c = static_cast<SampleChannel*>(c::channel::addChannel(
m_index, CHANNEL_SAMPLE, G_GUI_CHANNEL_H_1));
- result = glue_loadChannel(c, gu_stripFileUrl(path));
+ result = c::channel::loadChannel(c, gu_stripFileUrl(path));
if (result != G_RES_OK) {
deleteChannel(c->guiChannel);
fails = true;
gu_log("[geColumn::__cb_addChannel] m_index = %d\n", m_index);
int type = openTypeMenu();
if (type)
- glue_addChannel(m_index, type, G_GUI_CHANNEL_H_1);
+ c::channel::addChannel(m_index, type, G_GUI_CHANNEL_H_1);
}
int geKeyboard::handle(int e)
{
+ using namespace giada::c;
+
int ret = Fl_Group::handle(e); // assume the buttons won't handle the Keyboard events
switch (e) {
case FL_FOCUS:
}
else if (Fl::event_key() == FL_End && !endPressed) {
endPressed = true;
- glue_startStopInputRec(false); // not from GUI
+ io::startStopInputRec(false); // not from GUI
ret = 1;
break;
}
else if (Fl::event_key() == FL_Enter && !enterPressed) {
enterPressed = true;
- glue_startStopActionRec(false); // not from GUI
+ io::startStopActionRec(false); // not from GUI
ret = 1;
break;
}
using std::string;
-using namespace giada;
namespace
void menuCallback(Fl_Widget* w, void* v)
{
+ using namespace giada;
+
geMidiChannel* gch = static_cast<geMidiChannel*>(w);
Menu selectedItem = (Menu) (intptr_t) v;
static_cast<geColumn*>(gch->parent())->repositionChannels();
break;
case Menu::CLONE_CHANNEL:
- glue_cloneChannel(gch->ch);
+ c::channel::cloneChannel(gch->ch);
break;
case Menu::RENAME_CHANNEL:
gu_openSubWindow(G_MainWin, new gdChannelNameInput(gch->ch), WID_SAMPLE_NAME);
break;
case Menu::DELETE_CHANNEL:
- glue_deleteChannel(gch->ch);
+ c::channel::deleteChannel(gch->ch);
break;
}
}
void geMidiChannel::cb_button()
{
+ using namespace giada;
+
if (button->value())
- glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
+ c::io::keyPress(static_cast<MidiChannel*>(ch), Fl::event_ctrl(), Fl::event_shift());
}
mainButton->label(label.c_str());
- vol->value(mch->volume);
+ vol->value(mch->getVolume());
mute->value(mch->mute);
solo->value(mch->solo);
extern gdMainWindow* G_MainWin;
-using namespace giada;
-
-
namespace
{
enum class Menu
void menuCallback(Fl_Widget* w, void* v)
{
+ using namespace giada;
+
geSampleChannel* gch = static_cast<geSampleChannel*>(w);
Menu selectedItem = (Menu) (intptr_t) v;
switch (selectedItem) {
case Menu::INPUT_MONITOR: {
- glue_toggleInputMonitor(gch->ch);
+ c::channel::toggleInputMonitor(gch->ch);
break;
}
case Menu::LOAD_SAMPLE: {
break;
}
case Menu::CLONE_CHANNEL: {
- glue_cloneChannel(gch->ch);
+ c::channel::cloneChannel(gch->ch);
break;
}
case Menu::RENAME_CHANNEL: {
break;
}
case Menu::FREE_CHANNEL: {
- glue_freeChannel(gch->ch);
+ c::channel::freeChannel(gch->ch);
break;
}
case Menu::DELETE_CHANNEL: {
- glue_deleteChannel(gch->ch);
+ c::channel::deleteChannel(gch->ch);
break;
}
}
/* -------------------------------------------------------------------------- */
-void geSampleChannel::cb_button (Fl_Widget* v, void* p) { ((geSampleChannel*)p)->__cb_button(); }
-void geSampleChannel::cb_openMenu (Fl_Widget* v, void* p) { ((geSampleChannel*)p)->__cb_openMenu(); }
-void geSampleChannel::cb_readActions (Fl_Widget* v, void* p) { ((geSampleChannel*)p)->__cb_readActions(); }
+void geSampleChannel::cb_button (Fl_Widget* v, void* p) { ((geSampleChannel*)p)->cb_button(); }
+void geSampleChannel::cb_openMenu (Fl_Widget* v, void* p) { ((geSampleChannel*)p)->cb_openMenu(); }
+void geSampleChannel::cb_readActions (Fl_Widget* v, void* p) { ((geSampleChannel*)p)->cb_readActions(); }
/* -------------------------------------------------------------------------- */
-void geSampleChannel::__cb_button()
+void geSampleChannel::cb_button()
{
- if (button->value()) // pushed
- glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
+ using namespace giada;
+
+ if (button->value()) // pushed, max velocity (127 i.e. 0x7f)
+ c::io::keyPress(ch, Fl::event_ctrl(), Fl::event_shift(), 0x7F);
else // released
- glue_keyRelease(ch, Fl::event_ctrl(), Fl::event_shift());
+ c::io::keyRelease(ch, Fl::event_ctrl(), Fl::event_shift());
}
/* -------------------------------------------------------------------------- */
-void geSampleChannel::__cb_openMenu()
+void geSampleChannel::cb_openMenu()
{
+ using namespace giada;
+
/* If you're recording (input or actions) no menu is allowed; you can't do
anything, especially deallocate the channel */
/* -------------------------------------------------------------------------- */
-void geSampleChannel::__cb_readActions()
+void geSampleChannel::cb_readActions()
{
- glue_toggleReadingRecs(static_cast<SampleChannel*>(ch));
+ using namespace giada::c::channel;
+ toggleReadingRecs(static_cast<SampleChannel*>(ch));
}
void geSampleChannel::refresh()
{
+ using namespace giada;
+
if (!mainButton->visible()) // mainButton invisible? status too (see below)
return;
modeBox->value(sch->mode);
modeBox->redraw();
- vol->value(sch->volume);
+ vol->value(sch->getVolume());
mute->value(sch->mute);
solo->value(sch->solo);
{
private:
- static void cb_button (Fl_Widget* v, void* p);
- static void cb_openMenu (Fl_Widget* v, void* p);
+ static void cb_button(Fl_Widget* v, void* p);
+ static void cb_openMenu(Fl_Widget* v, void* p);
static void cb_readActions(Fl_Widget* v, void* p);
- void __cb_button ();
- void __cb_openMenu ();
- void __cb_readActions();
+ void cb_button();
+ void cb_openMenu();
+ void cb_readActions();
public:
extern gdMainWindow* G_MainWin;
+using namespace giada;
+
+
geSampleChannelButton::geSampleChannelButton(int x, int y, int w, int h,
const char* l)
: geChannelButton(x, y, w, h, l)
case FL_PASTE: {
geSampleChannel* gch = static_cast<geSampleChannel*>(parent());
SampleChannel* ch = static_cast<SampleChannel*>(gch->ch);
- int result = glue_loadChannel(ch, gu_trim(gu_stripFileUrl(Fl::event_text())));
+ int result = c::channel::loadChannel(ch, gu_trim(gu_stripFileUrl(Fl::event_text())));
if (result != G_RES_OK)
G_MainWin->keyboard->printChannelMessage(result);
ret = 1;
void geMainTransport::__cb_recAction()
{
- glue_startStopActionRec(true);
+ using namespace giada::c::io;
+ startStopActionRec(true);
}
void geMainTransport::__cb_recInput()
{
- glue_startStopInputRec(true);
+ using namespace giada::c::io;
+ startStopInputRec(true);
}
#include "boostTool.h"
-using namespace giada::m;
-
-
-geBoostTool::geBoostTool(int X, int Y, SampleChannel *ch)
+geBoostTool::geBoostTool(int X, int Y, SampleChannel* ch)
: Fl_Group(X, Y, 220, 20),
ch (ch)
{
void geBoostTool::refresh()
{
- input->value(gu_fToString(gu_linearToDB(ch->getBoost()), 2).c_str()); // 2 digits
+ using namespace giada::u;
+
+ input->value(gu_fToString(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 (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()
+void geBoostTool::cb_setBoost()
{
+ using namespace giada::c;
+
if (Fl::event() == FL_DRAG)
- glue_setBoost(ch, dial->value());
+ channel::setBoost(ch, dial->value());
else
if (Fl::event() == FL_RELEASE) {
- glue_setBoost(ch, dial->value());
+ channel::setBoost(ch, dial->value());
static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform();
}
}
/* -------------------------------------------------------------------------- */
-void geBoostTool::__cb_setBoostNum()
+void geBoostTool::cb_setBoostNum()
{
- glue_setBoost(ch, gu_dBtoLinear(atof(input->value())));
+ using namespace giada;
+
+ c::channel::setBoost(ch, u::math::dBtoLinear(atof(input->value())));
static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform();
}
/* -------------------------------------------------------------------------- */
-void geBoostTool::__cb_normalize()
+void geBoostTool::cb_normalize()
{
- float val = wfx::normalizeSoft(ch->wave);
- glue_setBoost(ch, val); // it's like a fake user moving the dial
+ using namespace giada;
+
+ float val = m::wfx::normalizeSoft(ch->wave);
+ c::channel::setBoost(ch, val); // it's like a fake user moving the dial
static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform();
}
{
private:
- SampleChannel *ch;
+ SampleChannel* ch;
- geBox *label;
- geDial *dial;
- geInput *input;
- geButton *normalize;
+ geBox* label;
+ geDial* dial;
+ geInput* input;
+ geButton* normalize;
- 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);
- inline void __cb_setBoost ();
- inline void __cb_setBoostNum();
- inline void __cb_normalize ();
+ 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);
+ inline void cb_setBoost();
+ inline void cb_setBoostNum();
+ inline void cb_normalize();
public:
- geBoostTool(int x, int y, SampleChannel *ch);
+ geBoostTool(int x, int y, SampleChannel* ch);
void refresh();
};
using std::string;
+using namespace giada;
gePanTool::gePanTool(int x, int y, SampleChannel *ch)
void gePanTool::__cb_panning()
{
- glue_setPanning(ch, dial->value());
+ c::channel::setPanning(ch, dial->value());
}
void gePanTool::__cb_panReset()
{
- glue_setPanning(ch, 0.5f);
+ c::channel::setPanning(ch, 0.5f);
}
\ No newline at end of file
#include "pitchTool.h"
-using namespace giada::m;
+using namespace giada;
gePitchTool::gePitchTool(int x, int y, SampleChannel* ch)
void gePitchTool::__cb_setPitch()
{
- glue_setPitch(ch, dial->value());
+ c::channel::setPitch(ch, dial->value());
}
void gePitchTool::__cb_setPitchNum()
{
- glue_setPitch(ch, atof(input->value()));
+ c::channel::setPitch(ch, atof(input->value()));
}
void gePitchTool::__cb_setPitchHalf()
{
- glue_setPitch(ch, dial->value()/2);
+ c::channel::setPitch(ch, dial->value()/2);
}
void gePitchTool::__cb_setPitchDouble()
{
- glue_setPitch(ch, dial->value()*2);
+ c::channel::setPitch(ch, dial->value()*2);
}
void gePitchTool::__cb_setPitchToBar()
{
// TODO - opaque channel's count
- glue_setPitch(ch, (ch->getEnd()*2) / (float) clock::getFramesPerBar());
+ c::channel::setPitch(ch, (ch->getEnd()*2) / (float) m::clock::getFramesPerBar());
}
void gePitchTool::__cb_setPitchToSong()
{
// TODO - opaque channel's count
- glue_setPitch(ch, (ch->getEnd()*2) / (float) clock::getTotalFrames());
+ c::channel::setPitch(ch, (ch->getEnd()*2) / (float) m::clock::getTotalFrames());
}
void gePitchTool::__cb_resetPitch()
{
- glue_setPitch(ch, G_DEFAULT_PITCH);
+ c::channel::setPitch(ch, G_DEFAULT_PITCH);
}
using std::string;
-geVolumeTool::geVolumeTool(int X, int Y, SampleChannel *ch)
+geVolumeTool::geVolumeTool(int X, int Y, SampleChannel* ch)
: Fl_Group(X, Y, 150, 20),
ch (ch)
{
void geVolumeTool::refresh()
{
+ using namespace giada::u;
+
string tmp;
- float dB = gu_linearToDB(ch->volume);
+ float dB = math::linearToDB(ch->getVolume());
if (dB > -INFINITY) tmp = gu_fToString(dB, 2); // 2 digits
else tmp = "-inf";
input->value(tmp.c_str());
/* -------------------------------------------------------------------------- */
-void geVolumeTool::cb_setVolume (Fl_Widget *w, void *p) { ((geVolumeTool*)p)->__cb_setVolume(); }
-void geVolumeTool::cb_setVolumeNum(Fl_Widget *w, void *p) { ((geVolumeTool*)p)->__cb_setVolumeNum(); }
+void geVolumeTool::cb_setVolume (Fl_Widget* w, void* p) { ((geVolumeTool*)p)->__cb_setVolume(); }
+void geVolumeTool::cb_setVolumeNum(Fl_Widget* w, void* p) { ((geVolumeTool*)p)->__cb_setVolumeNum(); }
/* -------------------------------------------------------------------------- */
void geVolumeTool::__cb_setVolume()
{
- glue_setVolume(ch, dial->value(), false, true);
+ using namespace giada;
+
+ c::channel::setVolume(ch, dial->value(), false, true);
refresh();
}
void geVolumeTool::__cb_setVolumeNum()
{
+ using namespace giada;
+
float value = pow(10, (atof(input->value()) / 20)); // linear = 10^(dB/20)
- glue_setVolume(ch, value, false, true);
+ c::channel::setVolume(ch, value, false, true);
dial->value(ch->guiChannel->vol->value());
}
#include "core/kernelMidi.h"
#include "core/recorder.h"
#include "utils/gui.h"
+#include "utils/time.h"
#include "gui/dialogs/gd_mainWindow.h"
#include "core/pluginHost.h"
pthread_t G_videoThread;
bool G_quit;
-gdMainWindow *G_MainWin;
+gdMainWindow* G_MainWin;
-void *videoThreadCb(void *arg);
+void* videoThreadCb(void* arg);
-int main(int argc, char **argv)
+int main(int argc, char** argv)
{
G_quit = false;
}
-void *videoThreadCb(void *arg)
+void* videoThreadCb(void* arg)
{
- if (giada::m::kernelAudio::getStatus())
+ using namespace giada;
+
+ if (m::kernelAudio::getStatus())
while (!G_quit) {
gu_refreshUI();
-#ifdef _WIN32
- Sleep(G_GUI_SLEEP);
-#else
- usleep(G_GUI_SLEEP);
-#endif
+ u::time::sleep(G_GUI_REFRESH_RATE);
}
pthread_exit(nullptr);
return 0;
/* -------------------------------------------------------------------------- */
-string gu_basename(const string &s)
+string gu_basename(const string& s)
{
string out = s;
out.erase(0, out.find_last_of(G_SLASH_STR) + 1);
/* -------------------------------------------------------------------------- */
-string gu_dirname(const string &path)
+string gu_dirname(const string& path)
{
if (path.empty())
return "";
/* -------------------------------------------------------------------------- */
-string gu_getExt(const string &file)
+string gu_getExt(const string& file)
{
// TODO - use std functions
int len = strlen(file.c_str());
/* -------------------------------------------------------------------------- */
-string gu_stripExt(const string &s)
+string gu_stripExt(const string& s)
{
return s.substr(0, s.find_last_of("."));
}
/* -------------------------------------------------------------------------- */
-bool gu_isProject(const string &path)
+bool gu_isProject(const string& path)
{
/** FIXME - checks too weak */
/* -------------------------------------------------------------------------- */
-string gu_stripFileUrl(const string &f)
+string gu_stripFileUrl(const string& f)
{
string out = f;
out = gu_replace(out, "file://", "");
#elif defined(__APPLE__)
- struct passwd *p = getpwuid(getuid());
+ struct passwd* p = getpwuid(getuid());
if (p == nullptr) {
gu_log("[gu_getHomePath] unable to fetch user infos\n");
return "";
}
else {
- const char *home = p->pw_dir;
+ const char* home = p->pw_dir;
snprintf(path, PATH_MAX, "%s/Library/Application Support/Giada", home);
}
return string(path);
}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+bool gu_isRootDir(const std::string& s)
+{
+ if (s == "")
+ return false;
+
+#ifdef G_OS_WINDOWS
+
+ return s.length() <= 3 && s[1] == ':'; /* X: or X:\ */
+
+#else
+
+ return s == G_SLASH_STR;
+
+#endif
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+std::string gu_getUpDir(const std::string& s)
+{
+#ifdef G_OS_WINDOWS
+
+ /* If root, let the user browse the drives list by returning "". */
+ if (gu_isRootDir(s))
+ return "";
+
+#endif
+
+ return s.substr(0, s.find_last_of(G_SLASH_STR)) + G_SLASH_STR;
+}
\ No newline at end of file
bool gu_fileExists(const std::string& path);
bool gu_dirExists(const std::string& path);
bool gu_isDir(const std::string& path);
+
+/* isRootDir
+Tells whether 's' is '/' on Unix or '[X]:\' on Windows. */
+
+bool gu_isRootDir(const std::string& s);
+
bool gu_isProject(const std::string& path);
bool gu_mkdir(const std::string& path);
std::string gu_getCurrentPath();
std::string gu_stripFileUrl(const std::string& s);
+/* gu_getUpDir
+Returns the upper directory:
+/path/to/my/directory -> /path/to/my/ */
+
+std::string gu_getUpDir(const std::string& s);
+
#endif
#include "math.h"
-float gu_linearToDB(float f)
+namespace giada {
+namespace u {
+namespace math
{
- return 20 * std::log10(f);
+float linearToDB(float f)
+{
+ return 20 * std::log10(f);
}
/* -------------------------------------------------------------------------- */
-float gu_dBtoLinear(float f)
+float dBtoLinear(float f)
{
- return std::pow(10, f/20.0f);
+ return std::pow(10, f/20.0f);
}
+
+}}} // giada::u::math::
\ No newline at end of file
#define G_UTILS_MATH_H
-float gu_linearToDB(float f);
+namespace giada {
+namespace u {
+namespace math
+{
+float linearToDB(float f);
+float dBtoLinear(float f);
-float gu_dBtoLinear(float f);
+/* map (template)
+Maps 'x' in range [a, b] to a new range [w, z]. Source:
+ https://en.wikipedia.org/wiki/Linear_equation#Two-point_form*/
+
+template <typename T>
+T map(T x, T a, T b, T w, T z)
+{
+ return (((x - a) / (b - a)) * (z - w)) + w;
+}
+
+}}} // giada::u::math::
#endif
/* Compute the size of the new expanded string (i.e. with replacement taken
into account). */
- size_t size = vsnprintf(nullptr, 0, format, args);
-
+ va_start(args, format);
+ size_t size = vsnprintf(nullptr, 0, format, args) + 1;
+ va_end(args);
+
/* Create a new temporary char array to hold the new expanded string. */
std::unique_ptr<char[]> tmp(new char[size]);
* -------------------------------------------------------------------------- */
-#include "../core/const.h"
-#ifndef G_OS_MAC
- #include <chrono>
- #include <thread>
-#else
- #include <unistd.h>
-#endif
+#include <chrono>
+#include <thread>
#include "time.h"
{
void sleep(int millisecs)
{
-#ifndef G_OS_MAC
std::this_thread::sleep_for(std::chrono::milliseconds(millisecs));
-#else
- usleep(millisecs * 1000);
-#endif
}
}}}; // giada::u::time::
#include "../src/core/const.h"
#include "../src/core/conf.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;
#define CATCH_CONFIG_MAIN
#define CATCH_CONFIG_FAST_COMPILE
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
#include "../src/core/const.h"
#include "../src/core/midiMapConf.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;
#include "../src/core/patch.h"
#include "../src/core/const.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;
#if 0
#include "../src/core/pluginHost.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
TEST_CASE("Test PluginHost class")
#include "../src/core/recorder.h"
#include "../src/core/const.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;
#include "../src/utils/fs.h"
#include "../src/utils/string.h"
-#include "catch/single_include/catch.hpp"
-
-
-using std::vector;
+#include "../src/utils/math.h"
+#include <catch.hpp>
TEST_CASE("Test filesystem utils")
{
- REQUIRE(gu_fileExists("giada_tests") == true);
- REQUIRE(gu_fileExists("ghost_file") == false);
- REQUIRE(gu_dirExists("src/") == true);
- REQUIRE(gu_dirExists("ghost_dir/") == false);
- REQUIRE(gu_isDir("src/") == true);
- REQUIRE(gu_isDir("giada_tests") == false);
- REQUIRE(gu_basename("tests/utils.cpp") == "utils.cpp");
- REQUIRE(gu_dirname("tests/utils.cpp") == "tests");
- REQUIRE(gu_getExt("tests/utils.cpp") == "cpp");
- REQUIRE(gu_stripExt("tests/utils.cpp") == "tests/utils");
+ REQUIRE(gu_fileExists("README.md") == true);
+ REQUIRE(gu_fileExists("ghost_file") == false);
+ REQUIRE(gu_dirExists("src/") == true);
+ REQUIRE(gu_dirExists("ghost_dir/") == false);
+ REQUIRE(gu_isDir("src/") == true);
+ REQUIRE(gu_isDir("giada_tests") == false);
+ REQUIRE(gu_basename("tests/utils.cpp") == "utils.cpp");
+ REQUIRE(gu_dirname("tests/utils.cpp") == "tests");
+ REQUIRE(gu_getExt("tests/utils.cpp") == "cpp");
+ REQUIRE(gu_stripExt("tests/utils.cpp") == "tests/utils");
+#if defined(_WIN32)
+ REQUIRE(gu_isRootDir("C:\\") == true);
+ REQUIRE(gu_isRootDir("C:\\path\\to\\something") == false);
+ REQUIRE(gu_getUpDir("C:\\path\\to\\something") == "C:\\path\\to\\");
+ REQUIRE(gu_getUpDir("C:\\path") == "C:\\");
+ REQUIRE(gu_getUpDir("C:\\") == "");
+#else
+ REQUIRE(gu_isRootDir("/") == true);
+ REQUIRE(gu_isRootDir("/path/to/something") == false);
+ REQUIRE(gu_getUpDir("/path/to/something") == "/path/to/");
+ REQUIRE(gu_getUpDir("/path") == "/");
+ REQUIRE(gu_getUpDir("/") == "/");
+#endif
}
TEST_CASE("Test string utils")
{
- REQUIRE(gu_replace("Giada is cool", "cool", "hot") == "Giada is hot");
- REQUIRE(gu_trim(" Giada is cool ") == "Giada is cool");
- REQUIRE(gu_iToString(666) == "666");
- REQUIRE(gu_iToString(0x99AABB, true) == "99AABB");
- REQUIRE(gu_fToString(3.14159, 2) == "3.14");
- // Catch can't handle this so far?
- //REQUIRE(gu_format("I see %d men with %s hats", 5, "strange") == "I see 5 men with strange hats");
-
- vector<std::string> v;
- gu_split("Giada is cool", " ", &v);
- REQUIRE(v.size() == 3);
- REQUIRE(v.at(0) == "Giada");
- REQUIRE(v.at(1) == "is");
- REQUIRE(v.at(2) == "cool");
+ using std::vector;
+
+ REQUIRE(gu_replace("Giada is cool", "cool", "hot") == "Giada is hot");
+ REQUIRE(gu_trim(" Giada is cool ") == "Giada is cool");
+ REQUIRE(gu_iToString(666) == "666");
+ REQUIRE(gu_iToString(0x99AABB, true) == "99AABB");
+ REQUIRE(gu_fToString(3.14159, 2) == "3.14");
+ REQUIRE(gu_format("I see %d men with %s hats", 5, "strange") == "I see 5 men with strange hats");
+
+ vector<std::string> v;
+ gu_split("Giada is cool", " ", &v);
+ REQUIRE(v.size() == 3);
+ REQUIRE(v.at(0) == "Giada");
+ REQUIRE(v.at(1) == "is");
+ REQUIRE(v.at(2) == "cool");
}
+
+
+TEST_CASE("Test math utils")
+{
+ using namespace giada::u::math;
+
+ REQUIRE(map( 0.0f, 0.0f, 30.0f, 0.0f, 1.0f) == 0.0f);
+ REQUIRE(map(30.0f, 0.0f, 30.0f, 0.0f, 1.0f) == 1.0f);
+ REQUIRE(map(15.0f, 0.0f, 30.0f, 0.0f, 1.0f) == Approx(0.5f));
+}
\ No newline at end of file
#include <memory>
#include "../src/core/wave.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;
#include "../src/core/const.h"
#include "../src/core/wave.h"
#include "../src/core/waveFx.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;
#include "../src/core/waveManager.h"
#include "../src/core/wave.h"
#include "../src/core/const.h"
-#include "catch/single_include/catch.hpp"
+#include <catch.hpp>
using std::string;