on_failure: always
before_install:
+ - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y # for gcc 6
- sudo apt-get update -qq
- - sudo apt-get install -y libsndfile1-dev libsamplerate0-dev libfltk1.3-dev libasound2-dev libxpm-dev libpulse-dev libjack-dev libxrandr-dev libx11-dev libxinerama-dev libxcursor-dev
+ - sudo apt-get install -y gcc-6 g++-6 libsndfile1-dev libsamplerate0-dev libfltk1.3-dev libasound2-dev libxpm-dev libpulse-dev libjack-dev libxrandr-dev libx11-dev libxinerama-dev libxcursor-dev
before_script:
+ - sudo ln -f -s /usr/bin/g++-6 /usr/bin/g++
# Download and build latest version of RtMidi
- sudo ldconfig
- cd ..
- # Download wav file for testing purposes
-
- - wget http://download.wavetlan.com/SVV/Media/HTTP/WAV/Media-Convert/Media-Convert_test3_PCM_Stereo_VBR_16SS_11025Hz.wav -O test.wav
-
# Download midimaps package for testing purposes
- wget https://github.com/monocasual/giada-midimaps/archive/master.zip -O giada-midimaps-master.zip
# Download vst plugin for testing purposes
- - wget 'http://downloads.sourceforge.net/project/distrho/2014-08-26/dexed-linux64bit-fixed.tar.xz?r=http%3A%2F%2Fdistrho.sourceforge.net%2Fports&ts=1454876566&use_mirror=freefr' -O dexed.tar.xz
- - tar xf dexed.tar.xz dexed-linux64bit/Dexed.so
- - cp dexed-linux64bit/Dexed.so .
+ - wget http://www.discodsp.com/download/?id=18 -O bliss-linux.zip
+ - unzip bliss-linux.zip -d bliss-linux
+ - cp bliss-linux/64-bit/Bliss64Demo.so .
# Build Giada. Note the CFLAGS: optimization levels are set to O1 in order
# not to throw up nasty errors from JUCE modules.
--------------------------------------------------------------------------------
+0.13.0 ---
+- Deep file browser refactoring
+- Save browser's scroll position and last item selected on opening
+- Load patches/projects/samples on double click
+- 64 bit builds for Windows
+- Prevent deprecated patch from crashing if a plugin is not found in the stack
+- Force logger to flush to file on Windows
+- Add more default values for windows' dimensions and positions
+- Avoid crashes on Configuration panel if no midimaps were selected
+- Fix missing keyRelease actions in action editor
+- Update JUCE to version 4.2.3
+- Don't include JUCE on tests without VST support (GitHub #75)
+- Fix compilation errors on GCC 6 (GitHub #82)
+- Fix wrong channel's actions count that prevented "R" button to be toggled
+ properly
+- Fixed a bug that prevented actions on frame 0 to being properly reproduced
+
+
0.12.2 --- 2016 . 06 . 02
- Update RtAudio to version 4.1.2
- Add WASAPI support on Windows
src/utils/gui_utils.cpp \
src/utils/gvector.h \
src/utils/utils.h \
-src/utils/utils.cpp
+src/utils/utils.cpp \
+src/utils/string.h \
+src/utils/string.cpp
if WITH_VST
giada_SOURCES += \
#
if WITH_VST
-giada_CPPFLAGS += -I./src/deps/juce -I./src/deps/vst -I/usr/include \
- -I/usr/include/freetype2
+giada_CPPFLAGS += \
+ -I./src/deps/juce \
+ -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
+giada_CXXFLAGS += -Wno-error=misleading-indentation
endif
if LINUX
giada_LDADD = -lrtaudio -ldsound -lwsock32 -lm -lfltk -lwininet -lgdi32 \
-lshell32 -lvfw32 -lrpcrt4 -luuid -lcomctl32 -lole32 -lws2_32 -lsndfile \
-lsamplerate -lrtmidi -lwinmm -lsetupapi -lksuser -lpthreadGC2 -ljansson \
- -limm32 -lglu32 -lshell32 -lversion -lopengl32 -loleaut32 -lshlwapi
+ -limm32 -lglu32 -lshell32 -lversion -lopengl32 -loleaut32 -lshlwapi -lcomdlg32
giada_LDFLAGS = -mwindows -static
giada_SOURCES += resource.rc
endif
src/core/dataStorageIni.cpp \
src/core/dataStorageJson.cpp \
src/utils/utils.cpp \
-src/utils/log.cpp \
+src/utils/log.cpp
+
+if WITH_VST
+giada_tests_SOURCES += \
src/deps/juce/juce_audio_basics/juce_audio_basics.cpp \
src/deps/juce/juce_audio_processors/juce_audio_processors.cpp \
src/deps/juce/juce_core/juce_core.cpp \
src/deps/juce/juce_graphics/juce_graphics.cpp \
src/deps/juce/juce_gui_basics/juce_gui_basics.cpp \
src/deps/juce/juce_gui_extra/juce_gui_extra.cpp
+endif
giada_tests_LDADD = -ljansson -lsndfile -lsamplerate -lfltk -lXext -lX11 -lXft \
-lXpm -lm -ljack -lasound -lpthread -ldl -lpulse-simple -lpulse -lrtmidi \
giada_tests_CXXFLAGS = -std=c++11
-giada_tests_CPPFLAGS = -I./src/deps/juce -I./src/deps/vst -I/usr/include \
- -I/usr/include/freetype2
+if WITH_VST
+giada_tests_CPPFLAGS = \
+ -I./src/deps/juce \
+ -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
+endif
# make rename ------------------------------------------------------------------
# prereq & init
AC_PREREQ(2.60)
-AC_INIT([giada], [0.12], [giadaloopmachine@gmail.com])
+AC_INIT([giada], [0.13], [giadaloopmachine@gmail.com])
AC_CONFIG_SRCDIR([src/main.cpp])
AM_INIT_AUTOMAKE([subdir-objects])
# test if files needed for Travis CI are present. If so, define a new macro
# RUN_TESTS_WITH_LOCAL_FILES used during the test suite
-if test -f "./test.wav" && test -f "giada-midimaps-master.zip" && test -f "dexed.tar.xz" ; then
+if test -f "giada-midimaps-master.zip" && test -f "dexed.tar.xz" ; then
AC_DEFINE(RUN_TESTS_WITH_LOCAL_FILES)
fi
#include "recorder.h"
#ifdef WITH_VST
-// TODO - can we move this stuff to a separate file?
-#include "../deps/juce/juce_audio_basics/juce_audio_basics.h"
-#include "../deps/juce/juce_audio_processors/juce_audio_processors.h"
-#include "../deps/juce/juce_core/juce_core.h"
-#include "../deps/juce/juce_data_structures/juce_data_structures.h"
-#include "../deps/juce/juce_events/juce_events.h"
-#include "../deps/juce/juce_graphics/juce_graphics.h"
-#include "../deps/juce/juce_gui_basics/juce_gui_basics.h"
-#include "../deps/juce/juce_gui_extra/juce_gui_extra.h"
+ #include "../deps/juce/config.h"
#endif
using std::vector;
#if defined(__linux__) || defined(__APPLE__)
- confFilePath = gGetHomePath() + gGetSlash() + CONF_FILENAME;
- confDirPath = gGetHomePath() + gGetSlash();
+ confFilePath = gGetHomePath() + G_SLASH + CONF_FILENAME;
+ confDirPath = gGetHomePath() + G_SLASH;
#elif defined(_WIN32)
limitOutput = false;
rsmpQuality = 0;
- midiPortIn = DEFAULT_MIDI_PORT_IN;
- noNoteOff = false;
- midiMapPath = "";
- midiPortOut = DEFAULT_MIDI_PORT_OUT;
- midiSync = MIDI_SYNC_NONE;
- midiTCfps = 25.0f;
+ midiPortIn = DEFAULT_MIDI_PORT_IN;
+ noNoteOff = false;
+ midiMapPath = "";
+ midiPortOut = DEFAULT_MIDI_PORT_OUT;
+ midiSync = MIDI_SYNC_NONE;
+ midiTCfps = 25.0f;
midiInRewind = 0x0;
midiInStartStop = 0x0;
resizeRecordings = true;
- actionEditorZoom = 100;
- actionEditorGridOn = false;
- actionEditorGridVal = 1;
-
mainWindowX = 0;
mainWindowY = 0;
mainWindowW = GUI_WIDTH;
mainWindowH = GUI_HEIGHT;
+ browserX = 0;
+ browserY = 0;
+ browserW = 640;
+ browserH = 480;
+ browserPosition = 0;
+ browserLastValue = 0;
+
+ actionEditorX = 0;
+ actionEditorY = 0;
+ actionEditorW = 640;
+ actionEditorH = 480;
+ actionEditorZoom = 100;
+ actionEditorGridOn = false;
+ actionEditorGridVal = 1;
+
+ sampleEditorX = 0;
+ sampleEditorY = 0;
+ sampleEditorW = 640;
+ sampleEditorH = 480;
+
pianoRollY = -1;
pianoRollH = 422;
#ifdef WITH_VST
- pluginChooserX = 0;
- pluginChooserY = 0;
- pluginChooserW = 640;
- pluginChooserH = 480;
+ pluginChooserX = 0;
+ pluginChooserY = 0;
+ pluginChooserW = 640;
+ pluginChooserH = 480;
pluginSortMethod = 0;
#endif
if (!setInt(jRoot, CONF_KEY_BROWSER_Y, browserY)) return 0;
if (!setInt(jRoot, CONF_KEY_BROWSER_W, browserW)) return 0;
if (!setInt(jRoot, CONF_KEY_BROWSER_H, browserH)) return 0;
+ if (!setInt(jRoot, CONF_KEY_BROWSER_POSITION, browserPosition)) return 0;
+ if (!setString(jRoot, CONF_KEY_BROWSER_LAST_PATH, browserLastPath)) return 0;
+ if (!setInt(jRoot, CONF_KEY_BROWSER_LAST_VALUE, browserLastValue)) return 0;
if (!setInt(jRoot, CONF_KEY_ACTION_EDITOR_X, actionEditorX)) return 0;
if (!setInt(jRoot, CONF_KEY_ACTION_EDITOR_Y, actionEditorY)) return 0;
if (!setInt(jRoot, CONF_KEY_ACTION_EDITOR_W, actionEditorW)) return 0;
json_object_set_new(jRoot, CONF_KEY_BROWSER_Y, json_integer(browserY));
json_object_set_new(jRoot, CONF_KEY_BROWSER_W, json_integer(browserW));
json_object_set_new(jRoot, CONF_KEY_BROWSER_H, json_integer(browserH));
+ json_object_set_new(jRoot, CONF_KEY_BROWSER_POSITION, json_integer(browserPosition));
+ json_object_set_new(jRoot, CONF_KEY_BROWSER_LAST_PATH, json_string(browserLastPath.c_str()));
+ json_object_set_new(jRoot, CONF_KEY_BROWSER_LAST_VALUE, json_integer(browserLastValue));
json_object_set_new(jRoot, CONF_KEY_ACTION_EDITOR_X, json_integer(actionEditorX));
json_object_set_new(jRoot, CONF_KEY_ACTION_EDITOR_Y, json_integer(actionEditorY));
json_object_set_new(jRoot, CONF_KEY_ACTION_EDITOR_W, json_integer(actionEditorW));
string samplePath;
int mainWindowX, mainWindowY, mainWindowW, mainWindowH;
- int browserX, browserY, browserW, browserH;
+
+ int browserX, browserY, browserW, browserH, browserPosition, browserLastValue;
+ string browserLastPath;
+
int actionEditorX, actionEditorY, actionEditorW, actionEditorH, actionEditorZoom;
int actionEditorGridVal;
int actionEditorGridOn;
+
int sampleEditorX, sampleEditorY, sampleEditorW, sampleEditorH;
int sampleEditorGridVal;
int sampleEditorGridOn;
+
int pianoRollY, pianoRollH;
int pluginListX, pluginListY;
int configX, configY;
/* -- version --------------------------------------------------------------- */
-#define G_VERSION_STR "0.12.2"
+#define G_VERSION_STR "0.13.0"
#define G_APP_NAME "Giada"
#define G_VERSION_MAJOR 0
-#define G_VERSION_MINOR 12
-#define G_VERSION_PATCH 2
+#define G_VERSION_MINOR 13
+#define G_VERSION_PATCH 0
#define CONF_FILENAME "giada.conf"
#ifndef BUILD_DATE
-# define BUILD_DATE __DATE__
+ #define BUILD_DATE __DATE__
+#endif
+
+#ifdef _WIN32
+ #define G_SLASH '\\'
+ #define G_SLASH_STR "\\"
+#else
+ #define G_SLASH '/'
+ #define G_SLASH_STR "/"
#endif
#define CONF_KEY_BROWSER_Y "browser_y"
#define CONF_KEY_BROWSER_W "browser_w"
#define CONF_KEY_BROWSER_H "browser_h"
+#define CONF_KEY_BROWSER_POSITION "browser_position"
+#define CONF_KEY_BROWSER_LAST_PATH "browser_last_path"
+#define CONF_KEY_BROWSER_LAST_VALUE "browser_last_value"
#define CONF_KEY_ACTION_EDITOR_X "action_editor_x"
#define CONF_KEY_ACTION_EDITOR_Y "action_editor_y"
#define CONF_KEY_ACTION_EDITOR_W "action_editor_w"
#ifdef WITH_VST
-// TODO - can we move this stuff to a separate file?
-#include "../deps/juce/juce_audio_basics/juce_audio_basics.h"
-#include "../deps/juce/juce_audio_processors/juce_audio_processors.h"
-#include "../deps/juce/juce_core/juce_core.h"
-#include "../deps/juce/juce_data_structures/juce_data_structures.h"
-#include "../deps/juce/juce_events/juce_events.h"
-#include "../deps/juce/juce_graphics/juce_graphics.h"
-#include "../deps/juce/juce_gui_basics/juce_gui_basics.h"
-#include "../deps/juce/juce_gui_extra/juce_gui_extra.h"
+ #include "../deps/juce/config.h"
#endif
#include "channel.h"
void MidiMapConf::init()
{
- midimapsPath = gGetHomePath() + gGetSlash() + "midimaps" + gGetSlash();
+ midimapsPath = gGetHomePath() + G_SLASH + "midimaps" + G_SLASH;
/* scan dir of midi maps and load the filenames into <>maps. */
int numChans = G_Patch_DEPR_.getNumChans();
for (int i=0; i<numChans; i++) {
Channel *ch = glue_addChannel(G_Patch_DEPR_.getColumn(i), G_Patch_DEPR_.getType(i));
- string samplePath = isProject ? projPath + gGetSlash() + G_Patch_DEPR_.getSamplePath(i) : "";
+ string projectPath = projPath; // safe
+ string samplePath = isProject ? projectPath + G_SLASH + G_Patch_DEPR_.getSamplePath(i) : "";
ch->readPatch_DEPR_(samplePath.c_str(), i, &G_Patch_DEPR_, G_Conf.samplerate,
G_Conf.rsmpQuality);
}
int nparam = atoi(getValue(tmp).c_str());
Plugin *pPlugin = G_PluginHost.getPluginByIndex(j, PluginHost::CHANNEL, ch);
sprintf(tmp, "chan%d_p%dbypass", ch->index, j);
- pPlugin->setBypass(atoi(getValue(tmp).c_str()));
- for (int k=0; k<nparam; k++) {
- sprintf(tmp, "chan%d_p%dparam%dvalue", ch->index, j, k);
- float pval = atof(getValue(tmp).c_str());
- pPlugin->setParameter(k, pval);
+ if (pPlugin) {
+ pPlugin->setBypass(atoi(getValue(tmp).c_str()));
+ for (int k=0; k<nparam; k++) {
+ sprintf(tmp, "chan%d_p%dparam%dvalue", ch->index, j, k);
+ float pval = atof(getValue(tmp).c_str());
+ pPlugin->setParameter(k, pval);
+ }
}
globalOut &= 1;
}
/* -------------------------------------------------------------------------- */
-void Plugin::initEditor()
+void Plugin::init()
{
+ ui = NULL;
+ id = idGenerator++;;
+ bypass = false;
+ status = 1;
+
if (getActiveEditor() != NULL) {
- gLog("[Plugin::initEditor] plugin has an already active editor!\n");
+ gLog("[Plugin::init] plugin has an already active editor!\n");
return;
}
- ui = createEditor();
+ ui = createEditorIfNeeded();
if (ui == NULL) {
- gLog("[Plugin::initEditor] unable to create editor!\n");
+ gLog("[Plugin::init] unable to create editor, the plugin might be GUI-less!\n");
return;
}
+
+ gLog("[Plugin::init] editor initialized and ready\n");
}
return;
}
ui->setOpaque(true);
- ui->setVisible(true);
ui->addToDesktop(0, parent);
}
bool Plugin::isEditorOpen()
{
- return ui->isVisible();
+ return ui->isVisible() && ui->isOnDesktop();
}
{
if (ui == NULL)
return;
- ui->setVisible(false);
if (ui->isOnDesktop())
ui->removeFromDesktop();
}
#define __PLUGIN_H__
-#include "../deps/juce/juce_audio_basics/juce_audio_basics.h"
-#include "../deps/juce/juce_audio_processors/juce_audio_processors.h"
-#include "../deps/juce/juce_core/juce_core.h"
-#include "../deps/juce/juce_data_structures/juce_data_structures.h"
-#include "../deps/juce/juce_events/juce_events.h"
-#include "../deps/juce/juce_graphics/juce_graphics.h"
-#include "../deps/juce/juce_gui_basics/juce_gui_basics.h"
-#include "../deps/juce/juce_gui_extra/juce_gui_extra.h"
+#include "../deps/juce/config.h"
using std::string;
public:
- /* initEditor
- * Prepare plugin GUI. 'parent' is a void pointer to the parent window that
- * will contain it. */
-
- void initEditor();
+ void init();
void showEditor(void *parent);
string getUniqueId();
- inline void setId() { id = idGenerator++; }
- inline int getId() { return id; }
- inline bool getStatus() { return status; }
- inline bool isBypassed() { return bypass; }
- inline int getEditorW() { return ui->getWidth(); }
- inline int getEditorH() { return ui->getHeight(); }
-
- inline void toggleBypass() { bypass = !bypass; }
- inline void setStatus(int s) { status = s; }
- inline void setBypass(bool b) { bypass = b; }
-
+ int getId() { return id; }
+ bool getStatus() { return status; }
+ bool isBypassed() { return bypass; }
+ int getEditorW() { return ui->getWidth(); }
+ int getEditorH() { return ui->getHeight(); }
+ void toggleBypass() { bypass = !bypass; }
+ void setStatus(int s) { status = s; }
+ void setBypass(bool b) { bypass = b; }
};
#endif
buffersize = _buffersize;
missingPlugins = false;
//unknownPluginList.empty();
- loadList(gGetHomePath() + gGetSlash() + "plugins.xml");
+ loadList(gGetHomePath() + G_SLASH + "plugins.xml");
}
return NULL;
}
- p->setStatus(1);
- p->setId();
+ //p->setStatus(1);
+ //p->setId();
+ //p->initEditor();
+ p->init();
p->prepareToPlay(samplerate, buffersize);
gLog("[PluginHost::addPlugin] plugin instance with fid=%s created\n", fid.c_str());
#include <pthread.h>
-//#include "../deps/juce/AppConfig.h"
-// TODO - can we move this stuff to a separate file?
-#include "../deps/juce/juce_audio_basics/juce_audio_basics.h"
-#include "../deps/juce/juce_audio_processors/juce_audio_processors.h"
-#include "../deps/juce/juce_core/juce_core.h"
-#include "../deps/juce/juce_data_structures/juce_data_structures.h"
-#include "../deps/juce/juce_events/juce_events.h"
-#include "../deps/juce/juce_graphics/juce_graphics.h"
-#include "../deps/juce/juce_gui_basics/juce_gui_basics.h"
-#include "../deps/juce/juce_gui_extra/juce_gui_extra.h"
+#include "../deps/juce/config.h"
using std::string;
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* recorder
* Action recorder.
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
#include <math.h>
#include "../utils/utils.h"
-
-
extern Mixer G_Mixer;
extern Patch_DEPR_ f_patch;
extern Conf G_Conf;
composite cmp;
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void init()
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
bool canRec(Channel *ch)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void rec(int index, int type, int frame, uint32_t iValue, float fValue)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void clearChan(int index)
if (j == global.at(i).size()) break; // for each action j of frame i
action *a = global.at(i).at(j);
if (a->chan == index) {
-#ifdef WITH_VST
-#if 0
- if (a->type == ACTION_MIDI)
- free(a->event);
-#endif
-#endif
free(a);
global.at(i).erase(global.at(i).begin() + j);
}
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void clearAction(int index, char act)
}
}
Channel *ch = G_Mixer.getChannelByIndex(index);
- ch->hasActions = false; /// FIXME - why this? Isn't it useless if we call chanHasActions?
+ ch->hasActions = false; /// FIXME - why this? Isn't it useless if we call setChanHasActionsStatus?
optimize();
- chanHasActions(index); /// FIXME
+ setChanHasActionsStatus(index); /// FIXME
//print();
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void deleteAction(int chan, int frame, char type, bool checkValues, uint32_t iValue, float fValue)
while (lockStatus == 0) {
lockStatus = pthread_mutex_trylock(&G_Mixer.mutex_recs);
if (lockStatus == 0) {
-#ifdef WITH_VST
-#if 0
- if (type == ACTION_MIDI)
- free(a->event);
-#endif
-#endif
free(a);
global.at(i).erase(global.at(i).begin() + j);
pthread_mutex_unlock(&G_Mixer.mutex_recs);
}
if (found) {
optimize();
- chanHasActions(chan);
+ setChanHasActionsStatus(chan);
gLog("[REC] action deleted, type=%d frame=%d chan=%d iValue=%d (%X) fValue=%f\n",
type, frame, chan, iValue, iValue, fValue);
}
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void deleteActions(int chan, int frame_a, int frame_b, char type)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void clearAll()
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void optimize()
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void sortActions()
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void updateBpm(float oldval, float newval, int oldquanto)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void updateSamplerate(int systemRate, int patchRate)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void expand(int old_fpb, int new_fpb)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void shrink(int new_fpb)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-void chanHasActions(int index)
+void setChanHasActionsStatus(int index)
{
Channel *ch = G_Mixer.getChannelByIndex(index);
if (global.size() == 0) {
ch->hasActions = false;
return;
}
- for (unsigned i=0; i<global.size() && !ch->hasActions; i++) {
- for (unsigned j=0; j<global.at(i).size() && !ch->hasActions; j++) {
- if (global.at(i).at(j)->chan == index)
+ for (unsigned i=0; i<global.size(); i++) {
+ for (unsigned j=0; j<global.at(i).size(); j++) {
+ if (global.at(i).at(j)->chan == index) {
ch->hasActions = true;
+ return;
+ }
}
}
+ ch->hasActions = false;
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int getNextAction(int chan, char type, int frame, action **out, uint32_t iValue)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int getAction(int chan, char action, int frame, struct action **out)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void startOverdub(int index, char actionMask, int frame)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void stopOverdub(int frame)
/* remove any nested action between keypress----keyrel, then record */
- if (!nullLoop)
+ if (!nullLoop) {
deleteActions(cmp.a2.chan, cmp.a1.frame, cmp.a2.frame, cmp.a1.type);
deleteActions(cmp.a2.chan, cmp.a1.frame, cmp.a2.frame, cmp.a2.type);
+ }
if (!ringLoop && !nullLoop) {
rec(cmp.a2.chan, cmp.a2.type, cmp.a2.frame);
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void print()
#include "const.h"
#include "mixer.h"
-#ifdef WITH_VST
-
-/* before including aeffetx(x).h we must define __cdecl, otherwise VST
- * headers can't be compiled correctly. In windows __cdecl is already
- * defined. */
-
- #ifdef __GNUC__
- #ifndef _WIN32
- #define __cdecl
- #endif
- #endif
- #include "../deps/vst/aeffectx.h"
-#endif
-
using std::vector;
* [global3]-->[vector<_action*>3]-->[a0][a1][a2] 3[frames4]
* */
-namespace recorder {
-
+namespace recorder
+{
/* action
* struct containing fields to describe an atomic action. Note from
* VST sdk: parameter values, like all VST parameters, are declared as
* floats with an inclusive range of 0.0 to 1.0 (fValue). */
-struct action {
+struct action
+{
int chan; // channel index, i.e. Channel->index
int type;
int frame; // redundant info, used by helper functions
* a group of two actions (keypress+keyrel, muteon+muteoff) used during
* the overdub process */
-struct composite {
+struct composite
+{
action a1;
action a2;
};
void init();
-/* chanHasActions
+/* setChanHasActionsStatus
* Check if the channel has at least one action recorded. If false, sets
* ch->hasActions = false. Used after an action deletion. */
-void chanHasActions(int chan);
+void setChanHasActionsStatus(int chan);
/* canRec
* can a channel rec an action? Call this one BEFORE rec(). */
return false;
w->name = "TAKE-" + gItoa(takeId);
- w->pathfile = gGetCurrentPath() + gGetSlash() + w->name;
+ w->pathfile = gGetCurrentPath() + G_SLASH + w->name;
wave = w;
status = STATUS_OFF;
begin = 0;
else {
/* fillChan only if frame != 0. If you call fillChan on frame == 0
- * a duplicate call to fillChan occurs with loss of data. */
+ a duplicate call to fillChan occurs with loss of data. Yeah, but
+ what happens if an action really occurs on frame 0 (and it happens,
+ for example when you start the sequencer from the firt beat)? Cheat
+ time! Shift a little bit the frame, so that it's no longer zero. */
status = STATUS_PLAY;
sendMidiLplay();
- if (frame != 0)
+ if (frame == 0)
+ frame = 2;
+ //if (frame != 0)
tracker = fillChan(vChan, tracker, frame);
}
}
#include <math.h>
#include "../utils/utils.h"
#include "../utils/log.h"
-#include "wave.h"
#include "init.h"
+#include "const.h"
+#include "wave.h"
+
+
+using std::string;
Wave::Wave()
/* -------------------------------------------------------------------------- */
-std::string Wave::basename() const
+string Wave::basename(bool ext) const
{
- return gStripExt(gBasename(pathfile.c_str()).c_str());
+ return ext ? gBasename(pathfile) : gStripExt(gBasename(pathfile));
}
-std::string Wave::extension() const
+string Wave::extension() const
{
return gGetExt(pathfile.c_str());
}
void Wave::updateName(const char *n)
{
- std::string ext = gGetExt(pathfile.c_str());
- name = gStripExt(gBasename(n).c_str());
- pathfile = gDirname(pathfile.c_str()) + gGetSlash() + name + "." + ext;
- isLogical = true;
+ string ext = gGetExt(pathfile.c_str());
+ name = gStripExt(gBasename(n).c_str());
+ pathfile = gDirname(pathfile.c_str()) + G_SLASH + name + "." + ext;
+ isLogical = true;
/* a wave with updated name must become logical, since the underlying
* file does not exist yet. */
#include <string>
+using std::string;
+
+
class Wave
{
private:
~Wave();
Wave(const Wave &other);
- std::string pathfile; // full path + sample name
- std::string name; // sample name (changeable)
+ string pathfile; // full path + sample name
+ string name; // sample name (changeable)
float *data;
int size; // wave size (size in stereo: size / 2)
inline void channels(int v) { inHeader.channels = v; }
inline void frames (int v) { inHeader.frames = v; }
- std::string basename () const;
- std::string extension() const;
+ string basename (bool ext=false) const;
+ string extension() const;
void updateName(const char *n);
int open (const char *f);
ch->panRight= 0.0f + val;
char buf[8];
- sprintf(buf, "%d L", abs((ch->panRight * 100.0f) - 100));
+ sprintf(buf, "%d L", (int) abs((ch->panRight * 100.0f) - 100));
win->panNum->value(buf);
}
else if (val == 1.0f) {
ch->panRight= 1.0f;
char buf[8];
- sprintf(buf, "%d R", abs((ch->panLeft * 100.0f) - 100));
+ sprintf(buf, "%d R", (int) abs((ch->panLeft * 100.0f) - 100));
win->panNum->value(buf);
}
win->panNum->redraw();
#include "../gui/elems/ge_keyboard.h"
#include "../gui/dialogs/gd_mainWindow.h"
#include "../gui/dialogs/gd_warnings.h"
+#include "../gui/dialogs/gd_browser.h"
#include "../core/mixer.h"
#include "../core/mixerHandler.h"
#include "../core/channel.h"
#endif
-static void __glue_setProgressBar__(class gProgress *status, float v)
-{
- status->value(status->value() + v);
- //Fl::check();
- Fl::wait(0);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
#ifdef WITH_VST
static void __glue_fillPatchGlobalsPlugins__(vector <Plugin *> *host, vector<Patch::plugin_t> *patch)
/* -------------------------------------------------------------------------- */
-int glue_savePatch(const string &fullPath, const string &name, bool isProject)
+static bool __glue_savePatch__(const string &fullPath, const string &name,
+ bool isProject)
{
G_Patch.init();
if (G_Patch.write(fullPath)) {
gu_update_win_label(name.c_str());
- gLog("[glue] patch saved as %s\n", fullPath.c_str());
- return 1;
+ gLog("[glue_savePatch] patch saved as %s\n", fullPath.c_str());
+ return true;
}
- return 0;
+ return false;
}
/* -------------------------------------------------------------------------- */
-int glue_loadPatch(const string &fullPath, class gProgress *status, bool isProject)
+void glue_savePatch(void *data)
{
- /* try to load the new JSON-based patch. If it fails, fall back to deprecated
- * one. */
+ gdSaveBrowser *browser = (gdSaveBrowser*) data;
+ string name = browser->getName();
+ string fullPath = browser->getCurrentPath() + G_SLASH + gStripExt(name) + ".gptc";
+
+ if (name == "") {
+ gdAlert("Please choose a file name.");
+ return;
+ }
+
+ if (gFileExists(fullPath.c_str()))
+ if (!gdConfirmWin("Warning", "File exists: overwrite?"))
+ return;
+
+ if (__glue_savePatch__(fullPath, name, false)) { // false == not a project
+ G_Conf.patchPath = gDirname(fullPath);
+ browser->do_callback();
+ }
+ else
+ gdAlert("Unable to save the patch!");
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_loadPatch(void *data)
+{
+ gdLoadBrowser *browser = (gdLoadBrowser*) data;
+ string fullPath = browser->getSelectedItem();
+ bool isProject = gIsProject(browser->getSelectedItem());
+
+ browser->showStatusBar();
gLog("[glue] loading %s...\n", fullPath.c_str());
string fileToLoad = fullPath; // patch file to read from
string basePath = ""; // base path, in case of reading from a project
if (isProject) {
- fileToLoad = fullPath + gGetSlash() + gStripExt(gBasename(fullPath)) + ".gptc";
- basePath = fullPath.c_str() + gGetSlash();
+ fileToLoad = fullPath + G_SLASH + gStripExt(gBasename(fullPath)) + ".gptc";
+ basePath = fullPath + G_SLASH;
}
- int res = G_Patch.read(fileToLoad);
+ /* try to load the new JSON-based patch. If it fails, fall back to deprecated
+ * one. */
+
+ int res = G_Patch.read(fileToLoad);
+ bool deprecated = false;
if (res == PATCH_UNREADABLE) {
gLog("[glue] failed reading JSON-based patch. Trying with the deprecated method\n");
- return glue_loadPatch__DEPR__(gBasename(fileToLoad).c_str(), fileToLoad.c_str(), status, isProject);
+ deprecated = true;
+ res = glue_loadPatch__DEPR__(gBasename(fileToLoad).c_str(), fileToLoad.c_str(),
+ browser->getStatusBar(), isProject);
+ }
+
+ if (res != PATCH_READ_OK) {
+ if (res == PATCH_UNREADABLE)
+ isProject ? gdAlert("This project is unreadable.") : gdAlert("This patch is unreadable.");
+ else
+ if (res == PATCH_INVALID)
+ isProject ? gdAlert("This project is not valid.") : gdAlert("This patch is not valid.");
+
+ browser->hideStatusBar();
+ return;
+ }
+ else
+ if (deprecated) {
+ browser->do_callback();
+ return;
}
- if (res != PATCH_READ_OK)
- return res;
/* close all other windows. This prevents segfault if plugin
* windows GUIs are on. */
glue_resetToInitState(false, false);
- __glue_setProgressBar__(status, 0.1f);
+ browser->setStatusBar(0.1f);
+ //__glue_setProgressBar__(status, 0.1f);
/* Add common stuff, columns and channels. Also increment the progress bar
* by 0.8 / total_channels steps. */
ch->readPatch(basePath, k, &G_Patch, &G_Mixer.mutex_plugins,
G_Conf.samplerate, G_Conf.rsmpQuality);
}
- __glue_setProgressBar__(status, steps);
+ //__glue_setProgressBar__(status, steps);
+ browser->setStatusBar(steps);
}
}
/* save patchPath by taking the last dir of the broswer, in order to
* reuse it the next time */
- G_Conf.patchPath = gDirname(fullPath.c_str());
+ G_Conf.patchPath = gDirname(fullPath);
/* refresh GUI */
gu_updateControls();
gu_update_win_label(G_Patch.name.c_str());
- __glue_setProgressBar__(status, 1.0f);
+ browser->setStatusBar(0.1f);
+ //__glue_setProgressBar__(status, 1.0f);
gLog("[glue] patch loaded successfully\n");
#endif
- return res;
+ browser->do_callback();
}
/* -------------------------------------------------------------------------- */
-int glue_saveProject(const string &folderPath, const string &projName)
+void glue_saveProject(void *data)
{
- if (!gDirExists(folderPath.c_str()) && !gMkdir(folderPath.c_str())) {
- gLog("[glue] unable to make project directory!\n");
- return 0;
+ gdSaveBrowser *browser = (gdSaveBrowser*) data;
+ string name = browser->getName();
+ string folderPath = browser->getCurrentPath(); //browser->getSelectedItem();
+ string fullPath = folderPath + G_SLASH + gStripExt(name) + ".gprj";
+
+ if (name == "") {
+ gdAlert("Please choose a project name.");
+ return;
+ }
+
+ if (gIsProject(fullPath.c_str()) && !gdConfirmWin("Warning", "Project exists: overwrite?"))
+ return;
+
+ if (!gDirExists(fullPath.c_str()) && !gMkdir(fullPath.c_str())) {
+ gLog("[glue_saveProject] unable to make project directory!\n");
+ return;
}
+ gLog("[glue_saveProject] project dir created: %s\n", fullPath.c_str());
+
/* copy all samples inside the folder. Takes and logical ones are saved
* via glue_saveSample() */
/* update the new samplePath: everything now comes from the project
* folder (folderPath). Also remove any existing file. */
- string samplePath = folderPath + gGetSlash() + ch->wave->basename() + "." + ch->wave->extension();
+ string samplePath = fullPath + G_SLASH + ch->wave->basename(true);
if (gFileExists(samplePath.c_str()))
remove(samplePath.c_str());
ch->wave->pathfile = samplePath;
}
- string gptcPath = folderPath + gGetSlash() + gStripExt(projName.c_str()) + ".gptc";
- glue_savePatch(gptcPath, projName, true); // true == it's a project
+ string gptcPath = fullPath + G_SLASH + gStripExt(name.c_str()) + ".gptc";
+ if (__glue_savePatch__(gptcPath, name, true)) // true == it's a project
+ browser->do_callback();
+ else
+ gdAlert("Unable to save the project!");
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_loadSample(void *data)
+{
+ gdLoadBrowser *browser = (gdLoadBrowser*) data;
+ string fullPath = browser->getSelectedItem();
+
+ if (fullPath.empty())
+ return;
+
+ int res = glue_loadChannel((SampleChannel*) browser->getChannel(), fullPath.c_str());
- return 1;
+ if (res == SAMPLE_LOADED_OK) {
+ G_Conf.samplePath = gDirname(fullPath);
+ browser->do_callback();
+ mainWin->delSubWindow(WID_SAMPLE_EDITOR); // if editor is open
+ }
+ else
+ mainWin->keyboard->printChannelMessage(res);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_saveSample(void *data)
+{
+ gdSaveBrowser *browser = (gdSaveBrowser*) data;
+ string name = browser->getName();
+ string folderPath = browser->getSelectedItem();
+
+ if (name == "") {
+ gdAlert("Please choose a file name.");
+ return;
+ }
+
+ /* bruteforce check extension. */
+
+ string filePath = folderPath + G_SLASH + gStripExt(name) + ".wav";
+
+ if (gFileExists(filePath))
+ if (!gdConfirmWin("Warning", "File exists: overwrite?"))
+ return;
+
+ if (((SampleChannel*)browser->getChannel())->save(filePath.c_str())) {
+ G_Conf.samplePath = gDirname(folderPath);
+ browser->do_callback();
+ }
+ else
+ gdAlert("Unable to save this sample!");
}
using std::vector;
-int glue_loadPatch (const string &fullPath, class gProgress *status, bool isProject);
+void glue_loadPatch (void *data);
int glue_loadPatch__DEPR__(const char *fname, const char *fpath, class gProgress *status, bool isProject);
-int glue_savePatch (const string &fullPath, const string &name, bool isProject);
-int glue_saveProject(const string &folderPath, const string &projName);
+void glue_savePatch (void *data);
+void glue_saveProject(void *data);
+void glue_saveSample (void *data);
+void glue_loadSample (void *data);
#endif
"Version " G_VERSION_STR " (" BUILD_DATE ")\n\n"
"Developed by Monocasual\n"
"Based on FLTK (%d.%d.%d), RtAudio (%s),\n"
- "RtMidi (%s), libsamplerate, Jansson (%s) \n"
- "and libsndfile\n\n"
+ "RtMidi (%s), Libsamplerate, Jansson (%s),\n"
+ "Libsndfile"
+#ifdef WITH_VST
+ ", JUCE (%d.%d.%d)\n\n"
+#else
+ "\n\n"
+#endif
"Released under the terms of the GNU General\n"
"Public License (GPL v3)\n\n"
"News, infos, contacts and documentation:\n"
FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION,
kernelAudio::getRtAudioVersion().c_str(),
kernelMidi::getRtMidiVersion().c_str(),
- JANSSON_VERSION);
+ JANSSON_VERSION
+#ifdef WITH_VST
+ , JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JUCE_BUILDNUMBER);
+#else
+ );
+#endif
int tw = 0;
int th = 0;
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* gd_actionEditor
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
#include <math.h>
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
gdActionEditor::~gdActionEditor() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gdActionEditor::cb_zoomIn(Fl_Widget *w, void *p) { ((gdActionEditor*)p)->__cb_zoomIn(); }
void gdActionEditor::cb_zoomOut(Fl_Widget *w, void *p) { ((gdActionEditor*)p)->__cb_zoomOut(); }
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gdActionEditor::__cb_zoomIn() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gdActionEditor::__cb_zoomOut() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gdActionEditor::update() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int gdActionEditor::handle(int e) {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int gdActionEditor::getActionType() {
}
-/* ------------------------------------------------------------------ */
-/* ------------------------------------------------------------------ */
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
gGridTool::gGridTool(int x, int y, gdActionEditor *parent)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
gGridTool::~gGridTool() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gGridTool::cb_changeType(Fl_Widget *w, void *p) { ((gGridTool*)p)->__cb_changeType(); }
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gGridTool::__cb_changeType() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
bool gGridTool::isOn() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int gGridTool::getValue() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void gGridTool::calc() {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int gGridTool::getSnapPoint(int v) {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int gGridTool::getSnapFrame(int v) {
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int gGridTool::getCellSize() {
* -------------------------------------------------------------------------- */
-#include "../../core/mixer.h"
#include "../../core/graphics.h"
#include "../../core/wave.h"
#include "../../core/channel.h"
#include "../../core/sampleChannel.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/patch.h"
#include "../../core/conf.h"
#include "../../glue/glue.h"
#include "../../glue/channel.h"
#include "../../glue/storage.h"
+#include "../../utils/gui_utils.h"
#include "../elems/ge_browser.h"
#include "../elems/ge_channel.h"
-#include "../elems/ge_keyboard.h"
#include "gd_browser.h"
-#include "gd_mainWindow.h"
-#include "gd_warnings.h"
using std::string;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern Patch G_Patch;
-extern Conf G_Conf;
-extern Mixer G_Mixer;
-extern gdMainWindow *mainWin;
+extern Conf G_Conf;
-gdBrowser::gdBrowser(const char *title, const char *initPath, Channel *ch, int type, int stackType)
- : gWindow (396, 302, title),
- ch (ch),
- type (type),
- stackType(stackType)
+gdBaseBrowser::gdBaseBrowser(int x, int y, int w, int h, const string &title,
+ const string &path, void (*callback)(void*))
+ : gWindow(x, y, w, h, title.c_str()), callback(callback)
{
set_non_modal();
- browser = new gBrowser(8, 36, 380, 230);
- Fl_Group *group_btn = new Fl_Group(8, 274, 380, 20);
- gBox *b = new gBox(8, 274, 204, 20); // spacer window border <-> buttons
- ok = new gClick(308, 274, 80, 20);
- cancel = new gClick(220, 274, 80, 20, "Cancel");
- status = new gProgress(8, 274, 204, 20);
- status->minimum(0);
- status->maximum(1);
- status->hide(); // show the bar only if necessary
- group_btn->resizable(b);
- group_btn->end();
-
- Fl_Group *group_upd = new Fl_Group(8, 8, 380, 25);
- if (type == BROWSER_SAVE_PATCH || type == BROWSER_SAVE_SAMPLE || type == BROWSER_SAVE_PROJECT) /// bitmask please!
- name = new gInput(208, 8, 152, 20);
- if (type == BROWSER_SAVE_PATCH || type == BROWSER_SAVE_SAMPLE || type == BROWSER_SAVE_PROJECT) /// bitmask please!
- where = new gInput(8, 8, 192, 20);
- else
- where = new gInput(8, 8, 352, 20);
- updir = new gClick(368, 8, 20, 20, "", updirOff_xpm, updirOn_xpm);
- group_upd->resizable(where);
- group_upd->end();
-
- end();
-
- resizable(browser);
- size_range(w(), h(), 0, 0);
+ groupTop = new Fl_Group(8, 8, w-16, 20);
+ where = new gInput(groupTop->x(), groupTop->y(), 152, 20);
+ updir = new gClick(groupTop->x()+groupTop->w()-20, groupTop->y(), 20, 20, "", updirOff_xpm, updirOn_xpm);
+ groupTop->end();
+ groupTop->resizable(where);
where->readonly(true);
where->cursor_color(COLOR_BG_DARK);
+ where->value(path.c_str());
- if (type == BROWSER_SAVE_PATCH || type == BROWSER_SAVE_SAMPLE || type == BROWSER_SAVE_PROJECT) /// bitmask please!
- ok->label("Save");
- else
- ok->label("Load");
+ updir->callback(cb_up, (void*) this);
- if (type == BROWSER_LOAD_PATCH)
- ok->callback(cb_load_patch, (void*)this);
- else
- if (type == BROWSER_LOAD_SAMPLE)
- ok->callback(cb_load_sample, (void*)this);
- else
- if (type == BROWSER_SAVE_PATCH) {
- ok->callback(cb_save_patch, (void*)this);
- name->value(G_Patch.name == "" ? "my_patch.gptc" : G_Patch.name.c_str());
- name->maximum_size(MAX_PATCHNAME_LEN+5); // +5 for ".gptc"
- }
- else
- if (type == BROWSER_SAVE_SAMPLE) {
- ok->callback(cb_save_sample, (void*)this);
- name->value(((SampleChannel*)ch)->wave->name.c_str());
- }
- else
- if (type == BROWSER_SAVE_PROJECT) {
- ok->callback(cb_save_project, (void*)this);
- name->value(gStripExt(G_Patch.name).c_str());
- }
+ browser = new gBrowser(8, groupTop->y()+groupTop->h()+8, w-16, h-73);
+ browser->loadDir(path);
+ if (path == G_Conf.browserLastPath)
+ browser->preselect(G_Conf.browserPosition, G_Conf.browserLastValue);
- ok->shortcut(FL_Enter);
+ Fl_Group *groupButtons = new Fl_Group(8, browser->y()+browser->h()+8, w-16, 20);
+ ok = new gClick(w-88, groupButtons->y(), 80, 20);
+ cancel = new gClick(w-ok->w()-96, groupButtons->y(), 80, 20, "Cancel");
+ status = new gProgress(8, groupButtons->y(), cancel->x()-16, 20);
+ status->minimum(0);
+ status->maximum(1);
+ status->hide(); // show the bar only if necessary
+ groupButtons->resizable(status);
+ groupButtons->end();
+
+ end();
- updir->callback(cb_up, (void*)this);
- cancel->callback(cb_close, (void*)this);
- browser->callback(cb_down, this);
- browser->path_obj = where;
- browser->init(initPath);
+ cancel->callback(cb_close, (void*) this);
- if (G_Conf.browserW)
- resize(G_Conf.browserX, G_Conf.browserY, G_Conf.browserW, G_Conf.browserH);
+ resizable(browser);
+ size_range(320, 200);
gu_setFavicon(this);
show();
/* -------------------------------------------------------------------------- */
-gdBrowser::~gdBrowser() {
+gdBaseBrowser::~gdBaseBrowser()
+{
G_Conf.browserX = x();
G_Conf.browserY = y();
G_Conf.browserW = w();
G_Conf.browserH = h();
+ G_Conf.browserPosition = browser->position();
+ G_Conf.browserLastPath = gDirname(browser->getSelectedItem());
+ G_Conf.browserLastValue = browser->value();
}
/* -------------------------------------------------------------------------- */
-void gdBrowser::cb_load_patch (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_load_patch(); }
-void gdBrowser::cb_load_sample (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_load_sample(); }
-void gdBrowser::cb_save_sample (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_save_sample(); }
-void gdBrowser::cb_save_patch (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_save_patch(); }
-void gdBrowser::cb_save_project(Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_save_project(); }
-void gdBrowser::cb_down (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_down(); }
-void gdBrowser::cb_up (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_up(); }
-void gdBrowser::cb_close (Fl_Widget *v, void *p) { ((gdBrowser*)p)->__cb_close(); }
+void gdBaseBrowser::cb_up (Fl_Widget *v, void *p) { ((gdBaseBrowser*)p)->__cb_up(); }
+void gdBaseBrowser::cb_close(Fl_Widget *v, void *p) { ((gdBaseBrowser*)p)->__cb_close(); }
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_load_patch() {
+void gdBaseBrowser::__cb_up() {
+ string dir = browser->getCurrentDir();
+ dir = dir.substr(0, dir.find_last_of(G_SLASH_STR)); // remove up to the next slash
+ browser->loadDir(dir);
+ where->value(browser->getCurrentDir().c_str());
+}
- if (browser->text(browser->value()) == NULL)
- return;
- bool isProject = gIsProject(browser->get_selected_item());
- int res = glue_loadPatch(browser->get_selected_item(), status, isProject);
+/* -------------------------------------------------------------------------- */
+
- if (res == PATCH_UNREADABLE) {
- status->hide();
- if (isProject)
- gdAlert("This project is unreadable.");
- else
- gdAlert("This patch is unreadable.");
- }
- else
- if (res == PATCH_INVALID) {
- status->hide();
- if (isProject)
- gdAlert("This project is not valid.");
- else
- gdAlert("This patch is not valid.");
- }
- else
- do_callback();
+void gdBaseBrowser::__cb_close() {
+ do_callback();
}
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_save_sample() {
-
- if (strcmp(name->value(), "") == 0) { /// FIXME glue business
- gdAlert("Please choose a file name.");
- return;
- }
+void gdBaseBrowser::setStatusBar(float v)
+{
+ status->value(status->value() + v);
+ Fl::wait(0);
+}
- /* bruteforce check extension. */
- string filename = gStripExt(name->value());
- char fullpath[PATH_MAX];
- sprintf(fullpath, "%s/%s.wav", where->value(), filename.c_str());
+/* -------------------------------------------------------------------------- */
- if (gFileExists(fullpath))
- if (!gdConfirmWin("Warning", "File exists: overwrite?"))
- return;
- if (((SampleChannel*)ch)->save(fullpath))
- do_callback();
- else
- gdAlert("Unable to save this sample!");
+string gdBaseBrowser::getSelectedItem()
+{
+ return browser->getSelectedItem();
}
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_load_sample() {
- if (browser->text(browser->value()) == NULL)
- return;
+gdSaveBrowser::gdSaveBrowser(int x, int y, int w, int h, const string &title,
+ const string &path, const string &_name, void (*cb)(void*), Channel *ch)
+ : gdBaseBrowser(x, y, w, h, title, path, cb)
+{
+ channel = ch;
- int res = glue_loadChannel((SampleChannel*) ch, browser->get_selected_item());
+ where->size(groupTop->w()-236, 20);
- if (res == SAMPLE_LOADED_OK) {
- do_callback();
- mainWin->delSubWindow(WID_SAMPLE_EDITOR); // if editor is open
- }
- else
- mainWin->keyboard->printChannelMessage(res);
+ name = new gInput(where->x()+where->w()+8, 8, 200, 20);
+ name->value(_name.c_str());
+ groupTop->add(name);
+
+ browser->callback(cb_down, (void*) this);
+
+ ok->label("Save");
+ ok->callback(cb_save, (void*) this);
+ ok->shortcut(FL_ENTER);
}
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_down() {
- const char *path = browser->get_selected_item();
- if (!path) // when click on an empty area
- return;
- if (!gIsDir(path)) {
-
- /* set the name of the patch/sample/project as the selected item */
-
- if (type == BROWSER_SAVE_PATCH || type == BROWSER_SAVE_SAMPLE || type == BROWSER_SAVE_PROJECT) {
- if (gIsProject(path)) {
- string tmp = browser->text(browser->value());
- tmp.erase(0, 4);
- name->value(tmp.c_str());
- }
- else
- name->value(browser->text(browser->value()));
- }
+void gdSaveBrowser::cb_save(Fl_Widget *v, void *p) { ((gdSaveBrowser*)p)->__cb_save(); }
+void gdSaveBrowser::cb_down(Fl_Widget *v, void *p) { ((gdSaveBrowser*)p)->__cb_down(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdSaveBrowser::__cb_down()
+{
+ string path = browser->getSelectedItem();
+
+ if (path.empty()) // when click on an empty area
return;
+
+ /* if the selected item is a directory just load its content. If it's a file
+ * use it as the file name (i.e. fill name->value()). */
+
+ if (gIsDir(path)) {
+ browser->loadDir(path);
+ where->value(browser->getCurrentDir().c_str());
}
- browser->clear();
- browser->down_dir(path);
- browser->sort();
+ else
+ name->value(browser->getSelectedItem(false).c_str());
}
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_up() {
- browser->clear();
- browser->up_dir();
- browser->sort();
+void gdSaveBrowser::__cb_save()
+{
+ callback((void*) this);
}
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_save_patch()
+gdLoadBrowser::gdLoadBrowser(int x, int y, int w, int h, const string &title,
+ const string &path, void (*cb)(void*), Channel *ch)
+ : gdBaseBrowser(x, y, w, h, title, path, cb)
{
- if (strcmp(name->value(), "") == 0) { /// FIXME glue business
- gdAlert("Please choose a file name.");
- return;
- }
+ channel = ch;
- string fullpath = where->value() + gGetSlash() + gStripExt(name->value()) + ".gptc";
+ where->size(groupTop->w()-updir->w()-8, 20);
- if (gFileExists(fullpath.c_str()))
- if (!gdConfirmWin("Warning", "File exists: overwrite?"))
- return;
+ browser->callback(cb_down, (void*) this);
- if (glue_savePatch(fullpath, name->value(), false)) // false == not a project
- do_callback();
- else
- gdAlert("Unable to save the patch!");
+ ok->label("Load");
+ ok->callback(cb_load, (void*) this);
+ ok->shortcut(FL_ENTER);
}
+
+
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_save_project()
-{
- if (strcmp(name->value(), "") == 0) { /// FIXME glue business
- gdAlert("Please choose a project name.");
- return;
- }
+void gdLoadBrowser::cb_load(Fl_Widget *v, void *p) { ((gdLoadBrowser*)p)->__cb_load(); }
+void gdLoadBrowser::cb_down(Fl_Widget *v, void *p) { ((gdLoadBrowser*)p)->__cb_down(); }
- string fullpath = where->value() + gGetSlash() + gStripExt(name->value()) + ".gprj";
- if (gIsProject(fullpath.c_str()) && !gdConfirmWin("Warning", "Project exists: overwrite?"))
- return;
+/* -------------------------------------------------------------------------- */
- if (glue_saveProject(fullpath, name->value()))
- do_callback();
- else
- gdAlert("Unable to save the project!");
+
+void gdLoadBrowser::__cb_load()
+{
+ callback((void*) this);
}
/* -------------------------------------------------------------------------- */
-void gdBrowser::__cb_close() {
- do_callback();
+void gdLoadBrowser::__cb_down()
+{
+ string path = browser->getSelectedItem();
+
+ if (path.empty() || !gIsDir(path)) // when click on an empty area or not a dir
+ return;
+
+ browser->loadDir(path);
+ where->value(browser->getCurrentDir().c_str());
}
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* gd_browser
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
#ifndef GD_BROWSER_H
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
+#include "../elems/ge_mixed.h"
#include "../elems/ge_window.h"
-/* TODO - this class must be subclassed into gdPluginBrowser, gdFileBrowser,
- * and so on. It's a real mess right now. */
+class gdBaseBrowser : public gWindow
+{
+protected:
-class gdBrowser : public gWindow {
-
-private:
- static void cb_down(Fl_Widget *v, void *p);
- static void cb_up (Fl_Widget *v, void *p);
- static void cb_load_sample (Fl_Widget *v, void *p);
- static void cb_save_sample (Fl_Widget *v, void *p);
- static void cb_load_patch (Fl_Widget *v, void *p);
- static void cb_save_patch (Fl_Widget *v, void *p);
- static void cb_save_project(Fl_Widget *v, void *p);
- static void cb_close (Fl_Widget *w, void *p);
-
- inline void __cb_down();
- inline void __cb_up();
- inline void __cb_load_sample();
- inline void __cb_save_sample();
- inline void __cb_save_project();
- inline void __cb_load_patch();
- inline void __cb_save_patch();
- inline void __cb_close();
-
+ class Fl_Group *groupTop;
class gBrowser *browser;
class gClick *ok;
class gClick *cancel;
class gInput *where;
- class gInput *name;
class gClick *updir;
class gProgress *status;
- class Channel *ch;
+ static void cb_up (Fl_Widget *v, void *p);
+ static void cb_close(Fl_Widget *w, void *p);
+
+ inline void __cb_up ();
+ inline void __cb_close();
+
+ /* Callback
+ * Fired when the save/load button is pressed. */
+
+ void (*callback)(void*);
+
+ class Channel *channel;
+
+public:
+
+ gdBaseBrowser(int x, int y, int w, int h, const string &title,
+ const string &path, void (*callback)(void*));
+
+ ~gdBaseBrowser();
+
+ /* getSelectedItem
+ * Return the full path of the selected file. */
+
+ string getSelectedItem();
+
+ /* setStatusBar
+ * Increment status bar for progress tracking. */
+
+ void setStatusBar(float v);
+
+ inline gProgress *getStatusBar() { return status; } // TODO - remove with Patch_DEPR_
+ inline void showStatusBar() { status->show(); }
+ inline void hideStatusBar() { status->hide(); }
+ inline Channel *getChannel() { return channel; }
+ inline void fireCallback() { callback((void*) this); }
+ inline string getCurrentPath() { return where->value(); }
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+
+class gdSaveBrowser : public gdBaseBrowser
+{
+private:
+
+ class gInput *name;
+
+ static void cb_down(Fl_Widget *v, void *p);
+ static void cb_save(Fl_Widget *w, void *p);
+
+ inline void __cb_down();
+ inline void __cb_save();
+
+public:
+
+ gdSaveBrowser(int x, int y, int w, int h, const string &title,
+ const string &path, const string &name, void (*callback)(void*),
+ class Channel *ch);
+
+ string getName() { return name->value(); }
+};
- /* browser type: see const.h */
- /** FIXME internal enum:
- * enum browserType {
- * TYPE_A,
- * TYPE_B,
- * ....
- * }; */
- int type;
+/* -------------------------------------------------------------------------- */
- /* PluginHost_DEPR_ stack type. Used only when loading plugins */
- int stackType;
+class gdLoadBrowser : public gdBaseBrowser
+{
+private:
- char selectedFile[FILENAME_MAX];
+ static void cb_load(Fl_Widget *w, void *p);
+ static void cb_down(Fl_Widget *v, void *p);
+
+ inline void __cb_load();
+ inline void __cb_down();
public:
- gdBrowser(const char *title, const char *initPath, class Channel *ch, int type, int stackType=0);
- ~gdBrowser();
- char* SelectedFile();
+ gdLoadBrowser(int x, int y, int w, int h, const string &title,
+ const string &path, void (*callback)(void*), class Channel *ch);
};
#endif
midiMap->deactivate();
return;
}
+
for (unsigned i=0; i<G_MidiMap.maps.size(); i++) {
const char *imap = G_MidiMap.maps.at(i).c_str();
midiMap->add(imap);
if (G_Conf.midiMapPath == imap)
midiMap->value(i);
}
+
+ /* Preselect the 0 midimap if nothing is selected but midimaps exist. */
+
+ if (midiMap->value() == -1 && G_MidiMap.maps.size() > 0)
+ midiMap->value(0);
}
{
info->show();
G_PluginHost.scanDir(folderPath->value(), cb_onScan, (void*) this);
- G_PluginHost.saveList(gGetHomePath() + gGetSlash() + "plugins.xml");
+ G_PluginHost.saveList(gGetHomePath() + G_SLASH + "plugins.xml");
info->hide();
updateCount();
}
if (ch->panRight < 1.0f) {
char buf[8];
- sprintf(buf, "%d L", abs((ch->panRight * 100.0f) - 100));
+ sprintf(buf, "%d L", (int) abs((ch->panRight * 100.0f) - 100));
pan->value(ch->panRight);
panNum->value(buf);
}
}
else {
char buf[8];
- sprintf(buf, "%d R", abs((ch->panLeft * 100.0f) - 100));
+ sprintf(buf, "%d R", (int) abs((ch->panLeft * 100.0f) - 100));
pan->value(2.0f - ch->panLeft);
panNum->value(buf);
}
#include "../../core/conf.h"
#include "../../core/pluginHost.h"
#include "../../glue/glue.h"
+#include "../../glue/storage.h"
#include "../elems/ge_keyboard.h"
#include "gd_warnings.h"
#include "gd_bpmInput.h"
extern Mixer G_Mixer;
extern Patch_DEPR_ G_Patch_DEPR_;
+extern Patch G_Patch;
extern Conf G_Conf;
extern gdMainWindow *mainWin;
extern bool G_quit;
: gWindow(W, H, title)
{
Fl::visible_focus(0);
+
Fl::background(25, 25, 25);
Fl::set_boxtype(G_BOX, gDrawBox, 1, 1, 2, 2); // custom box G_BOX
add(keyboard);
callback(cb_endprogram);
gu_setFavicon(this);
+
show(argc, argv);
}
if (strcmp(m->label(), "Open patch or project...") == 0) {
- gWindow *childWin = new gdBrowser("Load Patch", G_Conf.patchPath.c_str(), 0, BROWSER_LOAD_PATCH);
+ //gWindow *childWin = new gdBrowser("Load Patch", G_Conf.patchPath.c_str(), 0, BROWSER_LOAD_PATCH);
+ //gu_openSubWindow(mainWin, childWin, WID_FILE_BROWSER);
+ gWindow *childWin = new gdLoadBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Load patch or project",
+ G_Conf.patchPath, glue_loadPatch, NULL);
gu_openSubWindow(mainWin, childWin, WID_FILE_BROWSER);
return;
}
if (G_Mixer.hasLogicalSamples() || G_Mixer.hasEditedSamples())
if (!gdConfirmWin("Warning", "You should save a project in order to store\nyour takes and/or processed samples."))
return;
- gWindow *childWin = new gdBrowser("Save Patch", G_Conf.patchPath.c_str(), 0, BROWSER_SAVE_PATCH);
+ gWindow *childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Save patch",
+ G_Conf.patchPath, G_Patch.name, glue_savePatch, NULL);
gu_openSubWindow(mainWin, childWin, WID_FILE_BROWSER);
return;
}
if (strcmp(m->label(), "Save project...") == 0) {
- gWindow *childWin = new gdBrowser("Save Project", G_Conf.patchPath.c_str(), 0, BROWSER_SAVE_PROJECT);
+ gWindow *childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Save project",
+ G_Conf.patchPath, G_Patch.name, glue_saveProject, NULL);
gu_openSubWindow(mainWin, childWin, WID_FILE_BROWSER);
return;
}
stackType, ch);
addSubWindow(pc);
pc->callback(cb_refreshList, (void*)this); // 'this' refers to gdPluginList
-
-#if 0
- gdBrowser *b = new gdBrowser("Browse Plugin_DEPR_", G_Conf.pluginPath.c_str(), ch, BROWSER_LOAD_PLUGIN, stackType);
- addSubWindow(b);
- b->callback(cb_refreshList, (void*)this); // 'this' refers to gdPluginList
-#endif
}
else {
w = new gdPluginWindow(pPlugin);
}
-#if 0
-
- /* TODO - at the moment you can open a window for each plugin in the stack.
- * This is not consistent with the rest of the gui. You can avoid this by
- * calling
- *
- * gu_openSubWindow(this, new gdPluginWindow(pPlugin), WID_FX);
- *
- * instead of the following code.
- *
- * EDIT 2 - having only 1 plugin window would be very uncomfortable */
-
- if (!pParent->hasWindow(pPlugin->getId()+1)) {
- gWindow *w;
- if (pPlugin->hasEditor())
-#ifdef __APPLE__
- w = new gdPluginWindowGUImac(pPlugin);
-#else
- w = new gdPluginWindowGUI(pPlugin);
-#endif
- else
- w = new gdPluginWindow(pPlugin);
- w->setId(pPlugin->getId()+1);
- pParent->addSubWindow(w);
- }
-#endif
}
show();
#ifndef __APPLE__
+
Fl::check();
+
#endif
gLog("[gdPluginWindowGUI] opening GUI, this=%p, xid=%p\n",
(void*) this, (void*) fl_xid(this));
- pPlugin->initEditor();
-
#if defined(__APPLE__)
+
void *cocoaWindow = (void*) fl_xid(this);
cocoa_setWindowSize(cocoaWindow, pPlugin->getEditorW(), pPlugin->getEditorH());
pPlugin->showEditor(cocoa_getViewFromWindow(cocoaWindow));
+
#else
+
pPlugin->showEditor((void*) fl_xid(this));
+
#endif
- resize(0, 0, pPlugin->getEditorW(), pPlugin->getEditorH());
+ int pluginW = pPlugin->getEditorW();
+ int pluginH = pPlugin->getEditorH();
+
+ printf("w=%d h=%d\n", Fl::w(), Fl::h());
+
+ resize((Fl::w() - pluginW) / 2, (Fl::h() - pluginH) / 2, pluginW, pluginH);
Fl::add_timeout(GUI_PLUGIN_RATE, cb_refresh, (void*) this);
- copy_label(pPlugin->getName().toStdString().c_str());
+ copy_label(pPlugin->getName().toRawUTF8());
}
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* ge_actionChannel
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
#include <FL/fl_draw.H>
extern Conf G_Conf;
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
gActionChannel::gActionChannel(int x, int y, gdActionEditor *pParent, SampleChannel *ch)
- : gActionWidget(x, y, 200, 40, pParent), ch(ch), selected(NULL)
+ : gActionWidget(x, y, 200, 40, pParent),
+ ch (ch),
+ selected (NULL)
{
size(pParent->totalWidth, h());
for (unsigned i=0; i<recorder::frames.size(); i++) {
for (unsigned j=0; j<recorder::global.at(i).size(); j++) {
- recorder::action *ra = recorder::global.at(i).at(j);
-
- if (ra->chan == pParent->chan->index) {
-
- /* don't show actions > than the grey area */
-
- if (recorder::frames.at(i) > G_Mixer.totalFrames)
- continue;
-
- /* skip the killchan actions in a singlepress channel. They cannot be recorded
- * in such mode, but they can exist if you change from another mode to singlepress */
-
- if (ra->type == ACTION_KILLCHAN && ch->mode == SINGLE_PRESS)
- continue;
-
- /* also filter out ACTION_KEYREL: it's up to gAction to find the other piece
- * (namely frame_b) */
-
- if (ra->type & (ACTION_KEYPRESS | ACTION_KILLCHAN)) {
- int ax = x+(ra->frame/pParent->zoom);
- gAction *a = new gAction(
- ax, // x
- y+4, // y
- h()-8, // h
- ra->frame, // frame_a
- i, // n. of recordings
- pParent, // pointer to the pParent window
- ch, // pointer to SampleChannel
- false, // record = false: don't record it, we are just displaying it!
- ra->type); // type of action
- add(a);
- }
- }
+ recorder::action *action = recorder::global.at(i).at(j);
+
+ /* Don't show actions:
+ - that don't belong to the displayed channel (!= pParent->chan->index);
+ - that are covered by the grey area (> G_Mixer.totalFrames);
+ - of type ACTION_KILLCHAN in a SINGLE_PRESS channel. They cannot be
+ recorded in such mode, but they can exist if you change from another
+ mode to singlepress;
+ - of type ACTION_KEYREL in a SINGLE_PRESS channel. It's up to gAction to
+ find the other piece (namely frame_b)
+ - not of types ACTION_KEYPRESS | ACTION_KEYREL | ACTION_KILLCHAN */
+
+ if ((action->chan != pParent->chan->index) ||
+ (recorder::frames.at(i) > G_Mixer.totalFrames) ||
+ (action->type == ACTION_KILLCHAN && ch->mode == SINGLE_PRESS) ||
+ (action->type == ACTION_KEYREL && ch->mode == SINGLE_PRESS) ||
+ (action->type & ~(ACTION_KEYPRESS | ACTION_KEYREL | ACTION_KILLCHAN))
+ )
+ continue;
+
+ int ax = x + (action->frame / pParent->zoom);
+ gAction *a = new gAction(
+ ax, // x
+ y + 4, // y
+ h() - 8, // h
+ action->frame, // frame_a
+ i, // n. of recordings
+ pParent, // pointer to the pParent window
+ ch, // pointer to SampleChannel
+ false, // record = false: don't record it, we are just displaying it!
+ action->type); // type of action
+ add(a);
}
}
end(); // mandatory when you add widgets to a fl_group, otherwise mega malfunctions
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-gAction *gActionChannel::getSelectedAction() {
+gAction *gActionChannel::getSelectedAction()
+{
for (int i=0; i<children(); i++) {
int action_x = ((gAction*)child(i))->x();
int action_w = ((gAction*)child(i))->w();
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-void gActionChannel::updateActions() {
-
+void gActionChannel::updateActions()
+{
/* when zooming, don't delete and re-add actions, just MOVE them. This
* function shifts the action by a zoom factor. Those singlepress are
* stretched, as well */
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-void gActionChannel::draw() {
-
+void gActionChannel::draw()
+{
/* draw basic boundaries (+ beat bars) and hide the unused area. Then
* draw the children (the actions) */
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-int gActionChannel::handle(int e) {
-
+int gActionChannel::handle(int e)
+{
int ret = Fl_Group::handle(e);
/* do nothing if the widget is deactivated. It could happen for loopmode
switch (e) {
case FL_DRAG: {
- if (selected != NULL) { // if you don't drag an empty area
- /* if onLeftEdge o onRightEdge are true it means that you're resizing
- * an action. Otherwise move the widget. */
+ if (selected == NULL) { // if you drag an empty area
+ ret = 1;
+ break;
+ }
- if (selected->onLeftEdge || selected->onRightEdge) {
+ /* if onLeftEdge o onRightEdge are true it means that you're resizing
+ * an action. Otherwise move the widget. */
- /* some checks: a) cannot resize an action < N pixels, b) no beyond zero,
- * c) no beyond bar maxwidth. Checks for overlap are done in FL_RELEASE */
+ if (selected->onLeftEdge || selected->onRightEdge) {
- if (selected->onRightEdge) {
+ /* some checks: a) cannot resize an action < N pixels, b) no beyond zero,
+ * c) no beyond bar maxwidth. Checks for overlap are done in FL_RELEASE */
- int aw = Fl::event_x()-selected->x();
- int ah = selected->h();
+ if (selected->onRightEdge) {
- if (Fl::event_x() < selected->x()+gAction::MIN_WIDTH)
- aw = gAction::MIN_WIDTH;
- else
- if (Fl::event_x() > pParent->coverX)
- aw = pParent->coverX-selected->x();
+ int aw = Fl::event_x()-selected->x();
+ int ah = selected->h();
- selected->size(aw, ah);
- }
- else {
+ if (Fl::event_x() < selected->x()+gAction::MIN_WIDTH)
+ aw = gAction::MIN_WIDTH;
+ else
+ if (Fl::event_x() > pParent->coverX)
+ aw = pParent->coverX-selected->x();
- int ax = Fl::event_x();
- int ay = selected->y();
- int aw = selected->x()-Fl::event_x()+selected->w();
- int ah = selected->h();
+ selected->size(aw, ah);
+ }
+ else {
- if (Fl::event_x() < x()) {
- ax = x();
- aw = selected->w()+selected->x()-x();
- }
- else
- if (Fl::event_x() > selected->x()+selected->w()-gAction::MIN_WIDTH) {
- ax = selected->x()+selected->w()-gAction::MIN_WIDTH;
- aw = gAction::MIN_WIDTH;
- }
- selected->resize(ax, ay, aw, ah);
+ int ax = Fl::event_x();
+ int ay = selected->y();
+ int aw = selected->x()-Fl::event_x()+selected->w();
+ int ah = selected->h();
+
+ if (Fl::event_x() < x()) {
+ ax = x();
+ aw = selected->w()+selected->x()-x();
}
+ else
+ if (Fl::event_x() > selected->x()+selected->w()-gAction::MIN_WIDTH) {
+ ax = selected->x()+selected->w()-gAction::MIN_WIDTH;
+ aw = gAction::MIN_WIDTH;
+ }
+ selected->resize(ax, ay, aw, ah);
}
+ }
- /* move the widget around */
+ /* move the widget around */
+ else {
+ int real_x = Fl::event_x() - actionPickPoint;
+ if (real_x < x()) // don't go beyond the left border
+ selected->position(x(), selected->y());
+ else
+ if (real_x+selected->w() > pParent->coverX+x()) // don't go beyond the right border
+ selected->position(pParent->coverX+x()-selected->w(), selected->y());
else {
- int real_x = Fl::event_x() - actionPickPoint;
- if (real_x < x()) // don't go beyond the left border
- selected->position(x(), selected->y());
- else
- if (real_x+selected->w() > pParent->coverX+x()) // don't go beyond the right border
- selected->position(pParent->coverX+x()-selected->w(), selected->y());
- else {
- if (pParent->gridTool->isOn()) {
- int snpx = pParent->gridTool->getSnapPoint(real_x-x()) + x() -1;
- selected->position(snpx, selected->y());
- }
- else
- selected->position(real_x, selected->y());
+ if (pParent->gridTool->isOn()) {
+ int snpx = pParent->gridTool->getSnapPoint(real_x-x()) + x() -1;
+ selected->position(snpx, selected->y());
}
+ else
+ selected->position(real_x, selected->y());
}
- redraw();
}
+ redraw();
ret = 1;
break;
}
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-bool gActionChannel::actionCollides(int frame) {
-
+bool gActionChannel::actionCollides(int frame)
+{
/* if SINGLE_PRESS we check that the tail (frame_b) of the action doesn't
* overlap the head (frame) of the new one. First the general case, yet. */
bool collision = false;
for (int i=0; i<children() && !collision; i++)
- if ( ((gAction*)child(i))->frame_a == frame)
+ if (((gAction*) child(i))->frame_a == frame)
collision = true;
if (ch->mode == SINGLE_PRESS) {
for (int i=0; i<children() && !collision; i++) {
- gAction *c = ((gAction*)child(i));
+ gAction *c = ((gAction*) child(i));
if (frame <= c->frame_b && frame >= c->frame_a)
collision = true;
}
}
-/* ------------------------------------------------------------------ */
-/* ------------------------------------------------------------------ */
-/* ------------------------------------------------------------------ */
-
-
-const int gAction::MIN_WIDTH = 8;
-
-
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
/** TODO - index is useless?
}
-/* ------------------------------------------------------------------ */
-
+/* -------------------------------------------------------------------------- */
-void gAction::draw() {
+void gAction::draw()
+{
int color;
if (selected) /// && gActionChannel !disabled
color = COLOR_BD_1;
}
-/* ------------------------------------------------------------------ */
-
+/* -------------------------------------------------------------------------- */
-int gAction::handle(int e) {
+int gAction::handle(int e)
+{
/* ret = 0 sends the event to the parent window. */
int ret = 0;
}
-/* ------------------------------------------------------------------ */
-
+/* -------------------------------------------------------------------------- */
-void gAction::addAction() {
+void gAction::addAction()
+{
/* always check frame parity */
if (frame_a % 2 != 0)
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-void gAction::delAction() {
-
+void gAction::delAction()
+{
/* if SINGLE_PRESS you must delete both the keypress and the keyrelease
* actions. */
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-void gAction::moveAction(int frame_a) {
-
+void gAction::moveAction(int frame_a)
+{
/* easy one: delete previous action and record the new ones. As usual,
* SINGLE_PRESS requires two jobs. If frame_a is valid, use that frame
* value. */
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-int gAction::absx() {
+int gAction::absx()
+{
return x() - parent->ac->x();
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-int gAction::xToFrame_a() {
+int gAction::xToFrame_a()
+{
return (absx()) * parent->zoom;
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-int gAction::xToFrame_b() {
+int gAction::xToFrame_b()
+{
return (absx() + w()) * parent->zoom;
}
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* ge_actionChannel
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
+
#ifndef GE_ACTIONCHANNEL_H
#define GE_ACTIONCHANNEL_H
+
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include "../../utils/gui_utils.h"
#include "ge_actionWidget.h"
-class gAction : public Fl_Box {
-
+class gAction : public Fl_Box
+{
private:
bool selected;
char type; // type of action
public:
+
gAction(int x, int y, int h, int frame_a, unsigned index,
gdActionEditor *parent, class SampleChannel *ch, bool record,
char type);
bool onRightEdge;
bool onLeftEdge;
- static const int MIN_WIDTH;
+ static const int MIN_WIDTH = 8;
};
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-class gActionChannel : public gActionWidget {
+class gActionChannel : public gActionWidget
+{
private:
bool actionCollides(int frame);
public:
+
gActionChannel(int x, int y, gdActionEditor *pParent, class SampleChannel *ch);
void draw();
int handle(int e);
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* gd_browser
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
#include <limits.h>
#include "../../core/const.h"
#include "../../utils/utils.h"
+#include "../../utils/string.h"
#include "../../utils/log.h"
+#include "../dialogs/gd_browser.h"
#include "ge_browser.h"
-gBrowser::gBrowser(int x, int y, int w, int h, const char *L)
- : Fl_Hold_Browser(x, y, w, h, L)
+gBrowser::gBrowser(int x, int y, int w, int h)
+ : Fl_File_Browser(x, y, w, h)
{
box(G_BOX);
textsize(GUI_FONT_SIZE_BASE);
textcolor(COLOR_TEXT_0);
selection_color(COLOR_BG_1);
color(COLOR_BG_0);
+ type(FL_SELECT_BROWSER);
this->scrollbar.color(COLOR_BG_0);
this->scrollbar.selection_color(COLOR_BG_1);
this->hscrollbar.selection_color(COLOR_BG_1);
this->hscrollbar.labelcolor(COLOR_BD_1);
this->hscrollbar.slider(G_BOX);
-}
-
-
-/* ------------------------------------------------------------------ */
-
-
-gBrowser::~gBrowser() {}
-
-
-/* ------------------------------------------------------------------ */
-
-void gBrowser::init(const char *init_path) {
-
- gLog("[gBrowser] init path = '%s'\n", init_path);
-
- if (init_path == NULL || !gIsDir(init_path)) {
-#if defined(__linux__) || defined(__APPLE__)
- path_obj->value("/home");
-#elif defined(_WIN32)
-
- /* SHGetFolderPath is deprecated. We should use SHGetKnownFolderPath
- * but that would break compatibility with XP. On Vista, GetFolderPath
- * is a wrapper of GetKnownFolderPath, so no problem. */
-
- char winRoot[1024];
- SHGetFolderPath(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, winRoot); // si parte dal Desktop
- path_obj->value(winRoot);
-#endif
- gLog("[gBrowser] init_path null or invalid, using default\n");
- }
- else
- path_obj->value(init_path);
-
- refresh();
- sort();
+ take_focus(); // let it have focus on startup
}
-/* ------------------------------------------------------------------ */
-
-
-void gBrowser::refresh() {
- DIR *dp;
- struct dirent *ep;
- dp = opendir(path_obj->value());
- if (dp != NULL) {
- while ((ep = readdir(dp))) {
-
- /* skip:
- * - "." e ".."
- * - hidden files */
-
- if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
- if (ep->d_name[0] != '.') {
-
- /* is it a folder? add square brackets. Is it a file? Append
- * a '/' (on Windows seems useless, though) */
-
- std::string file = path_obj->value();
- file.insert(file.size(), gGetSlash());
- file += ep->d_name;
-
- if (gIsDir(file.c_str())) {
- char name[PATH_MAX];
- sprintf(name, "@b[%s]", ep->d_name);
- add(name);
- }
- else
- if (gIsProject(file.c_str())) {
- char name[PATH_MAX];
- sprintf(name, "@i@b%s", ep->d_name);
- add(name);
- }
- else
- add(ep->d_name);
- }
- }
- }
- closedir(dp);
- }
- else
- gLog("[gBrowser] Couldn't open the directory '%s'\n", path_obj->value());
-}
+/* -------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------ */
+void gBrowser::loadDir(const string &dir)
+{
+ currentDir = dir;
+ load(currentDir.c_str());
+ /* hide "../", it just screws up things */
-void gBrowser::sort() {
- for (int t=1; t<=size(); t++)
- for (int r=t+1; r<=size(); r++)
- if (strcmp(text(t), text(r)) > 0)
- swap(t,r);
+ if (text(1) != NULL && strcmp(text(1), "../") == 0)
+ remove(1);
}
-/* ------------------------------------------------------------------ */
-
-
-void gBrowser::up_dir() {
-
- /* updir = remove last folder from the path. Start from strlen(-1) to
- * skip the trailing slash */
-
- int i = strlen(path_obj->value())-1;
+/* -------------------------------------------------------------------------- */
- /* on Windows an updir from the path "X:\" (3 chars long) must redirect
- * to the list of available devices. */
-
-#if defined(_WIN32)
- if (i <= 3 || !strcmp(path_obj->value(), "All drives")) {
- path_obj->value("All drives");
- showDrives();
- return;
- }
- else {
- while (i >= 0) {
- if (path_obj->value()[i] == '\\')
- break;
- i--;
- }
-
- /* delete the last part of the string, from i to len-i, ie everything
- * after the "/" */
-
- std::string tmp = path_obj->value();
- tmp.erase(i, tmp.size()-i);
-
- /* if tmp.size == 2 we have something like 'C:'. Add a trailing
- * slash */
-
- if (tmp.size() == 2)
- tmp += "\\";
-
- path_obj->value(tmp.c_str());
- refresh();
- }
-#elif defined(__linux__) || defined (__APPLE__)
- while (i >= 0) {
- if (path_obj->value()[i] == '/')
+int gBrowser::handle(int e)
+{
+ int ret = Fl_File_Browser::handle(e);
+ switch (e) {
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ ret = 1; // enables receiving Keyboard events
break;
- i--;
- }
-
- /* i == 0 means '/', the root dir. It's meaningless to go updir */
-
- if (i==0)
- path_obj->value("/");
- else {
-
- /* delete the last part of the string, from i to len-i, ie everything
- * after the "/" */
-
- std::string tmp = path_obj->value();
- tmp.erase(i, tmp.size()-i);
- path_obj->value(tmp.c_str());
- }
- refresh();
-#endif
+ case FL_KEYDOWN: // keyboard
+ if (Fl::event_key(FL_Down))
+ select(value() + 1);
+ else
+ if (Fl::event_key(FL_Up))
+ select(value() - 1);
+ else
+ if (Fl::event_key(FL_Enter))
+ ((gdBaseBrowser*) parent())->fireCallback();
+ ret = 1;
+ break;
+ case FL_PUSH: // mouse
+ if (Fl::event_clicks() > 0) // double click
+ ((gdBaseBrowser*) parent())->fireCallback();
+ ret = 1;
+ break;
+ case FL_RELEASE: // mouse
+ /* nasty trick to keep the selection on mouse release */
+ if (value() > 1) {
+ select(value() - 1);
+ select(value() + 1);
+ }
+ else {
+ select(value() + 1);
+ select(value() - 1);
+ }
+ ret = 1;
+ break;
+ }
+ return ret;
}
+/* -------------------------------------------------------------------------- */
-/* ------------------------------------------------------------------ */
-
-void gBrowser::down_dir(const char *path) {
- path_obj->value(path);
- refresh();
+string gBrowser::getCurrentDir()
+{
+ return normalize(gGetRealPath(currentDir));
}
-/* ------------------------------------------------------------------ */
-
-
-const char *gBrowser::get_selected_item() {
-
- /* click on an empty line */
-
- if (text(value()) == NULL)
- return NULL;
-
- selected_item = text(value());
-
- /* @ = formatting marks.
- * @b = bold, i.e. a directory. Erease '@b[' and ']' */
-
- if (selected_item[0] == '@') {
- if (selected_item[1] == 'b') {
- selected_item.erase(0, 3);
- selected_item.erase(selected_item.size()-1, 1);
- }
- else
- if (selected_item[1] == 'i')
- selected_item.erase(0, 4);
- }
+/* -------------------------------------------------------------------------- */
-#if defined(__linux__) || defined(__APPLE__)
- /* add path to file name, to get an absolute path. Avoid double
- * slashes like '//' */
-
- if (strcmp("/", path_obj->value()))
- selected_item.insert(0, "/");
-
- selected_item.insert(0, path_obj->value());
- return selected_item.c_str();
-#elif defined(_WIN32)
-
- /* if path is 'All drives' we are in the devices list and the user
- * has clicked on a device such as 'X:\' */
+string gBrowser::getSelectedItem(bool fullPath)
+{
+ if (!fullPath) // no full path requested? return the selected text
+ return normalize(text(value()));
+ else
+ if (value() == 0) // no rows selected? return current directory
+ return normalize(currentDir);
+ else
+ return normalize(gGetRealPath(currentDir + G_SLASH + normalize(text(value()))));
+}
- if (strcmp(path_obj->value(), "All drives") == 0)
- return selected_item.c_str();
- else {
- /* add '\' if the path is like 'X:\' */
+/* -------------------------------------------------------------------------- */
- if (strlen(path_obj->value()) > 3) /// shouln't it be == 3?
- selected_item.insert(0, "\\");
- selected_item.insert(0, path_obj->value());
- return selected_item.c_str();
- }
-#endif
+void gBrowser::preselect(int pos, int line)
+{
+ position(pos);
+ select(line);
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
-#ifdef _WIN32
-void gBrowser::showDrives() {
-
- /* GetLogicalDriveStrings fills drives like that:
- *
- * a:\[null]b:\[null]c:\[null]...[null][null]
- *
- * where [null] stands for \0. */
+string gBrowser::normalize(const string &s)
+{
+ string out = s;
- char drives[64];
- char *i = drives; // pointer to 0th element in drives
- GetLogicalDriveStrings(64, drives);
+ /* our crappy version of Clang doesn't seem to support std::string::back() */
- /* code stolen from the web, still unknown. (Jan 09, 2012). */
+#ifdef __APPLE__
+ if (out[out.length() - 1] == G_SLASH)
+#else
+ if (out.back() == G_SLASH)
+#endif
- while (*i) {
- add(i);
- i = &i[strlen(i) + 1];
- }
+ out = out.substr(0, out.size()-1);
+ return out;
}
-
-#endif
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
* ge_browser
*
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
+
#ifndef GE_BROWSER_H
#define GE_BROWSER_H
#include <FL/Fl.H>
-#include <FL/Fl_Hold_Browser.H>
+#include <FL/Fl_File_Browser.H>
#include <string>
#include "ge_mixed.h"
-class gBrowser : public Fl_Hold_Browser {
+
+using std::string;
+
+
+class gBrowser : public Fl_File_Browser
+{
+private:
+
+ string currentDir;
+
+ /* normalize
+ * Make sure the string never ends with a trailing slash. */
+
+ string normalize(const string &s);
+
public:
- gBrowser(int x, int y, int w, int h, const char *L=0);
- ~gBrowser();
- void init(const char *init_path=NULL);
- void refresh();
- void sort();
- void up_dir();
- void down_dir(const char *path);
- const char *get_selected_item();
- /* path_obj
- * the actual path*/
+ gBrowser(int x, int y, int w, int h);
- class gInput *path_obj;
+ /* init
+ * Initialize browser and show 'dir' as initial directory. */
- /* selected_item
- * choosen item */
+ void loadDir(const string &dir);
- std::string selected_item;
+ /* getSelectedItem
+ * Return the full path or just the displayed name of the i-th selected item.
+ * Always with the trailing slash! */
-#ifdef _WIN32
-private:
+ string getSelectedItem(bool fullPath=true);
- /* showDrives [WIN32 only]
- * lists all the available drivers */
+ string getCurrentDir();
- void showDrives();
-#endif
+ void preselect(int position, int line);
+
+ int handle(int e);
};
#endif
len--;
}
}
- else
+ else {
out = "";
- copy_label(out.c_str());
+ }
+ copy_label(out.c_str());
}
#include "../../core/midiChannel.h"
#include "../../glue/glue.h"
#include "../../glue/channel.h"
+#include "../../glue/storage.h"
#include "../../utils/gui_utils.h"
#include "../dialogs/gd_mainWindow.h"
#include "../dialogs/gd_keyGrabber.h"
void gSampleChannel::openBrowser(int type)
{
- const char *title = "";
+ gWindow *childWin = NULL;
switch (type) {
case BROWSER_LOAD_SAMPLE:
- title = "Browse Sample";
+ childWin = new gdLoadBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Browse sample",
+ G_Conf.samplePath.c_str(), glue_loadSample, ch);
break;
case BROWSER_SAVE_SAMPLE:
- title = "Save Sample";
- break;
- case -1:
- title = "Edit Sample";
+ childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Save sample", \
+ G_Conf.samplePath.c_str(), "", glue_saveSample, ch);
break;
}
- gWindow *childWin = new gdBrowser(title, G_Conf.samplePath.c_str(), ch, type);
- gu_openSubWindow(mainWin, childWin, WID_FILE_BROWSER);
+ if (childWin)
+ gu_openSubWindow(mainWin, childWin, WID_FILE_BROWSER);
}
return;
va_list args;
va_start(args, format);
- if (mode == LOG_MODE_FILE && stat == true)
+ if (mode == LOG_MODE_FILE && stat == true) {
vfprintf(f, format, args);
+#ifdef _WIN32
+ fflush(f);
+#endif
+ }
else
vprintf(format, args);
va_end(args);
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * utils
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include "string.h"
+#include <limits.h>
+
+
+using std::string;
+
+
+string gGetRealPath(const string &path)
+{
+ string out = "";
+
+#if defined(__linux__) || defined(__APPLE__)
+
+ char *buf = realpath(path.c_str(), NULL);
+
+#else // Windows
+
+ char *buf = _fullpath(NULL, path.c_str(), PATH_MAX);
+
+#endif
+
+ if (buf) {
+ out = buf;
+ free(buf);
+ }
+ return out;
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * utils
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef __UTILS_STRING_H__
+#define __UTILS_STRING_H__
+
+
+#include <string>
+#include <cstdio>
+#include <vector>
+#include "log.h"
+
+
+using std::string;
+
+
+string gGetRealPath(const string &path);
+
+#endif
* -------------------------------------------------------------------------- */
-#include "utils.h"
#if defined(_WIN32) // getcwd (unix) or __getcwd (win)
#include <direct.h>
#include <windows.h>
#include <libgen.h> // basename unix
#include <pwd.h> // getpwuid
#endif
+#include "../core/const.h"
+#include "utils.h"
using std::string;
using std::vector;
-bool gFileExists(const char *filename) {
+bool gFileExists(const char *filename)
+{
FILE *fh = fopen(filename, "rb");
if (!fh) {
return 0;
}
+bool gFileExists(const string &filename)
+{
+ return gFileExists(filename.c_str());
+}
+
+
/* -------------------------------------------------------------------------- */
}
+bool gIsDir(const string &path)
+{
+ return gIsDir(path.c_str());
+}
+
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-/* TODO - avoid this shit, just wrap the other call */
-string gBasename(const char *path)
-{
- string out = path;
- out.erase(0, out.find_last_of(gGetSlash().c_str())+1);
- return out;
-}
string gBasename(const string &s)
{
string out = s;
- out.erase(0, out.find_last_of(gGetSlash().c_str())+1);
+ out.erase(0, out.find_last_of(G_SLASH_STR) + 1);
return out;
}
/* -------------------------------------------------------------------------- */
-string gDirname(const char *path)
+string gDirname(const string &path)
{
+ if (path.empty())
+ return "";
string out = path;
- out.erase(out.find_last_of(gGetSlash().c_str()));
+ out.erase(out.find_last_of(G_SLASH_STR));
return out;
}
/* -------------------------------------------------------------------------- */
-bool gIsProject(const char *path)
+bool gIsProject(const string &path)
{
/** FIXME - checks too weak */
- if (gGetExt(path) == "gprj" && gDirExists(path))
+ if (gGetExt(path.c_str()) == "gprj" && gDirExists(path))
return 1;
return 0;
}
}
-/* -------------------------------------------------------------------------- */
-
-
-string gGetSlash()
-{
-#if defined(_WIN32)
- return "\\";
-#else
- return "/";
-#endif
-}
-
/* -------------------------------------------------------------------------- */
bool gFileExists(const char *path);
+bool gFileExists(const string &path);
bool gDirExists(const char *path);
bool gDirExists(const string &path);
bool gIsDir(const char *path);
+bool gIsDir(const string &path);
-bool gIsProject(const char *path);
+bool gIsProject(const string &path);
bool gIsPatch(const char *path);
+bool gIsPatch(const string &path);
bool gMkdir(const char *path);
bool gMkdir(const string &path);
-string gBasename(const char *path);
string gBasename(const string &s);
string gReplace(string in, const string& search, const string& replace);
-string gDirname(const char *path);
+string gDirname(const string &s);
string gTrim(const char *path);
string gTrim(const string &s);
string gGetProjectName(const char *path); // TODO - useless!
-string gGetSlash();
-
string gItoa(int i);
void gSplit(string in, string sep, vector<string> *v);
-#ifdef RUN_TESTS_WITH_LOCAL_FILES
-
#include "../src/core/wave.h"
#include "catch.hpp"
SECTION("test read & write")
{
- REQUIRE(w1.open("test.wav") == 1);
+ REQUIRE(w1.open("tests/resources/test.wav") == 1);
REQUIRE(w1.readData() == 1);
- REQUIRE(w1.rate() == 11025);
- REQUIRE(w1.channels() == 2);
+ REQUIRE(w1.rate() == 44100);
+ REQUIRE(w1.channels() == 1);
REQUIRE(w1.basename() == "test");
REQUIRE(w1.extension() == "wav");
REQUIRE(w1.writeData("test-write.wav") == true);
Wave w2(w1);
REQUIRE(w2.size == w1.size);
REQUIRE(w2.isLogical == true);
- //REQUIRE(w2.rate() == 11025); // WHAT THE FUCK???
- REQUIRE(w2.channels() == 2);
+ //REQUIRE(w2.rate() == 44100); // WHAT THE FUCK???
+ REQUIRE(w2.channels() == 1);
REQUIRE(w2.writeData("test-write.wav") == true);
}
REQUIRE(w3.writeData("test-write.wav") == true);
}
}
-
-#endif // #ifdef RUN_TESTS_WITH_LOCAL_FILES