summaryrefslogtreecommitdiff
path: root/src/gui/elems/ge_keyboard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/elems/ge_keyboard.cpp')
-rw-r--r--src/gui/elems/ge_keyboard.cpp366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/gui/elems/ge_keyboard.cpp b/src/gui/elems/ge_keyboard.cpp
new file mode 100644
index 0000000..24d47bd
--- /dev/null
+++ b/src/gui/elems/ge_keyboard.cpp
@@ -0,0 +1,366 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * gg_keyboard
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2015 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 "../../core/mixer.h"
+#include "../../core/conf.h"
+#include "../../core/const.h"
+#include "../../core/patch.h"
+#include "../../core/channel.h"
+#include "../../core/sampleChannel.h"
+#include "../../glue/glue.h"
+#include "../../utils/log.h"
+#include "../dialogs/gd_browser.h"
+#include "../dialogs/gd_mainWindow.h"
+#include "../dialogs/gd_editor.h"
+#include "../dialogs/gd_warnings.h"
+#include "ge_channel.h"
+#include "ge_sampleChannel.h"
+#include "ge_keyboard.h"
+
+
+extern Mixer G_Mixer;
+extern Conf G_Conf;
+extern Patch G_Patch;
+extern gdMainWindow *mainWin;
+
+
+int gKeyboard::indexColumn = 0;
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gKeyboard::gKeyboard(int X, int Y, int W, int H)
+: Fl_Scroll (X, Y, W, H),
+ bckspcPressed(false),
+ endPressed (false),
+ spacePressed (false),
+ addColumnBtn (NULL)
+{
+ color(COLOR_BG_MAIN);
+ type(Fl_Scroll::BOTH_ALWAYS);
+ scrollbar.color(COLOR_BG_0);
+ scrollbar.selection_color(COLOR_BG_1);
+ scrollbar.labelcolor(COLOR_BD_1);
+ scrollbar.slider(G_BOX);
+ hscrollbar.color(COLOR_BG_0);
+ hscrollbar.selection_color(COLOR_BG_1);
+ hscrollbar.labelcolor(COLOR_BD_1);
+ hscrollbar.slider(G_BOX);
+
+ addColumnBtn = new gClick(8, y(), 200, 20, "Add new column");
+ addColumnBtn->callback(cb_addColumn, (void*) this);
+ add(addColumnBtn);
+
+ init();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::init()
+{
+ /* add 6 empty columns as init layout */
+
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::freeChannel(gChannel *gch)
+{
+ gch->reset();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::deleteChannel(gChannel *gch)
+{
+ for (unsigned i=0; i<columns.size; i++) {
+ int k = columns.at(i)->find(gch);
+ if (k != columns.at(i)->children()) {
+ columns.at(i)->deleteChannel(gch);
+ return;
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::updateChannel(gChannel *gch)
+{
+ gch->update();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::organizeColumns()
+{
+ /* if only one column exists don't cleanup: the initial column must
+ * stay here. */
+
+ if (columns.size == 1)
+ return;
+
+ /* otherwise delete all empty columns */
+ /** FIXME - this for loop might not work correctly! */
+
+ for (unsigned i=columns.size-1; i>=1; i--) {
+ if (columns.at(i)->isEmpty()) {
+ //Fl::delete_widget(columns.at(i));
+ delete columns.at(i);
+ columns.del(i);
+ }
+ }
+
+ /* compact column, avoid empty spaces */
+
+ for (unsigned i=1; i<columns.size; i++)
+ columns.at(i)->position(columns.at(i-1)->x() + columns.at(i-1)->w() + 16, y());
+
+ addColumnBtn->position(columns.last()->x() + columns.last()->w() + 16, y());
+
+ redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::cb_addColumn(Fl_Widget *v, void *p) { ((gKeyboard*)p)->__cb_addColumn(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gChannel *gKeyboard::addChannel(int colIndex, Channel *ch, bool build)
+{
+ gColumn *col = getColumn(colIndex);
+
+ /* no column with index 'colIndex' found? Just create it and set its index
+ to 'colIndex'. */
+
+ if (!col) {
+ __cb_addColumn();
+ col = columns.last();
+ col->setIndex(colIndex);
+ gLog("[gKeyboard::addChannel] created new column with index=%d\n", colIndex);
+ }
+
+ gLog("[gKeyboard::addChannel] add to column with index = %d\n", col->getIndex());
+ return col->addChannel(ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::refreshColumns()
+{
+ for (unsigned i=0; i<columns.size; i++)
+ columns.at(i)->refreshChannels();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gColumn *gKeyboard::getColumn(int index)
+{
+ for (unsigned i=0; i<columns.size; i++)
+ if (columns.at(i)->getIndex() == index)
+ return columns.at(i);
+ return NULL;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int gKeyboard::handle(int e)
+{
+ int ret = Fl_Group::handle(e); // assume the buttons won't handle the Keyboard events
+ switch (e) {
+ case FL_FOCUS:
+ case FL_UNFOCUS: {
+ ret = 1; // enables receiving Keyboard events
+ break;
+ }
+ case FL_SHORTCUT: // in case widget that isn't ours has focus
+ case FL_KEYDOWN: // Keyboard key pushed
+ case FL_KEYUP: { // Keyboard key released
+
+ /* rewind session. Avoid retrigs */
+
+ if (e == FL_KEYDOWN) {
+ if (Fl::event_key() == FL_BackSpace && !bckspcPressed) {
+ bckspcPressed = true;
+ glue_rewindSeq();
+ ret = 1;
+ break;
+ }
+ else if (Fl::event_key() == FL_End && !endPressed) {
+ endPressed = true;
+ glue_startStopInputRec(false); // update gui
+ ret = 1;
+ break;
+ }
+ else if (Fl::event_key() == FL_Enter && !enterPressed) {
+ enterPressed = true;
+ glue_startStopActionRec();
+ ret = 1;
+ break;
+ }
+ else if (Fl::event_key() == ' ' && !spacePressed) {
+ spacePressed = true;
+ G_Mixer.running ? glue_stopSeq() : glue_startSeq(); // TODO - glue_startStopSeq, no core logic here
+ ret = 1;
+ break;
+ }
+ }
+ else if (e == FL_KEYUP) {
+ if (Fl::event_key() == FL_BackSpace)
+ bckspcPressed = false;
+ else if (Fl::event_key() == FL_End)
+ endPressed = false;
+ else if (Fl::event_key() == ' ')
+ spacePressed = false;
+ else if (Fl::event_key() == FL_Enter)
+ enterPressed = false;
+ }
+
+ /* Walk button arrays, trying to match button's label with the Keyboard event.
+ * If found, set that button's value() based on up/down event,
+ * and invoke that button's callback() */
+
+ for (unsigned i=0; i<columns.size; i++)
+ for (int k=1; k<columns.at(i)->children(); k++)
+ ret &= ((gChannel*)columns.at(i)->child(k))->keyPress(e);
+ break;
+ }
+ }
+ return ret;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::clear()
+{
+ for (unsigned i=0; i<columns.size; i++)
+ delete columns.at(i);
+ columns.clear();
+ indexColumn = 0; // new columns will start from index=0
+ addColumnBtn->position(8, y());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::setChannelWithActions(gSampleChannel *gch)
+{
+ if (gch->ch->hasActions)
+ gch->addActionButton();
+ else
+ gch->delActionButton();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::printChannelMessage(int res)
+{
+ if (res == SAMPLE_NOT_VALID)
+ gdAlert("This is not a valid WAVE file.");
+ else if (res == SAMPLE_MULTICHANNEL)
+ gdAlert("Multichannel samples not supported.");
+ else if (res == SAMPLE_WRONG_BIT)
+ gdAlert("This sample has an\nunsupported bit-depth (> 32 bit).");
+ else if (res == SAMPLE_WRONG_ENDIAN)
+ gdAlert("This sample has a wrong\nbyte order (not little-endian).");
+ else if (res == SAMPLE_WRONG_FORMAT)
+ gdAlert("This sample is encoded in\nan unsupported audio format.");
+ else if (res == SAMPLE_READ_ERROR)
+ gdAlert("Unable to read this sample.");
+ else if (res == SAMPLE_PATH_TOO_LONG)
+ gdAlert("File path too long.");
+ else
+ gdAlert("Unknown error.");
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+void gKeyboard::__cb_addColumn()
+{
+ int colx;
+ int colxw;
+ int colw = 380;
+ if (columns.size == 0) {
+ colx = x() - xposition(); // mind the offset with xposition()
+ colxw = colx + colw;
+ }
+ else {
+ gColumn *prev = columns.last();
+ colx = prev->x()+prev->w() + 16;
+ colxw = colx + colw;
+ }
+
+ /* add gColumn to gKeyboard and to columns vector */
+
+ gColumn *gc = new gColumn(colx, y(), colw-20, 2000, indexColumn, this);
+ add(gc);
+ columns.add(gc);
+ indexColumn++;
+
+ /* move addColumn button */
+
+ addColumnBtn->position(colxw-4, y());
+ redraw();
+
+ gLog("[gKeyboard::__cb_addColumn] new column added (index = %d), total count=%d, addColumn(x)=%d\n",
+ gc->getIndex(), columns.size, addColumnBtn->x());
+}