summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Jonsson <spamatica@gmail.com>2011-04-16 18:40:54 +0000
committerRobert Jonsson <spamatica@gmail.com>2011-04-16 18:40:54 +0000
commit47f7c86b68c156a0dff15c0e2486371bc8a801f6 (patch)
tree2cc5e1c1fbae435cd68bbaa8553dbec22337dcc3
parentf644f66566e933364baa66c825799ab7de3b4bbe (diff)
added keymap
-rw-r--r--muse2/ChangeLog13
-rw-r--r--muse2/awl/sigedit.cpp13
-rw-r--r--muse2/awl/sigedit.h1
-rw-r--r--muse2/muse/CMakeLists.txt1
-rw-r--r--muse2/muse/dssihost.cpp12
-rw-r--r--muse2/muse/keyevent.cpp303
-rw-r--r--muse2/muse/keyevent.h97
-rw-r--r--muse2/muse/master/lmaster.cpp277
-rw-r--r--muse2/muse/master/lmaster.h30
-rw-r--r--muse2/muse/shortcuts.cpp5
-rw-r--r--muse2/muse/shortcuts.h3
-rw-r--r--muse2/muse/song.cpp14
-rw-r--r--muse2/muse/song.h1
-rw-r--r--muse2/muse/songfile.cpp5
14 files changed, 717 insertions, 58 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 3a160786..b73c40c7 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,16 @@
+16.04.2011:
+ - Added KeyList for keeping key change events and ability to edit it in
+ master list editor (rj)
+ - fixed stuff in master list editor (rj)
+ * editing tempo signature is now atleast working
+ * editing time position is now atleast working
+ * double clicking a line moves the playpointer to this position if we are not playing
+ * changed adding tempo/sig/key so they pick the postion from the play pointer instead
+ of just incrementing the time position, I can't fathom when that would be preferrable
+ (if there is a time, I'm sure someone will let me know :) )
+ - song changed not implemented yet
+ - undo/redo is not implemented
+ - prevented initialization crash for dssi, Tim, please have a look (rj)
15.04.2011:
- And while we're at it... Invert drum track 'slivers' in arranger parts. (Tim)
- Move part name text to bottom to accommodate drum 'slivers'.
diff --git a/muse2/awl/sigedit.cpp b/muse2/awl/sigedit.cpp
index 826182ca..460aafe4 100644
--- a/muse2/awl/sigedit.cpp
+++ b/muse2/awl/sigedit.cpp
@@ -58,6 +58,16 @@ bool SigEdit::event(QEvent* event)
if (event->type() == QEvent::KeyPress) {
QKeyEvent* ke = static_cast<QKeyEvent*>(event);
int segment = curSegment();
+ if (ke->key() == Qt::Key_Return)
+ {
+ int z, n;
+ sscanf(lineEdit()->text().toLatin1().data(), "%d/%d", &z, &n);
+ AL::TimeSignature sig(z, n);
+ _sig = sig;
+
+ emit returnPressed();
+ return true;
+ }
if (ke->key() == Qt::Key_Backtab) {
if (segment == 2) {
lineEdit()->setSelection(5, 2);
@@ -117,6 +127,7 @@ void SigEdit::setValue(const QString& s)
void SigEdit::updateValue()
{
+ //printf("updateValue\n");
char buffer[64];
sprintf(buffer, "%d/%d", _sig.z, _sig.n);
lineEdit()->setText(buffer);
@@ -160,7 +171,7 @@ void SigEdit::fixup(QString& input) const
QValidator::State SigEdit::validate(QString&,int&) const
{
// TODO
- // printf("validate\n");
+ //printf("validate\n");
return QValidator::Acceptable;
}
diff --git a/muse2/awl/sigedit.h b/muse2/awl/sigedit.h
index dd059ea2..d2494798 100644
--- a/muse2/awl/sigedit.h
+++ b/muse2/awl/sigedit.h
@@ -54,6 +54,7 @@ class SigEdit : public QAbstractSpinBox
signals:
void valueChanged(const AL::TimeSignature&);
+ void returnPressed();
public slots:
void setValue(const AL::TimeSignature&);
diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt
index 0877d025..2a630f84 100644
--- a/muse2/muse/CMakeLists.txt
+++ b/muse2/muse/CMakeLists.txt
@@ -94,6 +94,7 @@ file (GLOB core_source_files
helper.cpp
importmidi.cpp
key.cpp
+ keyevent.cpp
memory.cpp
midi.cpp
midictrl.cpp
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index aa18025d..49204780 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -1104,11 +1104,13 @@ bool DssiSynthIF::init(DssiSynth* s)
}
else if (LADSPA_IS_PORT_OUTPUT(pd))
{
- controlsOut[cop].idx = k;
- controls[cop].val = 0.0;
- controls[cop].tmpVal = 0.0;
- controls[cop].enCtrl = false;
- controls[cop].en2Ctrl = false;
+ controlsOut[cop].idx = k;
+ if (controls) {
+ controls[cop].val = 0.0;
+ controls[cop].tmpVal = 0.0;
+ controls[cop].enCtrl = false;
+ controls[cop].en2Ctrl = false;
+ }
#ifdef DSSI_DEBUG
printf("DssiSynthIF::init control output port:%d port idx:%d name:%s\n", cop, k, ld->PortNames[k]);
diff --git a/muse2/muse/keyevent.cpp b/muse2/muse/keyevent.cpp
new file mode 100644
index 00000000..de872c9c
--- /dev/null
+++ b/muse2/muse/keyevent.cpp
@@ -0,0 +1,303 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: key.cpp,v 1.7.2.7 2008/05/21 00:28:52 terminator356 Exp $
+//
+// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <stdio.h>
+#include <errno.h>
+#include <cmath>
+
+#include "key.h"
+#include "globals.h"
+#include "gconfig.h"
+#include "xml.h"
+#include "keyevent.h"
+
+KeyList keymap;
+
+//---------------------------------------------------------
+// KeyList
+//---------------------------------------------------------
+
+KeyList::KeyList()
+ {
+ _key = 0;
+ insert(std::pair<const unsigned, KeyEvent*> (MAX_TICK+1, new KeyEvent(_key, 0)));
+// _keySN = 1;
+ useList = true;
+ }
+
+//---------------------------------------------------------
+// add
+//---------------------------------------------------------
+
+void KeyList::add(unsigned tick, int key)
+ {
+ if (tick > MAX_TICK)
+ tick = MAX_TICK;
+ iKeyEvent e = upper_bound(tick);
+
+ if (tick == e->second->tick)
+ e->second->key = key;
+ else {
+ KeyEvent* ne = e->second;
+ KeyEvent* ev = new KeyEvent(ne->key, ne->tick);
+ ne->key = key;
+ ne->tick = tick;
+ insert(std::pair<const unsigned, KeyEvent*> (tick, ev));
+ }
+ }
+
+//---------------------------------------------------------
+// KeyList::dump
+//---------------------------------------------------------
+
+void KeyList::dump() const
+ {
+ printf("\nKeyList:\n");
+ for (ciKeyEvent i = begin(); i != end(); ++i) {
+ printf("%6d %06d key %6d\n",
+ i->first, i->second->tick, i->second->key);
+ }
+ }
+
+
+//---------------------------------------------------------
+// clear
+//---------------------------------------------------------
+
+void KeyList::clear()
+ {
+ for (iKeyEvent i = begin(); i != end(); ++i)
+ delete i->second;
+ KEYLIST::clear();
+ insert(std::pair<const unsigned, KeyEvent*> (MAX_TICK+1, new KeyEvent(0, 0)));
+// ++_keySN;
+ }
+
+//---------------------------------------------------------
+// key
+//---------------------------------------------------------
+
+int KeyList::key(unsigned tick) const
+ {
+ if (useList) {
+ ciKeyEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("no key at tick %d,0x%x\n", tick, tick);
+ return 1000;
+ }
+ return i->second->key;
+ }
+ else
+ return _key;
+ }
+
+//---------------------------------------------------------
+// del
+//---------------------------------------------------------
+
+void KeyList::del(unsigned tick)
+ {
+// printf("KeyList::del(%d)\n", tick);
+ iKeyEvent e = find(tick);
+ if (e == end()) {
+ printf("KeyList::del(%d): not found\n", tick);
+ return;
+ }
+ del(e);
+// ++_keySN;
+ }
+
+void KeyList::del(iKeyEvent e)
+ {
+ iKeyEvent ne = e;
+ ++ne;
+ if (ne == end()) {
+ printf("KeyList::del() HALLO\n");
+ return;
+ }
+ ne->second->key = e->second->key;
+ ne->second->tick = e->second->tick;
+ erase(e);
+// ++_keySN;
+ }
+
+//---------------------------------------------------------
+// change
+//---------------------------------------------------------
+
+void KeyList::change(unsigned tick, int newkey)
+ {
+ iKeyEvent e = find(tick);
+ e->second->key = newkey;
+// ++_keySN;
+ }
+
+//---------------------------------------------------------
+// setKey
+// called from transport window
+// & slave mode key changes
+//---------------------------------------------------------
+
+//void KeyList::setKey(unsigned tick, int newkey)
+// {
+// if (useList)
+// add(tick, newkey);
+// else
+// _key = newkey;
+// ++_keySN;
+// }
+
+//---------------------------------------------------------
+// addKey
+//---------------------------------------------------------
+
+void KeyList::addKey(unsigned t, int key)
+ {
+ add(t, key);
+// ++_keySN;
+ }
+
+//---------------------------------------------------------
+// delKey
+//---------------------------------------------------------
+
+void KeyList::delKey(unsigned tick)
+ {
+ del(tick);
+// ++_keySN;
+ }
+
+//---------------------------------------------------------
+// changeKey
+//---------------------------------------------------------
+
+//void KeyList::changeKey(unsigned tick, int newkey)
+// {
+// change(tick, newkey);
+// ++_keySN;
+// }
+
+//---------------------------------------------------------
+// setMasterFlag
+//---------------------------------------------------------
+
+bool KeyList::setMasterFlag(unsigned /*tick*/, bool val)
+ {
+ if (useList != val) {
+ useList = val;
+// ++_keySN;
+ return true;
+ }
+ return false;
+ }
+
+
+
+//---------------------------------------------------------
+// KeyList::write
+//---------------------------------------------------------
+
+void KeyList::write(int level, Xml& xml) const
+ {
+ xml.put(level++, "<keylist fix=\"%d\">", _key);
+ for (ciKeyEvent i = begin(); i != end(); ++i)
+ i->second->write(level, xml, i->first);
+ xml.tag(level, "/keylist");
+ }
+
+//---------------------------------------------------------
+// KeyList::read
+//---------------------------------------------------------
+
+void KeyList::read(Xml& xml)
+ {
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return;
+ case Xml::TagStart:
+ if (tag == "key") {
+ KeyEvent* t = new KeyEvent();
+ unsigned tick = t->read(xml);
+ iKeyEvent pos = find(tick);
+ if (pos != end())
+ erase(pos);
+ insert(std::pair<const int, KeyEvent*> (tick, t));
+ }
+ else
+ xml.unknown("keyList");
+ break;
+ case Xml::Attribut:
+ if (tag == "fix")
+ _key = xml.s2().toInt();
+ break;
+ case Xml::TagEnd:
+ if (tag == "keylist") {
+ //++_keySN;
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// KeyEvent::write
+//---------------------------------------------------------
+
+void KeyEvent::write(int level, Xml& xml, int at) const
+ {
+ xml.tag(level++, "key at=\"%d\"", at);
+ xml.intTag(level, "tick", tick);
+ xml.intTag(level, "val", key);
+ xml.tag(level, "/key");
+ }
+
+//---------------------------------------------------------
+// KeyEvent::read
+//---------------------------------------------------------
+
+int KeyEvent::read(Xml& xml)
+ {
+ int at = 0;
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return 0;
+ case Xml::TagStart:
+ if (tag == "tick")
+ tick = xml.parseInt();
+ else if (tag == "val")
+ key = xml.parseInt();
+ else
+ xml.unknown("KeyEvent");
+ break;
+ case Xml::Attribut:
+ if (tag == "at")
+ at = xml.s2().toInt();
+ break;
+ case Xml::TagEnd:
+ if (tag == "key") {
+ return at;
+ }
+ default:
+ break;
+ }
+ }
+ return 0;
+ }
+
+
+
diff --git a/muse2/muse/keyevent.h b/muse2/muse/keyevent.h
new file mode 100644
index 00000000..cf475a52
--- /dev/null
+++ b/muse2/muse/keyevent.h
@@ -0,0 +1,97 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: tempo.h,v 1.2.2.1 2006/09/19 19:07:09 spamatica Exp $
+//
+// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+//=========================================================
+#ifndef KEYEVENT_H
+#define KEYEVENT_H
+
+#include <map>
+
+#ifndef MAX_TICK
+#define MAX_TICK (0x7fffffff/100)
+#endif
+
+class Xml;
+
+//---------------------------------------------------------
+// Tempo Event
+//---------------------------------------------------------
+
+struct KeyEvent {
+ int key;
+ unsigned tick; // new tempo at tick
+ //unsigned frame; // precomputed time for tick in sec
+
+ int read(Xml&);
+ void write(int, Xml&, int) const;
+
+ KeyEvent() { }
+ KeyEvent(unsigned k, unsigned tk) {
+ key = k;
+ tick = tk;
+ //frame = 0;
+ }
+ };
+
+//---------------------------------------------------------
+// TempoList
+//---------------------------------------------------------
+
+typedef std::map<unsigned, KeyEvent*, std::less<unsigned> > KEYLIST;
+typedef KEYLIST::iterator iKeyEvent;
+typedef KEYLIST::const_iterator ciKeyEvent;
+typedef KEYLIST::reverse_iterator riKeyEvent;
+typedef KEYLIST::const_reverse_iterator criKeyEvent;
+
+class KeyList : public KEYLIST {
+// int _keySN; // serial no to track key changes
+ bool useList;
+ int _key; // key if not using key list
+
+ void add(unsigned tick, int tempo);
+ void change(unsigned tick, int newKey);
+ void del(iKeyEvent);
+ void del(unsigned tick);
+
+ public:
+
+ enum keyList {
+ keyC,
+ keyCis,
+ keyD,
+ keyDis,
+ keyE,
+ keyF,
+ keyFis,
+ keyG,
+ keyGis,
+ keyA,
+ keyB,
+ keyBes,
+ };
+
+
+ KeyList();
+ void clear();
+
+ void read(Xml&);
+ void write(int, Xml&) const;
+ void dump() const;
+
+ int key(unsigned tick) const;
+
+ //int keySN() const { return _keySN; }
+// void setKey(unsigned tick, int newKey);
+ void addKey(unsigned t, int newKey);
+ void delKey(unsigned tick);
+// void changeKey(unsigned tick, int newKey);
+ bool setMasterFlag(unsigned tick, bool val);
+ };
+
+extern KeyList keymap;
+
+
+#endif // KEYEVENT_H
diff --git a/muse2/muse/master/lmaster.cpp b/muse2/muse/master/lmaster.cpp
index 00a09d13..8b2d84a8 100644
--- a/muse2/muse/master/lmaster.cpp
+++ b/muse2/muse/master/lmaster.cpp
@@ -13,8 +13,8 @@
#include "song.h"
#include "globals.h"
#include "audio.h"
-///#include "posedit.h"
-///#include "sigedit.h"
+//#include "posedit.h"
+//#include "sigedit.h"
#include "shortcuts.h"
#include "debug.h"
@@ -30,6 +30,7 @@
#include <QToolBar>
#include <QToolButton>
#include <QTreeWidget>
+#include <QComboBox>
#define LMASTER_BEAT_COL 0
#define LMASTER_TIME_COL 1
@@ -37,6 +38,13 @@
#define LMASTER_VAL_COL 3
#define LMASTER_MSGBOX_STRING "MusE: List Editor"
+
+QStringList keyStrs = QStringList()
+ << "C" << "C#" << "D" << "D#"<< "E" << "F"
+ << "F#"<< "G"<< "G#"<< "A"<< "B"<< "B#";
+
+
+
//---------------------------------------------------------
// closeEvent
//---------------------------------------------------------
@@ -67,6 +75,7 @@ LMaster::LMaster()
pos_editor = 0;
editor = 0;
sig_editor = 0;
+ key_editor = 0;
editedItem = 0;
editingNewItem = false;
setWindowTitle(tr("MusE: Mastertrack"));
@@ -80,6 +89,7 @@ LMaster::LMaster()
menuEdit->addSeparator();
tempoAction = menuEdit->addAction(tr("Insert Tempo"));
signAction = menuEdit->addAction(tr("Insert Signature"));
+ keyAction = menuEdit->addAction(tr("Insert Key"));
posAction = menuEdit->addAction(tr("Edit Positon"));
valAction = menuEdit->addAction(tr("Edit Value"));
delAction = menuEdit->addAction(tr("Delete Event"));
@@ -87,12 +97,14 @@ LMaster::LMaster()
connect(tempoAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
connect(signAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
+ connect(keyAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
connect(posAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
connect(valAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
connect(delAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
signalMapper->setMapping(tempoAction, CMD_INSERT_TEMPO);
signalMapper->setMapping(signAction, CMD_INSERT_SIG);
+ signalMapper->setMapping(keyAction, CMD_INSERT_KEY);
signalMapper->setMapping(posAction, CMD_EDIT_BEAT);
signalMapper->setMapping(valAction, CMD_EDIT_VALUE);
signalMapper->setMapping(delAction, CMD_DELETE);
@@ -103,18 +115,19 @@ LMaster::LMaster()
tools = addToolBar(tr("Master tools"));
tools->addActions(undoRedo->actions());
- //QToolBar* edit = new QToolBar(this, "edit tools");
QToolBar* edit = addToolBar(tr("Edit tools"));
- //QToolButton* tempoButton = new QToolButton(edit);
QToolButton* tempoButton = new QToolButton();
- //QToolButton* timeSigButton = new QToolButton(edit);
QToolButton* timeSigButton = new QToolButton();
+ QToolButton* keyButton = new QToolButton();
tempoButton->setText(tr("Tempo"));
timeSigButton->setText(tr("Timesig"));
+ keyButton->setText(tr("Key"));
tempoButton->setToolTip(tr("new tempo"));
timeSigButton->setToolTip(tr("new signature"));
+ keyButton->setToolTip(tr("new key"));
edit->addWidget(tempoButton);
edit->addWidget(timeSigButton);
+ edit->addWidget(keyButton);
///Q3Accel* qa = new Q3Accel(this);
///qa->connectItem(qa->insertItem(Qt::CTRL+Qt::Key_Z), song, SLOT(undo()));
@@ -153,8 +166,10 @@ LMaster::LMaster()
connect(view, SIGNAL(itemPressed(QTreeWidgetItem*, int)), SLOT(itemPressed(QTreeWidgetItem*, int)));
connect(view, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), SLOT(itemDoubleClicked(QTreeWidgetItem*)));
connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int)));
+ connect(this, SIGNAL(seekTo(int)), song, SLOT(seekTo(int)));
connect(tempoButton, SIGNAL(clicked()), SLOT(tempoButtonClicked()));
connect(timeSigButton, SIGNAL(clicked()), SLOT(timeSigButtonClicked()));
+ connect(keyButton, SIGNAL(clicked()), SLOT(insertKey()));
initShortcuts();
}
@@ -186,6 +201,10 @@ void LMaster::insertTempo(const TEvent* ev)
new LMasterTempoItem(view, ev);
}
+void LMaster::insertKey(const KeyEvent* ev)
+ {
+ new LMasterKeyEventItem(view, ev);
+ }
//---------------------------------------------------------
// updateList
//---------------------------------------------------------
@@ -204,33 +223,65 @@ void LMaster::updateList()
view->clear();
const TempoList* t = &tempomap;
const AL::SigList* s = &AL::sigmap;
+ const KeyList* k = &keymap;
criTEvent it = t->rbegin();
AL::criSigEvent is = s->rbegin();
+ criKeyEvent ik = k->rbegin();
+
+ // three lists that should be added to the view.
+ // question if it would not be easier to merge the lists and use a sorting algorithm?
+ // how often is this function called? A: only on songChanged (SC_TEMPO && SC_SIG)
+
for (;;) {
- if (it == t->rend()) {
- while(is != s->rend()) {
- insertSig(is->second);
- ++is;
- }
- break;
- }
- if (is == s->rend()) {
- while (it != t->rend()) {
- insertTempo(it->second);
- ++it;
- }
- break;
- }
- if (is->second->tick > it->second->tick) {
- insertSig(is->second);
- ++is;
- }
- else {
- insertTempo(it->second);
- ++it;
- }
- }
+
+ // crazy long, must be possible to solve more elegantly...
+
+ if (ik != k->rend() && is == s->rend() && it == t->rend()) {// ik biggest
+ insertKey(ik->second);
+ ++ik;
+ }
+ else if (is != s->rend() && ik == k->rend() && it == t->rend()) {// is biggest
+ insertSig(is->second);
+ ++is;
+ }
+ else if (it != t->rend() && ik == k->rend() && is == s->rend()) {// it biggest
+ insertTempo(it->second);
+ ++it;
+ }
+
+ else if (ik != k->rend() && (is == s->rend() && (ik->second->tick >= it->second->tick)
+ || (it == t->rend() && ik->second->tick >= is->second->tick ))) {// ik biggest
+ insertKey(ik->second);
+ ++ik;
+ }
+ else if (is != s->rend() && (ik == k->rend() && (is->second->tick >= it->second->tick)
+ || (it == t->rend() && is->second->tick >= ik->second->tick ))) {// is biggest
+ insertSig(is->second);
+ ++is;
+ }
+
+ else if (it != t->rend() && (ik == k->rend() && (it->second->tick >= is->second->tick)
+ || (is == s->rend() && it->second->tick >= ik->second->tick ))) {// it biggest
+ insertTempo(it->second);
+ ++it;
+ }
+
+ else if (ik != k->rend() && ik->second->tick >= is->second->tick && ik->second->tick >= it->second->tick) {// ik biggest
+ insertKey(ik->second);
+ ++ik;
+ }
+ else if (is != s->rend() && is->second->tick >= it->second->tick && is->second->tick >= ik->second->tick) { // is biggest
+ insertSig(is->second);
+ ++is;
+ }
+ else if (it != t->rend() && it->second->tick >= is->second->tick && it->second->tick >= ik->second->tick) { // it biggest
+ insertTempo(it->second);
+ ++it;
+ }
+ if (ik == k->rend() && is == s->rend() && it == t->rend() )
+ break;
+ }
// Try to reselect the previous selection:
if(selected)
@@ -321,6 +372,13 @@ void LMaster::cmd(int cmd)
audio->msgRemoveSig(s->tick(), s->z(), s->n());
break;
}
+ case LMASTER_KEYEVENT:
+ {
+ //LMasterKeyEventItem* k = (LMasterKeyEventItem*) l;
+ keymap.delKey(l->tick());
+ //audio->msgRemoveSig(k->tick(), k->z(), k->n());
+ break;
+ }
default:
M_ERROR("Default switch statement reached");
break;
@@ -334,6 +392,9 @@ void LMaster::cmd(int cmd)
case CMD_INSERT_SIG:
timeSigButtonClicked();
break;
+ case CMD_INSERT_KEY:
+ insertKey();
+ break;
case CMD_EDIT_BEAT:
case CMD_EDIT_VALUE:
cmd == CMD_EDIT_VALUE ? editorColumn = LMASTER_VAL_COL : editorColumn = LMASTER_BEAT_COL;
@@ -365,6 +426,7 @@ void LMaster::itemPressed(QTreeWidgetItem* i, int column)
void LMaster::itemDoubleClicked(QTreeWidgetItem* i)
{
//printf("itemDoubleClicked\n");
+ emit seekTo(((LMasterLViewItem*) i)->tick());
if (!editedItem && editorColumn == LMASTER_VAL_COL) {
editedItem = (LMasterLViewItem*) i;
@@ -394,7 +456,7 @@ void LMaster::itemDoubleClicked(QTreeWidgetItem* i)
editor->selectAll();
connect(editor, SIGNAL(returnPressed()), SLOT(returnPressed()));
}
- else { // Edit signatur value:
+ else if (editedItem->getType() == LMASTER_SIGEVENT) { // Edit signatur value:
if (!sig_editor)
sig_editor = new SigEdit(view->viewport());
sig_editor->setValue(editedItem->text(LMASTER_VAL_COL));
@@ -403,6 +465,21 @@ void LMaster::itemDoubleClicked(QTreeWidgetItem* i)
sig_editor->setFocus();
connect(sig_editor, SIGNAL(returnPressed()), SLOT(returnPressed()));
}
+ else if (editedItem->getType() == LMASTER_KEYEVENT) {
+ if (!key_editor)
+ key_editor = new QComboBox(view->viewport());
+ key_editor->addItems(keyStrs);
+ //key_editor->setText(editedItem->text(LMASTER_VAL_COL));
+ key_editor->setCurrentIndex(keyStrs.indexOf(editedItem->text(LMASTER_VAL_COL)));
+ key_editor->setGeometry(itemRect);
+ key_editor->show();
+ key_editor->setFocus();
+ //key_editor->selectAll();
+ connect(key_editor, SIGNAL(currentIndexChanged(int)), SLOT(returnPressed()));
+ }
+ else {
+ printf("illegal Master list type\n");
+ }
}
// Edit tempo or signal position:
else if (!editedItem && editorColumn == LMASTER_BEAT_COL) {
@@ -523,6 +600,25 @@ void LMaster::returnPressed()
view->setCurrentItem(newSelected);
}
}
+ else if (editedItem->getType() == LMASTER_KEYEVENT) {
+ LMasterKeyEventItem* k = (LMasterKeyEventItem*) editedItem;
+ int key = k->key();
+// song->startUndo();
+// audio->msgDeleteTempo(oldtick, tempo, false);
+// audio->msgAddTempo(newtick, tempo, false);
+// song->endUndo(SC_TEMPO);
+ keymap.delKey(oldtick);
+ keymap.addKey(newtick, key);
+ // Select the item:
+ QTreeWidgetItem* newSelected = (QTreeWidgetItem*) getItemAtPos(newtick, LMASTER_KEYEVENT);
+ if (newSelected) {
+ view->clearSelection();
+ view->setCurrentItem(newSelected);
+ }
+ }
+ else {
+ printf("unknown master list event type!\n");
+ }
}
pos_editor->hide();
@@ -533,7 +629,8 @@ void LMaster::returnPressed()
//
else if (editedItem->getType() == LMASTER_SIGEVENT && editorColumn == LMASTER_VAL_COL)
{
- ///Sig newSig = sig_editor->sig();
+ printf("SIGEVENT return\n");
+ ///Sig newSig = sig_editor->sig();
AL::TimeSignature newSig = sig_editor->sig();
sig_editor->hide();
@@ -541,8 +638,8 @@ void LMaster::returnPressed()
// Added p3.3.43 Prevents aborting with 0 z or n.
if(newSig.isValid())
{
-
LMasterSigEventItem* e = (LMasterSigEventItem*) editedItem;
+ printf("adding sig %d %d\n", e->z(),e->n());
int tick = e->tick();
if (!editingNewItem) {
song->startUndo();
@@ -553,9 +650,38 @@ void LMaster::returnPressed()
}
else
audio->msgAddSig(tick, newSig.z, newSig.n, true);
- }
+ }
+ else {
+ printf("Signature is not valid!\n");
+ }
}
+ else if (editedItem->getType() == LMASTER_KEYEVENT && editorColumn == LMASTER_VAL_COL) {
+ printf("KEYEVENT return\n");
+ QString input = key_editor->currentText();
+ key_editor->hide();
+ repaint();
+ LMasterKeyEventItem* e = (LMasterKeyEventItem*) editedItem;
+ const KeyEvent* t = e->getEvent();
+ unsigned tick = t->tick;
+ int key = keyStrs.indexOf(input);
+
+ if (!editingNewItem) {
+// song->startUndo();
+// audio->msgDeleteTempo(tick, e->tempo(), false);
+// audio->msgAddTempo(tick, tempo, false);
+// song->endUndo(SC_TEMPO);
+ keymap.addKey(tick,key);
+ }
+ //
+ // New item edited:
+ //
+ else {
+ //audio->msgAddTempo(tick, tempo, true);
+ keymap.addKey(tick,key);
+ }
+ }
+ updateList();
view->setFocus();
// No item edited now:
editedItem = 0;
@@ -593,6 +719,35 @@ QString LMasterLViewItem::text(int column) const
}
//---------------------------------------------------------
+// LMasterKeyEventItem
+//! Initializes a LMasterKeyEventItem with a KeyEvent
+//---------------------------------------------------------
+LMasterKeyEventItem::LMasterKeyEventItem(QTreeWidget* parent, const KeyEvent* ev)
+ : LMasterLViewItem(parent)
+ {
+ keyEvent = ev;
+ unsigned t = ev->tick;
+ int bar, beat;
+ unsigned tick;
+ AL::sigmap.tickValues(t, &bar, &beat, &tick);
+ c1.sprintf("%04d.%02d.%03d", bar+1, beat+1, tick);
+
+ double time = double(tempomap.tick2frame(t)) / double(sampleRate);
+ int min = int(time) / 60;
+ int sec = int(time) % 60;
+ int msec = int((time - (min*60 + sec)) * 1000.0);
+ c2.sprintf("%03d:%02d:%03d", min, sec, msec);
+ c3 = "Key";
+ //int dt = ev->key;
+ c4 = keyStrs[ev->key];
+ setText(0, c1);
+ setText(1, c2);
+ setText(2, c3);
+ setText(3, c4);
+ }
+
+
+//---------------------------------------------------------
// LMasterTempoItem
//! Initializes a LMasterTempoItem with a TEvent
//---------------------------------------------------------
@@ -607,7 +762,7 @@ LMasterTempoItem::LMasterTempoItem(QTreeWidget* parent, const TEvent* ev)
AL::sigmap.tickValues(t, &bar, &beat, &tick);
c1.sprintf("%04d.%02d.%03d", bar+1, beat+1, tick);
- double time = double(ev->frame) / double(sampleRate);
+ double time = double(tempomap.tick2frame(t) /*ev->frame*/) / double(sampleRate);
int min = int(time) / 60;
int sec = int(time) % 60;
int msec = int((time - (min*60 + sec)) * 1000.0);
@@ -655,12 +810,13 @@ LMasterSigEventItem::LMasterSigEventItem(QTreeWidget* parent, const AL::SigEvent
void LMaster::tempoButtonClicked()
{
LMasterTempoItem* lastTempo = (LMasterTempoItem*) getLastOfType(LMASTER_TEMPO);
- QString beatString = ((LMasterLViewItem*)lastTempo)->text(LMASTER_BEAT_COL);
- int m, b, t;
- Pos p = Pos(beatString);
- p.mbt(&m, &b, &t);
- m++; //Next bar
- int newTick = AL::sigmap.bar2tick(m, b, t);
+// QString beatString = ((LMasterLViewItem*)lastTempo)->text(LMASTER_BEAT_COL);
+// int m, b, t;
+// Pos p = Pos(beatString);
+// p.mbt(&m, &b, &t);
+// m++; //Next bar
+// int newTick = AL::sigmap.bar2tick(m, b, t);
+ int newTick = song->cpos();
TEvent* ev = new TEvent(lastTempo->tempo(), newTick);
new LMasterTempoItem(view, ev);
QTreeWidgetItem* newTempoItem = view->topLevelItem(0);
@@ -675,18 +831,19 @@ void LMaster::tempoButtonClicked()
//---------------------------------------------------------
-// tempoButtonClicked()
+// timeSigButtonClicked()
//! inserts a new sig-item in the list and starts the editor for it
//---------------------------------------------------------
void LMaster::timeSigButtonClicked()
{
LMasterSigEventItem* lastSig = (LMasterSigEventItem*) getLastOfType(LMASTER_SIGEVENT);
- QString beatString = ((LMasterLViewItem*)lastSig)->text(LMASTER_BEAT_COL);
- int m, b, t;
- Pos p = Pos(beatString);
- p.mbt(&m, &b, &t);
- m++;
- int newTick = AL::sigmap.bar2tick(m, b, t);
+// QString beatString = ((LMasterLViewItem*)lastSig)->text(LMASTER_BEAT_COL);
+// int m, b, t;
+// Pos p = Pos(beatString);
+// p.mbt(&m, &b, &t);
+// m++;
+// int newTick = AL::sigmap.bar2tick(m, b, t);
+ int newTick = song->cpos();
AL::SigEvent* ev = new AL::SigEvent(AL::TimeSignature(lastSig->z(), lastSig->n()), newTick);
new LMasterSigEventItem(view, ev);
QTreeWidgetItem* newSigItem = view->topLevelItem(0);
@@ -699,6 +856,33 @@ void LMaster::timeSigButtonClicked()
itemDoubleClicked(newSigItem);
}
+//---------------------------------------------------------
+// insertKey()
+//! inserts a new key in the list and starts the editor for it
+//---------------------------------------------------------
+void LMaster::insertKey()
+ {
+ LMasterKeyEventItem* lastKey = (LMasterKeyEventItem*) getLastOfType(LMASTER_KEYEVENT);
+
+ //QString beatString = ((LMasterLViewItem*)lastKey)->text(LMASTER_BEAT_COL);
+ //int m, b, t;
+ //Pos p = Pos(beatString);
+ //p.mbt(&m, &b, &t);
+ //m++; //Next bar
+
+ //int newTick = AL::sigmap.bar2tick(m, b, t);
+ int newTick = song->cpos();
+ KeyEvent* ev = new KeyEvent(lastKey->key(), newTick);
+ new LMasterKeyEventItem(view, ev);
+ QTreeWidgetItem* newKeyItem = view->topLevelItem(0);
+
+ editingNewItem = true; // State
+ editorColumn = LMASTER_VAL_COL; // Set that we edit editorColumn
+ view->clearSelection();
+ view->setCurrentItem(newKeyItem);
+ itemDoubleClicked(newKeyItem);
+ }
+
/*!
\fn LMaster::getLastOfType(LMASTER_LVTYPE t)
@@ -745,6 +929,7 @@ void LMaster::initShortcuts()
{
tempoAction->setShortcut(shortcuts[SHRT_LM_INS_TEMPO].key);
signAction->setShortcut(shortcuts[SHRT_LM_INS_SIG].key);
+ keyAction->setShortcut(shortcuts[SHRT_LM_INS_KEY].key);
posAction->setShortcut(shortcuts[SHRT_LM_EDIT_BEAT].key);
valAction->setShortcut(shortcuts[SHRT_LM_EDIT_VALUE].key);
}
diff --git a/muse2/muse/master/lmaster.h b/muse2/muse/master/lmaster.h
index cd687e45..925b5837 100644
--- a/muse2/muse/master/lmaster.h
+++ b/muse2/muse/master/lmaster.h
@@ -12,6 +12,7 @@
#include "noteinfo.h"
#include "cobject.h"
#include "tempo.h"
+#include "keyevent.h"
///#include "sig.h"
//#include "al/sig.h"
@@ -30,13 +31,16 @@ using Awl::PosEdit;
using Awl::SigEdit;
class QLineEdit;
+class QComboBox;
enum LMASTER_LVTYPE
{
LMASTER_TEMPO = 0,
- LMASTER_SIGEVENT
+ LMASTER_SIGEVENT,
+ LMASTER_KEYEVENT
};
+
//---------------------------------------------------------
// LMasterLViewItem
//! QListViewItem base class for LMasterTempoItem and LMasterSigEventItem
@@ -71,6 +75,22 @@ class LMasterTempoItem : public LMasterLViewItem {
};
//---------------------------------------------------------
+// LMasterKeyItem
+//! QListViewItem which holds data for a KetEvent
+//---------------------------------------------------------
+class LMasterKeyEventItem : public LMasterLViewItem {
+
+ private:
+ const KeyEvent* keyEvent;
+
+ public:
+ LMasterKeyEventItem(QTreeWidget* parent, const KeyEvent* t);
+ virtual LMASTER_LVTYPE getType() { return LMASTER_KEYEVENT; }
+ const KeyEvent* getEvent() { return keyEvent; }
+ virtual unsigned tick() { return keyEvent->tick; }
+ int key() { return keyEvent->key; }
+ };
+//---------------------------------------------------------
// LMasterTempoItem
//! QListViewItem which holds data for a SigEvent
//---------------------------------------------------------
@@ -98,24 +118,26 @@ class LMaster : public MidiEditor {
QToolBar* tools;
QMenu* menuEdit;
- enum { CMD_DELETE, CMD_INSERT_SIG, CMD_INSERT_TEMPO, CMD_EDIT_BEAT, CMD_EDIT_VALUE };
+ enum { CMD_DELETE, CMD_INSERT_SIG, CMD_INSERT_TEMPO, CMD_EDIT_BEAT, CMD_EDIT_VALUE, CMD_INSERT_KEY };
Q_OBJECT
virtual void closeEvent(QCloseEvent*);
void updateList();
void insertTempo(const TEvent*);
void insertSig(const SigEvent*);
+ void insertKey(const KeyEvent*);
LMasterLViewItem* getItemAtPos(unsigned tick, LMASTER_LVTYPE t);
void initShortcuts();
QLineEdit* editor;
PosEdit* pos_editor;
+ QComboBox* key_editor;
// State-like members:
LMasterLViewItem* editedItem;
SigEdit* sig_editor;
int editorColumn;
bool editingNewItem;
- QAction *tempoAction, *signAction, *posAction, *valAction, *delAction;
+ QAction *tempoAction, *signAction, *posAction, *valAction, *delAction, *keyAction;
private slots:
void select(QTreeWidgetItem*, QTreeWidgetItem*);
@@ -124,6 +146,7 @@ class LMaster : public MidiEditor {
void itemPressed(QTreeWidgetItem* i, int column);
void tempoButtonClicked();
void timeSigButtonClicked();
+ void insertKey();
void cmd(int cmd);
public slots:
@@ -132,6 +155,7 @@ class LMaster : public MidiEditor {
signals:
void deleted(unsigned long);
+ void seekTo(int tick);
public:
LMaster();
diff --git a/muse2/muse/shortcuts.cpp b/muse2/muse/shortcuts.cpp
index 9cbc3726..cd54b096 100644
--- a/muse2/muse/shortcuts.cpp
+++ b/muse2/muse/shortcuts.cpp
@@ -134,7 +134,7 @@ void initShortCuts()
defShrt(SHRT_SEL_BELOW_ADD, Qt::SHIFT + Qt::Key_Down, "Edit: Add nearest part on track below", ARRANG_SHRT, "sel_part_below_add");
defShrt(SHRT_INSERT, Qt::CTRL+Qt::SHIFT+ Qt::Key_I, "Edit: Insert parts, moving time", ARRANG_SHRT, "insert_parts");
- defShrt(SHRT_INSERTMEAS, Qt::CTRL+Qt::SHIFT+ Qt::Key_M, "Edit: Insert empty measure", ARRANG_SHRT, "insert_measure");
+ defShrt(SHRT_INSERTMEAS, Qt::CTRL+Qt::SHIFT+ Qt::Key_O, "Edit: Insert empty measure", ARRANG_SHRT, "insert_measure");
defShrt(SHRT_PASTE_CLONE, Qt::CTRL+Qt::SHIFT+Qt::Key_V, "Edit: Paste clone", ARRANG_SHRT, "paste_clone");
defShrt(SHRT_PASTE_TO_TRACK, Qt::CTRL+Qt::Key_B, "Edit: Paste to track", ARRANG_SHRT, "paste_to_track");
@@ -299,7 +299,8 @@ void initShortCuts()
defShrt(SHRT_LM_INS_SIG , Qt::CTRL + Qt::Key_R, "Insert Signature", LMEDIT_SHRT, "lm_ins_sig");
defShrt(SHRT_LM_EDIT_BEAT, Qt::CTRL + Qt::SHIFT+ Qt::Key_E, "Change Event Position", LMEDIT_SHRT, "lm_edit_beat");
defShrt(SHRT_LM_EDIT_VALUE, Qt::CTRL + Qt::Key_E, "Edit Event Value", LMEDIT_SHRT, "lm_edit_val");
-
+ defShrt(SHRT_LM_INS_KEY, Qt::CTRL + Qt::Key_K, "Insert Key", LMEDIT_SHRT, "lm_ins_key");
+
defShrt(SHRT_NEXT_MARKER, Qt::Key_F6, "Goto Next Marker", ARRANG_SHRT, "me_sel_next");
defShrt(SHRT_PREV_MARKER, Qt::Key_F5, "Goto Prev Marker", ARRANG_SHRT, "me_sel_prev");
diff --git a/muse2/muse/shortcuts.h b/muse2/muse/shortcuts.h
index 6878d177..1098be49 100644
--- a/muse2/muse/shortcuts.h
+++ b/muse2/muse/shortcuts.h
@@ -316,7 +316,8 @@ enum {
SHRT_LM_INS_SIG, // Ctrl+R
SHRT_LM_EDIT_BEAT, // Ctrl+Shift+E
SHRT_LM_EDIT_VALUE,// Ctrl+E
-
+ SHRT_LM_INS_KEY, // Ctrl+K
+
// Marker view
SHRT_NEXT_MARKER,
SHRT_PREV_MARKER,
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index dbb193d9..a7cff79d 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -42,6 +42,7 @@
#include "midi.h"
///#include "sig.h"
#include "al/sig.h"
+#include "keyevent.h"
#include <sys/wait.h>
extern void clearMidiTransforms();
@@ -1289,6 +1290,17 @@ void Song::swapTracks(int i1, int i2)
}
//---------------------------------------------------------
+// seekTo
+// setPos slot, only active when not doing playback
+//---------------------------------------------------------
+void Song::seekTo(int tick)
+{
+ if (!audio->isPlaying()) {
+ Pos p(tick, true);
+ setPos(0, p);
+ }
+}
+//---------------------------------------------------------
// setPos
// song->setPos(Song::CPOS, pos, true, true, true);
//---------------------------------------------------------
@@ -2098,6 +2110,7 @@ void Song::clear(bool signal, bool /*clear_all*/)
tempomap.clear();
AL::sigmap.clear();
+ keymap.clear();
undoList->clearDelete();
redoList->clear();
_markerList->clear();
@@ -2183,6 +2196,7 @@ void Song::cleanupForQuit()
tempomap.clear();
AL::sigmap.clear();
+ keymap.clear();
if(debugMsg)
printf("deleting undoList, clearing redoList\n");
diff --git a/muse2/muse/song.h b/muse2/muse/song.h
index c735dfd5..e4695728 100644
--- a/muse2/muse/song.h
+++ b/muse2/muse/song.h
@@ -362,6 +362,7 @@ class Song : public QObject {
void executeScript(const char* scriptfile, PartList* parts, int quant, bool onlyIfSelected);
public slots:
+ void seekTo(int tick);
void update(int flags = -1);
void beat();
diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp
index 1e8a849b..7a690f74 100644
--- a/muse2/muse/songfile.cpp
+++ b/muse2/muse/songfile.cpp
@@ -36,6 +36,7 @@
//#include "mixer/amixer.h" // p4.0.2
#include "conf.h"
#include "driver/jackmidi.h"
+#include "keyevent.h"
//struct ClonePart {
//const EventList* el;
@@ -1258,6 +1259,9 @@ void Song::read(Xml& xml)
else if (tag == "siglist")
///sigmap.read(xml);
AL::sigmap.read(xml);
+ else if (tag == "keylist") {
+ keymap.read(xml);
+ }
else if (tag == "miditrack") {
MidiTrack* track = new MidiTrack();
track->read(xml);
@@ -1484,6 +1488,7 @@ void Song::write(int level, Xml& xml) const
tempomap.write(level, xml);
///sigmap.write(level, xml);
AL::sigmap.write(level, xml);
+ keymap.write(level, xml);
_markerList->write(level, xml);
writeDrumMap(level, xml, false);