summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/audioextractor.cc119
-rw-r--r--src/audioextractor.h15
-rw-r--r--src/canvas.cc5
-rw-r--r--src/canvas.h1
-rw-r--r--src/canvastoolselections.cc4
-rw-r--r--src/channeldialog.cc77
-rw-r--r--src/channeldialog.h49
-rw-r--r--src/dgedit.cc19
-rw-r--r--src/filelist.cc450
-rw-r--r--src/filelist.h38
-rw-r--r--src/imageeditor.cc49
-rw-r--r--src/imageeditor.h40
-rw-r--r--src/instrumentwidget.cc20
-rw-r--r--src/localehandler.cc4
-rw-r--r--src/mainwindow.cc72
-rw-r--r--src/mainwindow.h5
-rw-r--r--src/player.cc5
-rw-r--r--src/player.h3
-rw-r--r--src/project.cc218
-rw-r--r--src/project.h74
-rw-r--r--src/projectrenderer.cc124
-rw-r--r--src/projectrenderer.h54
-rw-r--r--src/projectserialiser.cc69
-rw-r--r--src/renderdialog.cc98
-rw-r--r--src/renderdialog.h64
26 files changed, 1386 insertions, 298 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index cefe0ff..43b87e3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,8 +22,10 @@ dgedit_SOURCES = \
canvastoolselections.cc \
canvastoolthreshold.cc \
canvaswidget.cc \
+ channeldialog.cc \
channelswidget.cc \
filelist.cc \
+ imageeditor.cc \
instrumentdialog.cc \
instrumentwidget.cc \
itemeditor.cc \
@@ -33,7 +35,9 @@ dgedit_SOURCES = \
player.cc \
project.cc \
projectdialog.cc \
+ projectrenderer.cc \
projectserialiser.cc \
+ renderdialog.cc \
samplesorter.cc \
selection.cc \
selectioneditor.cc \
@@ -49,8 +53,10 @@ EXTRA_DIST = \
canvastoolselections.h \
canvastoolthreshold.h \
canvaswidget.h \
+ channeldialog.h \
channelswidget.h \
filelist.h \
+ imageeditor.h \
instrumentdialog.h \
instrumentwidget.h \
itemeditor.h \
@@ -60,7 +66,9 @@ EXTRA_DIST = \
player.h \
project.h \
projectdialog.h \
+ projectrenderer.h \
projectserialiser.h \
+ renderdialog.h \
samplesorter.h \
selection.h \
selectioneditor.h \
diff --git a/src/audioextractor.cc b/src/audioextractor.cc
index 2132cba..50f2947 100644
--- a/src/audioextractor.cc
+++ b/src/audioextractor.cc
@@ -43,17 +43,18 @@ typedef struct
float *data;
} audiodata_t;
-AudioExtractor::AudioExtractor(Instrument& instrument, Selections &selections,
- QObject *parent)
+AudioExtractor::AudioExtractor(Instrument& instrument, QObject *parent)
: QObject(parent)
, instrument(instrument)
- , selections(selections)
{
- audiofiles = instrument.getFileList();
}
void AudioExtractor::exportSelections()
{
+ auto selections = instrument.getSelections();
+ auto exportpath = instrument.getProject().getExportPath();
+ auto prefix = instrument.getPrefix();
+
int samplerate = -1;
emit setMaximumProgress(selections.ids().size() + 1/* for xml writing*/);
int progress = 0;
@@ -61,19 +62,20 @@ void AudioExtractor::exportSelections()
qApp->processEvents();
// Open all input audio files:
- audiodata_t audiodata[audiofiles.size()];
+ auto audiofile_ids = instrument.getAudioFileList();
+ audiodata_t audiodata[audiofile_ids.size()];
int idx = 0;
- AudioFileList::iterator j = audiofiles.begin();
- while(j != audiofiles.end())
+ for(auto audiofile_id : audiofile_ids)
{
- QString file = j->first;
+ const auto& audiofile = instrument.getAudioFile(audiofile_id);
+ QString file = audiofile.getFile();
SF_INFO sf_info;
audiodata[idx].fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info);
if(!audiodata[idx].fh)
{
- printf("Load error '%s'\n", file.toStdString().c_str());
+ printf("AudioExtractor load error '%s'\n", file.toStdString().c_str());
return;
}
@@ -85,7 +87,6 @@ void AudioExtractor::exportSelections()
audiodata[idx].data = NULL;
- j++;
idx++;
}
@@ -127,7 +128,7 @@ void AudioExtractor::exportSelections()
// Read all input audio file chunks:
- for(int i = 0; i < audiofiles.size(); i++)
+ for(int i = 0; i < audiofile_ids.size(); i++)
{
// Clear out old buffer (if one exists)
if(audiodata[i].data)
@@ -175,23 +176,23 @@ void AudioExtractor::exportSelections()
SF_INFO sf_info;
sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
sf_info.samplerate = samplerate;
- sf_info.channels = audiofiles.size();
+ sf_info.channels = audiofile_ids.size();
SNDFILE *ofh = sf_open(file.toStdString().c_str(), SFM_WRITE, &sf_info);
if(!ofh)
{
- printf("Open for write error...\n");
+ printf("Open for write error. %s\n", file.toStdString().c_str());
return;
}
for(size_t ob = 0; ob < size; ob++)
{
- float obuf[audiofiles.size()];
- for(int ai = 0; ai < audiofiles.size(); ai++)
+ float obuf[audiofile_ids.size()];
+ for(int ai = 0; ai < audiofile_ids.size(); ai++)
{
obuf[ai] = audiodata[ai].data[ob];
}
- sf_write_float(ofh, obuf, audiofiles.size());
+ sf_write_float(ofh, obuf, audiofile_ids.size());
}
sf_close(ofh);
@@ -203,7 +204,7 @@ void AudioExtractor::exportSelections()
}
// Close all input audio files:
- for(int i = 0; i < audiofiles.size(); i++)
+ for(int i = 0; i < audiofile_ids.size(); i++)
{
if(audiodata[i].data)
{
@@ -219,13 +220,13 @@ void AudioExtractor::exportSelections()
doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
doc.appendChild(header);
- QDomElement instrument = doc.createElement("instrument");
- instrument.setAttribute("version", INSTRUMENT_VERSION);
- instrument.setAttribute("name", prefix);
- doc.appendChild(instrument);
+ QDomElement instrument_node = doc.createElement("instrument");
+ instrument_node.setAttribute("version", INSTRUMENT_VERSION);
+ instrument_node.setAttribute("name", prefix);
+ doc.appendChild(instrument_node);
QDomElement samples = doc.createElement("samples");
- instrument.appendChild(samples);
+ instrument_node.appendChild(samples);
{
// Do the adding to the xml file one sample at the time.
@@ -246,20 +247,21 @@ void AudioExtractor::exportSelections()
selections.update(*si, i);
int channelnum = 1; // Filechannel numbers are 1-based.
- AudioFileList::iterator j = audiofiles.begin();
- while(j != audiofiles.end())
+
+ for(auto audiofile_id : audiofile_ids)
{
- QString file = j->first;
- QString name = j->second;
-
- QDomElement audiofile = doc.createElement("audiofile");
- audiofile.setAttribute("file", "samples/" +
- QString::number(index) + "-" + prefix + ".wav");
- audiofile.setAttribute("channel", name);
- audiofile.setAttribute("filechannel", QString::number(channelnum));
- sample.appendChild(audiofile);
+ const auto& audiofile = instrument.getAudioFile(audiofile_id);
+
+ QString file = audiofile.getFile();
+ QString name = audiofile.getName();
+
+ QDomElement audiofile_node = doc.createElement("audiofile");
+ audiofile_node.setAttribute("file", "samples/" +
+ QString::number(index) + "-" + prefix + ".wav");
+ audiofile_node.setAttribute("channel", name);
+ audiofile_node.setAttribute("filechannel", QString::number(channelnum));
+ sample.appendChild(audiofile_node);
channelnum++;
- j++;
}
si++;
@@ -274,52 +276,3 @@ void AudioExtractor::exportSelections()
emit progressUpdate(progress++);
qApp->processEvents();
}
-
-void AudioExtractor::addFile(QString file, QString name)
-{
- QPair<QString, QString> pair;
- pair.first = file;
- pair.second = name;
- audiofiles.push_back(pair);
- instrument.setFileList(audiofiles);
-}
-
-void AudioExtractor::removeFile(QString file, QString name)
-{
- AudioFileList::iterator j = audiofiles.begin();
- while(j != audiofiles.end())
- {
- if(file == j->first/* && name == j->second*/)
- {
- audiofiles.erase(j);
- break;
- }
- j++;
- }
- instrument.setFileList(audiofiles);
-}
-
-void AudioExtractor::setOutputPrefix(const QString &p)
-{
- prefix = p;
-}
-
-void AudioExtractor::setExportPath(const QString &path)
-{
- exportpath = path;
-}
-
-void AudioExtractor::changeName(QString file, QString name)
-{
- AudioFileList::iterator j = audiofiles.begin();
- while(j != audiofiles.end())
- {
- if(file == j->first)
- {
- j->second = name;
- break;
- }
- j++;
- }
- instrument.setFileList(audiofiles);
-}
diff --git a/src/audioextractor.h b/src/audioextractor.h
index a38f706..35eb5ba 100644
--- a/src/audioextractor.h
+++ b/src/audioextractor.h
@@ -37,24 +37,15 @@
class Instrument;
-typedef QLinkedList< QPair<QString, QString> > AudioFileList;
-
class AudioExtractor
: public QObject
{
Q_OBJECT
public:
- AudioExtractor(Instrument& instrument, Selections& selections,
- QObject* parent);
+ AudioExtractor(Instrument& instrument, QObject* parent);
public slots:
- void addFile(QString file, QString name);
- void changeName(QString file, QString name);
- void removeFile(QString file, QString name);
-
void exportSelections();
- void setExportPath(const QString& path);
- void setOutputPrefix(const QString& prefix);
signals:
void progressUpdate(int value);
@@ -62,8 +53,4 @@ signals:
private:
Instrument& instrument;
- Selections& selections;
- AudioFileList audiofiles;
- QString exportpath;
- QString prefix;
};
diff --git a/src/canvas.cc b/src/canvas.cc
index f2956fc..b9356d6 100644
--- a/src/canvas.cc
+++ b/src/canvas.cc
@@ -96,11 +96,12 @@ void Canvas::load(QString file)
SNDFILE *fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info);
if(!fh)
{
- printf("Load error...\n");
+ printf("Canvas load error '%s'\n", file.toStdString().c_str());
return;
}
size = sf_info.frames;
+ samplerate = sf_info.samplerate;
data = new float[size];
@@ -203,7 +204,7 @@ void Canvas::updateWav()
painter.drawRect(0, 0, wav.width(), wav.height());
painter.setPen(colSec);
- int step = 44100;
+ int step = samplerate;
for(size_t i = 0; i < size; i += step)
{
painter.drawLine(mapX(i), mapY(1.0), mapX(i), mapY(-1.0));
diff --git a/src/canvas.h b/src/canvas.h
index 425e38d..dbdd211 100644
--- a/src/canvas.h
+++ b/src/canvas.h
@@ -76,6 +76,7 @@ private:
public:
float* data;
size_t size;
+ double samplerate{44100};
QVector<CanvasTool*> tools;
diff --git a/src/canvastoolselections.cc b/src/canvastoolselections.cc
index 0012d8e..d3e90f1 100644
--- a/src/canvastoolselections.cc
+++ b/src/canvastoolselections.cc
@@ -293,7 +293,7 @@ void CanvasToolSelections::doAutoCreateSelections(bool preview)
if(data[from] > 0.0)
{
- while(data[from] > data[from-1] && // Falling
+ while(/*data[from] > data[from-1] &&*/ // Falling
data[from-1] > 0.0 // Not crossing zero
)
{
@@ -302,7 +302,7 @@ void CanvasToolSelections::doAutoCreateSelections(bool preview)
}
else if(data[from] < 0.0)
{
- while(data[from] < data[from-1] && // Rising
+ while(/*data[from] < data[from-1] &&*/ // Rising
data[from-1] < 0.0 // Not crossing zero
)
{
diff --git a/src/channeldialog.cc b/src/channeldialog.cc
new file mode 100644
index 0000000..440a37d
--- /dev/null
+++ b/src/channeldialog.cc
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * channeldialog.cc
+ *
+ * Fri Sep 21 17:27:08 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "channeldialog.h"
+
+#include <QGridLayout>
+
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+
+#include <QFileDialog>
+#include <QDialogButtonBox>
+
+#include "project.h"
+
+ChannelDialog::ChannelDialog(QWidget* parent, Channel& channel)
+ : QDialog(parent)
+ , channel(channel)
+{
+ setWindowModality(Qt::ApplicationModal);
+ setWindowTitle(tr("Channel Dialog"));
+ setMinimumWidth(300);
+
+ auto layout = new QGridLayout();
+ setLayout(layout);
+
+ int idx = 0;
+
+ name = new QLineEdit();
+ name->setText(channel.getChannelName());
+ layout->addWidget(new QLabel(tr("Name of the channel:")), idx, 0, 1, 2);
+ idx++;
+ layout->addWidget(name, idx, 0);
+ idx++;
+
+ auto buttons =
+ new QDialogButtonBox(QDialogButtonBox::Ok |
+ QDialogButtonBox::Cancel |
+ QDialogButtonBox::Apply);
+ connect(buttons, SIGNAL(accepted()), this, SLOT(apply()));
+ connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
+ this, SLOT(apply()));
+ layout->addWidget(buttons, idx, 0, 1, 2);
+}
+
+void ChannelDialog::apply()
+{
+ // Only send out one update signal
+ Project::RAIIBulkUpdate bulkUpdate(channel.getProject());
+ channel.setChannelName(name->text());
+}
diff --git a/src/channeldialog.h b/src/channeldialog.h
new file mode 100644
index 0000000..a005a23
--- /dev/null
+++ b/src/channeldialog.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * channeldialog.h
+ *
+ * Fri Sep 21 17:27:08 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <QDialog>
+#include <QLineEdit>
+
+class Channel;
+
+class ChannelDialog
+ : public QDialog
+{
+ Q_OBJECT
+public:
+ ChannelDialog(QWidget* parent, Channel& channel);
+ ~ChannelDialog() = default;
+
+private slots:
+ void apply();
+
+private:
+ QLineEdit* name{nullptr};
+
+ Channel& channel;
+};
diff --git a/src/dgedit.cc b/src/dgedit.cc
index 3984f5a..218c73e 100644
--- a/src/dgedit.cc
+++ b/src/dgedit.cc
@@ -30,15 +30,30 @@
#include "settings.h"
#include "localehandler.h"
+extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed;
+
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ // Ugly hack to ensure the xml attribute order is the same each time a save
+ // or export is performed.
+ qt_qhash_seed.store(0);
+
LocaleHandler locale(app);
Settings settings;
- MainWindow wnd(settings);
- wnd.show();
+ MainWindow mainwindow(settings);
+ mainwindow.show();
+
+ if(argc > 1)
+ {
+ QFile file(argv[1]);
+ if(file.exists())
+ {
+ mainwindow.loadProject(argv[1]);
+ }
+ }
return app.exec();
}
diff --git a/src/filelist.cc b/src/filelist.cc
index 21b843e..c9e6a8a 100644
--- a/src/filelist.cc
+++ b/src/filelist.cc
@@ -35,35 +35,323 @@
#include "itemeditor.h"
#include "project.h"
-FileList::FileList(Instrument& instrument)
- : instrument(instrument)
+#include <QAbstractItemModel>
+#include <QTreeView>
+
+#include <iostream>
+
+#include <QComboBox>
+#include <QLineEdit>
+#include <QStyledItemDelegate>
+#include <QPainter>
+#include <QHeaderView>
+
+class ChannelMapDeligate
+ : public QStyledItemDelegate
{
- setContextMenuPolicy(Qt::CustomContextMenu);
+public:
+ ChannelMapDeligate(Instrument& instrument)
+ : instrument(instrument)
+ {
+ }
- connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
- this, SLOT(popupMenu(const QPoint&)));
+ QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override
+ {
+ // Name:
+ if(index.column() == 1)
+ {
+ auto w = new QLineEdit(parent);
+ return w;
+ }
+
+ // Channel Map ID:
+ if(index.column() == 2)
+ {
+ auto w = new QComboBox(parent);
+ w->addItem(tr("<None>"), -1);
+ auto channel_ids = instrument.getProject().getChannelList();
+ for(auto channel_id : channel_ids)
+ {
+ const auto& channel = instrument.getProject().getChannel(channel_id);
+ w->addItem(channel.getChannelName(), channel.getId());
+ }
+ return w;
+ }
+
+ return QStyledItemDelegate::createEditor(parent, option, index);
+ }
- connect(this, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
- this, SLOT(selectionChanged(QListWidgetItem*)));
+ void setEditorData(QWidget *editor, const QModelIndex &index) const override
+ {
+ // Name:
+ if(index.column() == 1)
+ {
+ auto w = static_cast<QLineEdit*>(editor);
+ auto s = index.data(Qt::EditRole).toString();
+ w->setText(s);
+ }
+
+ // Channel Map ID:
+ if(index.column() == 2)
+ {
+ auto w = static_cast<QComboBox*>(editor);
+ auto i = w->findData(index.data(Qt::EditRole).toInt());
+ w->setCurrentIndex(i);
+ }
+}
- createMenus();
+ void setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const override
+ { // Name:
+ if(index.column() == 1)
+ {
+ model->setData(index, static_cast<QLineEdit*>(editor)->text(),
+ Qt::EditRole);
+ }
+
+ // Channel Map ID:
+ if(index.column() == 2)
+ {
+ model->setData(index, static_cast<QComboBox*>(editor)->currentData(),
+ Qt::EditRole);
+ }
+ }
+
+// void paint(QPainter * painter,
+// const QStyleOptionViewItem & option,
+// const QModelIndex & index ) const override
+// {
+// if(index.column() == 0)
+// {
+// painter->drawRect(option.rect);
+// return;
+// }
+// QStyledItemDelegate::paint(painter, option, index);
+// }
+
+private:
+ Instrument& instrument;
+};
+
+class FileDataModel
+ : public QAbstractItemModel
+{
+public:
+ FileDataModel(Instrument& instrument)
+ : instrument(instrument)
+ {
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
+ {
+ if(!hasIndex(row, column, parent))
+ {
+ return QModelIndex();
+ }
+
+ auto audiofile_ids = instrument.getAudioFileList();
+ if(!parent.isValid())
+ {
+ if(row < audiofile_ids.size())
+ {
+ return createIndex(row, column, &instrument);
+ }
+ else
+ {
+ return QModelIndex(); // row is out of bounds.
+ }
+ }
+
+ return QModelIndex();
+ }
+
+ QModelIndex parent(const QModelIndex &index) const override
+ {
+ return QModelIndex(); // no parent
+ }
- // Load files into list:
- auto master_file = instrument.getMasterFile();
- auto files = instrument.getFileList();
- for(auto file : files)
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
- auto item = new QListWidgetItem();
- //item->setIcon(QPixmap(":icons/instrument.png"));
- setItemFile(item, file.first);
- setItemName(item, file.second);
- setItemMaster(item, file.first == master_file);
- addItem(item);
+ if(parent.column() > 0) // only return row count on first column
+ {
+ return 0;
+ }
+
+ if(!parent.isValid())
+ {
+ auto audiofile_ids = instrument.getAudioFileList();
+ return audiofile_ids.size(); // root level
+ }
+
+ return 0; // no children
}
+
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override
+ {
+ return 4;
+ }
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if(!index.isValid())
+ {
+ return QVariant();
+ }
+
+ auto audiofile_ids = instrument.getAudioFileList();
+
+ auto audiofile_id = audiofile_ids.begin() + index.row();
+ const auto& audiofile = instrument.getAudioFile(*audiofile_id);
+
+ if(role == Qt::DecorationRole )
+ {
+ if(index.column() == 0)
+ {
+ if(audiofile.getAbsoluteFile() == instrument.getMasterFile())
+ {
+ return QPixmap(":/icons/master.png");
+ }
+ else
+ {
+ return QPixmap(":/icons/file.png");
+ }
+ }
+ }
+
+ if(role == Qt::DisplayRole)
+ {
+ switch(index.column())
+ {
+ case 1: return audiofile.getName();
+ case 2:
+ {
+ auto channelMapId = audiofile.getChannelMapId();
+ if(channelMapId == -1)
+ {
+ return tr("<None>");
+ }
+ return instrument.getProject().getChannel(channelMapId).getChannelName();
+ }
+ case 3: return audiofile.getFile();
+ default: return QVariant();
+ }
+ }
+ else if(role == Qt::EditRole)
+ {
+ switch(index.column())
+ {
+ case 1: return audiofile.getName();
+ case 2: return audiofile.getChannelMapId();
+ case 3: return audiofile.getFile();
+ default: return QVariant();
+ }
+ }
+ else
+
+ {
+ return QVariant();
+ }
+ }
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override
+ {
+ if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ {
+ switch(section)
+ {
+ case 0: return tr("M");
+ case 1: return tr("Name");
+ case 2: return tr("Kit Channel");
+ case 3: return tr("Filename");
+ default: return QVariant();
+ }
+ }
+
+ return QVariant();
+ }
+
+ Qt::ItemFlags flags(const QModelIndex &index) const override
+ {
+ if(!index.isValid())
+ {
+ return 0;
+ }
+
+ switch(index.column())
+ {
+ case 0:
+ return QAbstractItemModel::flags(index);
+ case 1:
+ case 2:
+ return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
+ case 3:
+ return QAbstractItemModel::flags(index); // only column 1 is editable
+ }
+ }
+
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role = Qt::EditRole) override
+ {
+ auto audiofile_ids = instrument.getAudioFileList();
+
+ if(index.row() > audiofile_ids.size() || index.column() > 2)
+ {
+ return false;
+ }
+
+ auto audiofile_id = audiofile_ids.begin() + index.row();
+ auto& audiofile = instrument.getAudioFile(*audiofile_id);
+
+ switch(index.column())
+ {
+ case 0: break;
+ case 1: audiofile.setName(value.toString()); break;
+ case 2: audiofile.setChannelMapId(value.toInt()); break;
+ default: break;
+ }
+
+ return true;
+ }
+
+ void refresh()
+ {
+ beginResetModel();
+ endResetModel();
+ }
+
+private:
+ Instrument& instrument;
+};
+
+FileList::FileList(Instrument& instrument)
+ : instrument(instrument)
+{
+ model = new FileDataModel(instrument);
+ setModel(model);
+ setItemDelegate(new ChannelMapDeligate(instrument));
+ setEditTriggers(QAbstractItemView::AllEditTriggers); // show list on click
+
+ setContextMenuPolicy(Qt::CustomContextMenu); // enable context menu
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
+ this, SLOT(onCustomContextMenu(const QPoint &)));
+ setRootIsDecorated(false);
+ header()->resizeSection(0, 24);
+
+ connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
+ this, SLOT(selectionChanged(const QModelIndex&)));
+
+ createMenus();
}
void FileList::addFiles()
{
+ auto root = instrument.getProject().getRawFileRoot();
+ if(path.isEmpty())
+ {
+ path = root;
+ }
+
QStringList files =
QFileDialog::getOpenFileNames(this, tr("Open file"),
path, tr("Audio Files (*.wav)"));
@@ -74,38 +362,36 @@ void FileList::addFiles()
QFileInfo fi(file);
QString name = fi.baseName();
path = fi.absolutePath();
+ if(root == file.left(root.length()))
+ {
+ file = file.mid(root.length() + 1);
+ }
- QListWidgetItem* item = new QListWidgetItem();
- setItemFile(item, file);
- setItemName(item, name);
- setItemMaster(item, false);
- addItem(item);
-
- emit fileAdded(file, name);
+ auto id = instrument.createAudioFile();
+ auto& audiofile = instrument.getAudioFile(id);
+ audiofile.setName(name);
+ audiofile.setFile(file);
+ audiofile.setChannelMapId(-1);
i++;
}
+
+ model->refresh();
}
-void FileList::setMasterFile(QListWidgetItem* i)
+void FileList::selectionChanged(const QModelIndex &index)
{
- QString filename = itemFile(i);
-
- for(int idx = 0; idx < count(); idx++)
- {
- setItemMaster(item(idx), false);
- }
+ auto audiofile_ids = instrument.getAudioFileList();
+ auto audiofile_id = audiofile_ids.begin() + index.row();
+ const auto& audiofile = instrument.getAudioFile(*audiofile_id);
- setItemMaster(i, true);
- emit masterFileChanged(filename);
-}
+ instrument.setMasterFile(audiofile.getFile());
-void FileList::selectionChanged(QListWidgetItem* i)
-{
- setMasterFile(i);
+ emit masterFileChanged(audiofile.getAbsoluteFile());
+ //setMasterFile(i);
+ model->refresh();
}
-
void FileList::createMenus()
{
menu = new QMenu();
@@ -113,9 +399,6 @@ void FileList::createMenus()
setMasterAction = new QAction(tr("Set as Master (dbl-click)"), this);
connect(setMasterAction, SIGNAL(triggered()), this, SLOT(setMaster()));
- editAction = new QAction(tr("Edit name"), this);
- connect(editAction, SIGNAL(triggered()), this, SLOT(editName()));
-
removeAction = new QAction(tr("Remove"), this);
connect(removeAction, SIGNAL(triggered()), this, SLOT(removeFile()));
@@ -123,96 +406,43 @@ void FileList::createMenus()
connect(removeAllAction, SIGNAL(triggered()), this, SLOT(removeAllFiles()));
menu->addAction(setMasterAction);
- menu->addAction(editAction);
menu->addAction(removeAction);
menu->addSeparator();
menu->addAction(removeAllAction);
-
}
-void FileList::popupMenu(const QPoint& pos)
+void FileList::onCustomContextMenu(const QPoint &point)
{
- activeItem = itemAt(pos);
- if(!activeItem)
+ QModelIndex index = indexAt(point);
+ if(index.isValid())
{
- return;
+ menu->popup(viewport()->mapToGlobal(point));
}
- menu->popup(mapToGlobal(pos));
}
void FileList::setMaster()
{
- setMasterFile(activeItem);
+// setMasterFile(activeItem);
}
void FileList::removeFile()
{
- QString file = itemFile(activeItem);
- QString name = itemName(activeItem);
-
- printf("Removing: %s\n", file.toStdString().c_str());
- delete activeItem;//takeItem(row(activeItem));
- activeItem = NULL;
- setCurrentRow(-1);
+ auto audiofile_ids = instrument.getAudioFileList();
+ auto audiofile_id = audiofile_ids.begin() + currentIndex().row();
+ instrument.deleteAudioFile(*audiofile_id);
- emit fileRemoved(file, name);
+ //emit fileRemoved(file, name);
}
void FileList::removeAllFiles()
{
- activeItem = NULL;
-
- clear();
-
- emit allFilesRemoved();
-}
-
-void FileList::editName()
-{
- ItemEditor* e = new ItemEditor(activeItem, itemName(activeItem));
- connect(e, SIGNAL(updateItem(QListWidgetItem*, QString)),
- this, SLOT(setItemName(QListWidgetItem*, QString)));
-}
-
-
-// Item utility functions.
-QString FileList::itemFile(QListWidgetItem* i)
-{
- return i->data(Qt::ToolTipRole).toString();
-}
-
-void FileList::setItemFile(QListWidgetItem* i, QString file)
-{
- i->setData(Qt::ToolTipRole, file);
- i->setData(Qt::DisplayRole, itemName(i) + "\t" + file);
-}
-
-QString FileList::itemName(QListWidgetItem* i)
-{
- return i->data(Qt::UserRole).toString();
-}
-
-void FileList::setItemName(QListWidgetItem* i, QString name)
-{
- QString oldname = itemName(i);
-
- i->setData(Qt::UserRole, name);
- i->setData(Qt::DisplayRole, name + "\t" + itemFile(i));
-
- if(oldname != "" && oldname != name)
+ instrument.setMasterFile("");
+ auto audiofile_ids = instrument.getAudioFileList();
+ for(auto audiofile_id : audiofile_ids)
{
- emit nameChanged(itemFile(i), name);
+ instrument.deleteAudioFile(audiofile_id);
}
-}
+ reset();
-void FileList::setItemMaster(QListWidgetItem* i, bool master)
-{
- if(master)
- {
- i->setIcon(QPixmap(":icons/master.png"));
- }
- else
- {
- i->setIcon(QPixmap(":icons/file.png"));
- }
+ emit allFilesRemoved();
}
diff --git a/src/filelist.h b/src/filelist.h
index e336bc1..165af83 100644
--- a/src/filelist.h
+++ b/src/filelist.h
@@ -26,15 +26,15 @@
*/
#pragma once
-#include <QListWidget>
-#include <QListWidgetItem>
+#include <QTreeView>
#include <QAction>
#include <QMenu>
class Instrument;
+class FileDataModel;
class FileList
- : public QListWidget
+ : public QTreeView
{
Q_OBJECT
public:
@@ -44,30 +44,33 @@ public:
signals:
void masterFileChanged(QString filename);
- void fileAdded(QString file, QString name);
+// void fileAdded(QString file, QString name);
void fileRemoved(QString file, QString name);
void allFilesRemoved();
- void nameChanged(QString file, QString name);
+// void nameChanged(QString file, QString name);
public slots:
void addFiles();
- void popupMenu(const QPoint& pos);
private slots:
- void selectionChanged(QListWidgetItem* item);
+ void selectionChanged(const QModelIndex &index);
+ void onCustomContextMenu(const QPoint &point);
void setMaster();
void removeFile();
void removeAllFiles();
- void editName();
- void setItemName(QListWidgetItem* i, QString name);
-
+// void setItemName(QListWidgetItem* i, QString name);
+//
private:
- QString itemFile(QListWidgetItem* i);
- QString itemName(QListWidgetItem* i);
- void setItemFile(QListWidgetItem* i, QString file);
- void setItemMaster(QListWidgetItem* i, bool master);
-
- void setMasterFile(QListWidgetItem* i);
+// QString itemFile(QListWidgetItem* i);
+// void setItemFile(QListWidgetItem* i, QString file);
+//
+// QString itemName(QListWidgetItem* i);
+// void setItemMaster(QListWidgetItem* i, bool master);
+//
+// int itemChannelMap(QListWidgetItem* i);
+// void setItemChannelMap(QListWidgetItem* i, int id);
+//
+// void setMasterFile(QListWidgetItem* i);
void createMenus();
QMenu* menu;
@@ -76,6 +79,7 @@ private:
QAction* removeAction;
QAction* removeAllAction;
- QListWidgetItem* activeItem;
+// QListWidgetItem* activeItem;
Instrument& instrument;
+ FileDataModel* model;
};
diff --git a/src/imageeditor.cc b/src/imageeditor.cc
new file mode 100644
index 0000000..556084b
--- /dev/null
+++ b/src/imageeditor.cc
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * imageeditor.cc
+ *
+ * Tue Jul 24 11:55:43 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "imageeditor.h"
+
+#include <QLabel>
+
+ImageEditor::ImageEditor(QWidget* parent)
+ : QWidget(parent)
+{
+}
+
+ImageEditor::~ImageEditor()
+{
+}
+
+void ImageEditor::setImage(QString filename)
+{
+ QLabel *image = new QLabel(this);
+ QPixmap pic(filename);
+ QPixmap scaled = pic.scaled(width(), height(),
+ Qt::KeepAspectRatio, Qt::FastTransformation);
+ image->setPixmap(scaled);
+ image->move(0, 0);
+ image->resize(width(), height());
+}
diff --git a/src/imageeditor.h b/src/imageeditor.h
new file mode 100644
index 0000000..c2df4dc
--- /dev/null
+++ b/src/imageeditor.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * imageeditor.h
+ *
+ * Tue Jul 24 11:55:43 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <QWidget>
+
+class ImageEditor
+ : public QWidget
+{
+ Q_OBJECT
+public:
+ ImageEditor(QWidget* parent);
+ ~ImageEditor();
+
+ void setImage(QString filename);
+};
diff --git a/src/instrumentwidget.cc b/src/instrumentwidget.cc
index 0058f93..d7b0024 100644
--- a/src/instrumentwidget.cc
+++ b/src/instrumentwidget.cc
@@ -86,7 +86,7 @@ InstrumentWidget::InstrumentWidget(Settings& settings, Instrument& instrument)
central->setLayout(lv);
setCentralWidget(central);
- extractor = new AudioExtractor(instrument, selections, this);
+ extractor = new AudioExtractor(instrument, this);
canvaswidget = new CanvasWidget(this);
QToolBar* toolbar = addToolBar(tr("Tools"));
@@ -199,12 +199,6 @@ QWidget* InstrumentWidget::createFilesTab()
connect(filelist, SIGNAL(masterFileChanged(QString)),
this, SLOT(loadFile(QString)));
connect(loadbtn, SIGNAL(clicked()), filelist, SLOT(addFiles()));
- connect(filelist, SIGNAL(fileAdded(QString, QString)),
- extractor, SLOT(addFile(QString, QString)));
- connect(filelist, SIGNAL(fileRemoved(QString, QString)),
- extractor, SLOT(removeFile(QString, QString)));
- connect(filelist, SIGNAL(nameChanged(QString, QString)),
- extractor, SLOT(changeName(QString, QString)));
l->addWidget(filelist);
if(!instrument.getMasterFile().isEmpty())
@@ -366,17 +360,13 @@ QWidget* InstrumentWidget::createExportTab()
prefix = new QLineEdit();
prefix->setText(instrument.getPrefix());
connect(prefix, SIGNAL(textChanged(const QString &)),
- extractor, SLOT(setOutputPrefix(const QString &)));
- connect(prefix, SIGNAL(textChanged(const QString &)),
this, SLOT(prefixChanged()));
l->addWidget(prefix);
l->addWidget(new QLabel(tr("Export path:")));
QHBoxLayout* lo_exportp = new QHBoxLayout();
lineed_exportp = new QLineEdit();
- lineed_exportp->setText(instrument.getExportPath());
- connect(lineed_exportp, SIGNAL(textChanged(const QString &)),
- extractor, SLOT(setExportPath(const QString &)));
+ lineed_exportp->setText(instrument.getProject().getExportPath());
connect(lineed_exportp, SIGNAL(textChanged(const QString &)),
this, SLOT(exportPathChanged()));
lo_exportp->addWidget(lineed_exportp);
@@ -409,7 +399,7 @@ void InstrumentWidget::prefixChanged()
void InstrumentWidget::exportPathChanged()
{
- instrument.setExportPath(lineed_exportp->text());
+ instrument.getProject().setExportPath(lineed_exportp->text());
}
void InstrumentWidget::playSamples()
@@ -486,12 +476,12 @@ void InstrumentWidget::loadFile(QString filename)
qApp->processEvents();
sorter->setWavData(NULL, 0);
- player.setPcmData(NULL, 0);
+ player.setPcmData(NULL, 0, 0);
canvaswidget->canvas->load(filename);
sorter->setWavData(canvaswidget->canvas->data, canvaswidget->canvas->size);
- player.setPcmData(canvaswidget->canvas->data, canvaswidget->canvas->size);
+ player.setPcmData(canvaswidget->canvas->data, canvaswidget->canvas->size, canvaswidget->canvas->samplerate);
statusBar()->showMessage(tr("Ready"));
setCursor(Qt::ArrowCursor);
diff --git a/src/localehandler.cc b/src/localehandler.cc
index 6721492..9bc08c8 100644
--- a/src/localehandler.cc
+++ b/src/localehandler.cc
@@ -26,10 +26,8 @@
*/
#include "localehandler.h"
-#include <iostream>
-
#include <QApplication>
-//#include <QLocale>
+#include <QLocale>
#include <QTranslator>
#include <QString>
#include <QFile>
diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 8091d2e..4084df1 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -41,11 +41,15 @@
#include "settings.h"
#include "projectdialog.h"
+#include "renderdialog.h"
+#include "channeldialog.h"
#include "instrumentdialog.h"
#include "projectserialiser.h"
#include "instrumentwidget.h"
#include "channelswidget.h"
+#include "imageeditor.h"
+
#define MAXVAL 10000000L
MainWindow::MainWindow(Settings& settings)
@@ -82,6 +86,16 @@ MainWindow::MainWindow(Settings& settings)
fileMenu->addAction(act_quit);
connect(act_quit, SIGNAL(triggered()), this, SLOT(close()));
+ QMenu* projectMenu = menuBar()->addMenu(tr("&Project"));
+ QAction* act_render = new QAction(tr("&Render..."), this);
+ projectMenu->addAction(act_render);
+ connect(act_render, SIGNAL(triggered()), this, SLOT(render()));
+
+ QMenu* testMenu = menuBar()->addMenu(tr("Test"));
+ QAction* act_test = new QAction(tr("Test"), this);
+ testMenu->addAction(act_test);
+ connect(act_test, SIGNAL(triggered()), this, SLOT(test()));
+
instruments_dock = new QDockWidget(tr("Instruments:"), this);
instruments_dock->setObjectName("instruments_dock");
instruments_dock->setAllowedAreas(Qt::LeftDockWidgetArea);
@@ -134,13 +148,13 @@ MainWindow::MainWindow(Settings& settings)
channel_list = new QListWidget();
connect(channel_list, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
this, SLOT(channelDoubleClicked(QListWidgetItem*)));
- channel_list->addItems({"AmbL", "AmbR", "Kdrum_back", "Kdrum_front",
- "Hihat", "OHL", "OHR", "Ride","Snare_bottom",
- "Snare_top", "Tom1", "Tom2", "Tom3"});
- for(int i = 0; i < channel_list->count(); ++i)
- {
- channel_list->item(i)->setIcon(QPixmap(":icons/channel.png"));
- }
+// channel_list->addItems({"AmbL", "AmbR", "Kdrum_back", "Kdrum_front",
+// "Hihat", "OHL", "OHR", "Ride","Snare_bottom",
+// "Snare_top", "Tom1", "Tom2", "Tom3"});
+// for(int i = 0; i < channel_list->count(); ++i)
+// {
+// channel_list->item(i)->setIcon(QPixmap(":icons/channel.png"));
+// }
l->addWidget(tools);
l->addWidget(channel_list);
@@ -259,10 +273,17 @@ void MainWindow::instrumentDoubleClicked(QListWidgetItem *item)
void MainWindow::addChannel()
{
+ auto id = project.createChannel();
+ auto& channel = project.getChannel(id);
+
+ ChannelDialog dlg(this, channel);
+ dlg.show();
+ dlg.exec();
+
auto item = new QListWidgetItem();
item->setIcon(QPixmap(":icons/channel.png"));
- item->setText("New Channel");
- //item->setData(Qt::UserRole, id);
+ item->setData(Qt::UserRole, id);
+ item->setText(channel.getChannelName());
channel_list->addItem(item);
}
@@ -271,6 +292,8 @@ void MainWindow::removeChannel()
auto items = channel_list->selectedItems();
for(auto item : items)
{
+ auto id = item->data(Qt::UserRole).toInt();
+ project.deleteChannel(id);
delete item;
}
}
@@ -283,7 +306,6 @@ void MainWindow::channelDoubleClicked(QListWidgetItem *item)
tr("Channels"));
// Make new tab active
tab_widget->setCurrentIndex(tab_widget->count() - 1);
-
}
void MainWindow::updateWindowTitle()
@@ -350,6 +372,11 @@ void MainWindow::loadProject()
return;
}
+ loadProject(filename);
+}
+
+void MainWindow::loadProject(QString filename)
+{
QFile file(filename);
if(!file.open(QIODevice::ReadOnly))
{
@@ -379,6 +406,18 @@ void MainWindow::loadProject()
instrument_list->addItem(item);
}
+ channel_list->clear();
+ auto channel_ids = project.getChannelList();
+ for(auto id : channel_ids)
+ {
+ auto& channel = project.getChannel(id);
+ auto item = new QListWidgetItem();
+ item->setIcon(QPixmap(":icons/channel.png"));
+ item->setText(channel.getChannelName());
+ item->setData(Qt::UserRole, id);
+ channel_list->addItem(item);
+ }
+
statusBar()->showMessage(tr("Loaded"));
}
@@ -436,3 +475,16 @@ void MainWindow::closeTab(int tab)
{
tab_widget->removeTab(tab);
}
+
+void MainWindow::test()
+{
+ ImageEditor* e = new ImageEditor(nullptr);
+ e->setImage("/mnt/atuin/misc/stuff/deva/CrocellKit/crocellkit01.png");
+ e->show();
+}
+
+void MainWindow::render()
+{
+ RenderDialog renderDialog(this, project);
+ renderDialog.exec();
+}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index d9ab062..e4c5863 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -58,12 +58,17 @@ public slots:
void newProject();
void loadProject();
+ void loadProject(QString filename);
void saveProject();
void saveProjectAs();
void projectChanged();
void closeTab(int tab);
+private slots:
+ void test();
+ void render();
+
protected:
void closeEvent(QCloseEvent*);
diff --git a/src/player.cc b/src/player.cc
index af3cd7c..d598d9f 100644
--- a/src/player.cc
+++ b/src/player.cc
@@ -67,7 +67,7 @@ void Player::run()
ao_sample_format sf;
memset(&sf, 0, sizeof(sf));
sf.bits = 16;
- sf.rate = 44100;
+ sf.rate = pcm_samplerate;
sf.channels = 1;
sf.byte_format = AO_FMT_NATIVE;
@@ -188,10 +188,11 @@ void Player::reportTimeout()
peak = 0.0;
}
-void Player::setPcmData(float* data, size_t size)
+void Player::setPcmData(float* data, size_t size, double samplerate)
{
pcm_data = data;
pcm_size = size;
+ pcm_samplerate = samplerate;
}
void Player::setPosition(size_t position)
diff --git a/src/player.h b/src/player.h
index 8548c0a..0f5b780 100644
--- a/src/player.h
+++ b/src/player.h
@@ -53,7 +53,7 @@ public:
public slots:
//! Assign PCM data to the player.
- void setPcmData(float *data, size_t num_samples);
+ void setPcmData(float *data, size_t num_samples, double samplerate);
//! Set gain scalar.
//! This value is multiplied with each sample before it is played.
@@ -95,6 +95,7 @@ private:
float *pcm_data;
size_t pcm_size;
+ double pcm_samplerate{44100.0};
QTimer report_timer;
diff --git a/src/project.cc b/src/project.cc
index 5ad809b..86100bc 100644
--- a/src/project.cc
+++ b/src/project.cc
@@ -30,6 +30,82 @@
#include <iostream>
+AudioFile::AudioFile(Instrument& instrument, int id)
+ : id(id)
+ , instrument(instrument)
+{
+}
+
+int AudioFile::getId() const
+{
+ return id;
+}
+
+QString AudioFile::getFile() const
+{
+ return file;
+}
+
+void AudioFile::setFile(const QString& file)
+{
+ if(this->file == file)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(instrument.getProject());
+ this->file = file;
+ }
+}
+
+QString AudioFile::getAbsoluteFile() const
+{
+ if(file.left(1) != "/")
+ {
+ // Prepend root path
+ return instrument.getProject().getRawFileRoot() + "/" + file;
+ }
+
+ return file;
+}
+
+QString AudioFile::getName() const
+{
+ return name;
+}
+
+void AudioFile::setName(const QString& name)
+{
+ if(this->name == name)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(instrument.getProject());
+ this->name = name;
+ }
+}
+
+int AudioFile::getChannelMapId() const
+{
+ return channel_map_id;
+}
+
+void AudioFile::setChannelMapId(int channel_map_id)
+{
+ if(this->channel_map_id == channel_map_id)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(instrument.getProject());
+ this->channel_map_id = channel_map_id;
+ }
+}
+
Instrument::Instrument(Project& project, int id)
: id(id)
, project(project)
@@ -81,22 +157,53 @@ void Instrument::setMasterFile(const QString& master_file)
}
}
-AudioFileList Instrument::getFileList() const
+AudioFile& Instrument::getAudioFile(int id)
+{
+ for(auto& audio_file : audio_files)
+ {
+ if(audio_file.getId() == id)
+ {
+ return audio_file;
+ }
+ }
+
+ Q_ASSERT(false); // No such audio_file id.
+}
+
+int Instrument::createAudioFile()
{
- return file_list;
+ Project::RAIIBulkUpdate bulkUpdate(project);
+
+ audio_files.emplace_back(*this, project.next_id);
+ ++project.next_id;
+
+ return audio_files.back().getId();
}
-void Instrument::setFileList(const AudioFileList& file_list)
+void Instrument::deleteAudioFile(int id)
{
- if(this->file_list == file_list)
+ Project::RAIIBulkUpdate bulkUpdate(project);
+
+ for(auto it = audio_files.begin(); it != audio_files.end(); ++it)
{
- return;
+ if((*it).getId() == id)
+ {
+ audio_files.erase(it);
+ return;
+ }
}
+ Q_ASSERT(false); // No such audio_file id.
+}
+
+QList<int> Instrument::getAudioFileList() const
+{
+ QList<int> audio_file_list;
+ for(auto& audio_file : audio_files)
{
- Project::RAIIBulkUpdate bulkUpdate(project);
- this->file_list = file_list;
+ audio_file_list.push_back(audio_file.getId());
}
+ return audio_file_list;
}
std::size_t Instrument::getAttackLength() const
@@ -238,29 +345,46 @@ void Instrument::setPrefix(const QString& prefix)
}
}
-QString Instrument::getExportPath() const
+Project& Instrument::getProject()
{
- return export_path;
+ return project;
}
-void Instrument::setExportPath(const QString& export_path)
+Channel::Channel(Project& project, int id)
+ : id(id)
+ , project(project)
{
- if(this->export_path == export_path)
+}
+
+int Channel::getId() const
+{
+ return id;
+}
+
+QString Channel::getChannelName() const
+{
+ return channel_name;
+}
+
+void Channel::setChannelName(const QString& channel_name)
+{
+ if(this->channel_name == channel_name)
{
return;
}
{
Project::RAIIBulkUpdate bulkUpdate(project);
- this->export_path = export_path;
+ this->channel_name = channel_name;
}
}
-Project& Instrument::getProject()
+Project& Channel::getProject()
{
return project;
}
+
void Project::bulkUpdateBegin()
{
++update_count;
@@ -323,6 +447,24 @@ void Project::setRawFileRoot(const QString& raw_file_root)
}
}
+QString Project::getExportPath() const
+{
+ return export_path;
+}
+
+void Project::setExportPath(const QString& export_path)
+{
+ if(this->export_path == export_path)
+ {
+ return;
+ }
+
+ {
+ Project::RAIIBulkUpdate bulkUpdate(*this);
+ this->export_path = export_path;
+ }
+}
+
Instrument& Project::getInstrument(int id)
{
for(auto& instrument : instruments)
@@ -372,11 +514,61 @@ QList<int> Project::getInstrumentList() const
return instrument_list;
}
+Channel& Project::getChannel(int id)
+{
+ for(auto& channel : channels)
+ {
+ if(channel.getId() == id)
+ {
+ return channel;
+ }
+ }
+
+ Q_ASSERT(false); // No such channel id.
+}
+
+int Project::createChannel()
+{
+ RAIIBulkUpdate bulkUpdate(*this);
+
+ channels.emplace_back(*this, next_id);
+ ++next_id;
+
+ return channels.back().getId();
+}
+
+void Project::deleteChannel(int id)
+{
+ RAIIBulkUpdate bulkUpdate(*this);
+
+ for(auto it = channels.begin(); it != channels.end(); ++it)
+ {
+ if((*it).getId() == id)
+ {
+ channels.erase(it);
+ return;
+ }
+ }
+
+ Q_ASSERT(false); // No such channel id.
+}
+
+QList<int> Project::getChannelList() const
+{
+ QList<int> channel_list;
+ for(auto& channel : channels)
+ {
+ channel_list.push_back(channel.getId());
+ }
+ return channel_list;
+}
+
void Project::reset()
{
RAIIBulkUpdate bulkUpdate(*this);
setRawFileRoot("");
setProjectName("");
instruments.clear();
+ channels.clear();
next_id = 0;
}
diff --git a/src/project.h b/src/project.h
index 98be92a..b0f9060 100644
--- a/src/project.h
+++ b/src/project.h
@@ -35,6 +35,35 @@
#include "selection.h"
class Project;
+class Instrument;
+
+class AudioFile
+{
+public:
+ AudioFile(Instrument& instrument, int id);
+
+ int getId() const;
+
+ QString getFile() const;
+ void setFile(const QString& file);
+ QString getAbsoluteFile() const;
+
+ QString getName() const;
+ void setName(const QString& name);
+
+ int getChannelMapId() const;
+ void setChannelMapId(int id);
+
+private:
+ friend class ProjectSerialiser;
+
+ QString file;
+ QString name;
+ int channel_map_id;
+
+ int id;
+ Instrument& instrument;
+};
class Instrument
{
@@ -49,8 +78,10 @@ public:
QString getMasterFile() const;
void setMasterFile(const QString& master_file);
- AudioFileList getFileList() const;
- void setFileList(const AudioFileList& file_list);
+ AudioFile& getAudioFile(int id);
+ int createAudioFile();
+ void deleteAudioFile(int id);
+ QList<int> getAudioFileList() const;
std::size_t getAttackLength() const;
void setAttackLength(std::size_t attack_length);
@@ -76,9 +107,6 @@ public:
QString getPrefix() const;
void setPrefix(const QString& prefix);
- QString getExportPath() const;
- void setExportPath(const QString& prefix);
-
Project& getProject();
private:
@@ -89,7 +117,7 @@ private:
// Files tab
QString master_file;
- AudioFileList file_list;
+ std::list<AudioFile> audio_files;
// Generate tab
std::size_t attack_length{300};
@@ -106,7 +134,28 @@ private:
// Export tab
QString prefix;
- QString export_path;
+
+ Project& project;
+};
+
+class Channel
+{
+public:
+ Channel(Project& project, int id);
+
+ int getId() const;
+
+ QString getChannelName() const;
+ void setChannelName(const QString& channel_name);
+
+ Project& getProject();
+
+private:
+ friend class ProjectSerialiser;
+
+ int id;
+
+ QString channel_name;
Project& project;
};
@@ -145,11 +194,19 @@ public:
QString getRawFileRoot() const;
void setRawFileRoot(const QString& raw_file_root);
+ QString getExportPath() const;
+ void setExportPath(const QString& prefix);
+
Instrument& getInstrument(int id);
int createInstrument();
void deleteInstrument(int id);
QList<int> getInstrumentList() const;
+ Channel& getChannel(int id);
+ int createChannel();
+ void deleteChannel(int id);
+ QList<int> getChannelList() const;
+
void reset();
signals:
@@ -157,12 +214,15 @@ signals:
private:
friend class ProjectSerialiser;
+ friend class Instrument;
QString project_file;
QString project_name;
QString raw_file_root;
+ QString export_path;
std::list<Instrument> instruments;
+ std::list<Channel> channels;
int next_id{0};
int update_count{0};
diff --git a/src/projectrenderer.cc b/src/projectrenderer.cc
new file mode 100644
index 0000000..e1856cb
--- /dev/null
+++ b/src/projectrenderer.cc
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * projectrender.cc
+ *
+ * Sat Sep 22 10:35:01 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "projectrenderer.h"
+
+#include <QDomDocument>
+#include <QFile>
+#include <QApplication>
+
+#include "project.h"
+#include "audioextractor.h"
+
+ProjectRenderer::ProjectRenderer(Project& project)
+ : project(project)
+{
+}
+
+void ProjectRenderer::render()
+{
+ QDomDocument doc;
+ QDomProcessingInstruction header =
+ doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
+ doc.appendChild(header);
+
+ QDomElement drumkit = doc.createElement("drumkit");
+ drumkit.setAttribute("version", "1.0");
+ drumkit.setAttribute("name", project.getProjectName());
+// drumkit.setAttribute("description", project.getProjectDescription());
+ doc.appendChild(drumkit);
+
+ QDomElement channels = doc.createElement("channels");
+ drumkit.appendChild(channels);
+
+ auto channel_ids = project.getChannelList();
+ for(auto channel_id : channel_ids)
+ {
+ const auto& channel = project.getChannel(channel_id);
+ QDomElement channel_node = doc.createElement("channel");
+ channel_node.setAttribute("name", channel.getChannelName());
+ channels.appendChild(channel_node);
+ }
+
+ QDomElement instruments = doc.createElement("instruments");
+ drumkit.appendChild(instruments);
+
+ auto instrument_ids = project.getInstrumentList();
+
+ emit progressStart(instrument_ids.count());
+ qApp->processEvents();
+
+ for(auto instrument_id : instrument_ids)
+ {
+ auto& instrument = project.getInstrument(instrument_id);
+ emit progressTask(tr("Writing instrument: ") +
+ instrument.getInstrumentName());
+
+ {
+ auto selections = instrument.getSelections().ids();
+ emit progressRenderStart(selections.count());
+ qApp->processEvents();
+ }
+
+ AudioExtractor extractor(instrument, this);
+ connect(&extractor, SIGNAL(progressUpdate(int)),
+ this, SIGNAL(progressRenderTask(int)));
+
+ extractor.exportSelections();
+
+ QDomElement instrument_node = doc.createElement("instrument");
+ instrument_node.setAttribute("name", instrument.getInstrumentName());
+ QString file = instrument.getPrefix() + "/" + instrument.getPrefix() + ".xml";
+ instrument_node.setAttribute("file", file);
+ instruments.appendChild(instrument_node);
+ auto audiofile_ids = instrument.getAudioFileList();
+ for(auto audiofile_id : audiofile_ids)
+ {
+ const auto& audiofile = instrument.getAudioFile(audiofile_id);
+ if(audiofile.getChannelMapId() == -1)
+ {
+ // Not mapped
+ continue;
+ }
+ QDomElement channelmap = doc.createElement("channelmap");
+ channelmap.setAttribute("in", audiofile.getName());
+ const auto& channel = project.getChannel(audiofile.getChannelMapId());
+ channelmap.setAttribute("out", channel.getChannelName());
+ instrument_node.appendChild(channelmap);
+ }
+
+ emit progressRenderFinished(0);
+ qApp->processEvents();
+ }
+
+ QFile xmlfile(project.getExportPath() + "/drumkit.xml");
+ xmlfile.open(QIODevice::WriteOnly);
+ xmlfile.write(doc.toByteArray());
+ xmlfile.close();
+
+ emit progressFinished(0);
+ qApp->processEvents();
+}
diff --git a/src/projectrenderer.h b/src/projectrenderer.h
new file mode 100644
index 0000000..a92b049
--- /dev/null
+++ b/src/projectrenderer.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * projectrender.h
+ *
+ * Sat Sep 22 10:35:00 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <QObject>
+
+class Project;
+
+class ProjectRenderer
+ : public QObject
+{
+ Q_OBJECT
+public:
+ ProjectRenderer(Project& project);
+
+ void render();
+
+signals:
+ void progressStart(int total);
+ void progressTask(QString text);
+
+ void progressRenderStart(int tasktotal);
+ void progressRenderTask(int subtask);
+ void progressRenderFinished(int success);
+
+ void progressFinished(int success);
+
+private:
+ Project& project;
+};
diff --git a/src/projectserialiser.cc b/src/projectserialiser.cc
index f80fa36..ced4636 100644
--- a/src/projectserialiser.cc
+++ b/src/projectserialiser.cc
@@ -122,6 +122,23 @@ QString ProjectSerialiser::serialise(const Project& project)
raw_file_root.appendChild(doc.createTextNode(project.raw_file_root));
dgedit.appendChild(raw_file_root);
+ auto export_path = doc.createElement("export_path");
+ export_path.appendChild(doc.createTextNode(project.export_path));
+ dgedit.appendChild(export_path);
+
+ dgedit.setAttribute("next_id", project.next_id);
+
+ auto channels = doc.createElement("channels");
+ dgedit.appendChild(channels);
+
+ for(const auto& c : project.channels)
+ {
+ auto channel = doc.createElement("channel");
+ channel.setAttribute("id", c.getId());
+ channel.setAttribute("name", c.getChannelName());
+ channels.appendChild(channel);
+ }
+
auto instruments = doc.createElement("instruments");
dgedit.appendChild(instruments);
@@ -129,6 +146,8 @@ QString ProjectSerialiser::serialise(const Project& project)
{
auto instrument = doc.createElement("instrument");
+ instrument.setAttribute("id", (int)i.getId());
+
instrument.setAttribute("attack_length", (int)i.getAttackLength());
instrument.setAttribute("power_spread", (int)i.getPowerSpread());
instrument.setAttribute("minimum_size", (int)i.getMinimumSize());
@@ -137,12 +156,11 @@ QString ProjectSerialiser::serialise(const Project& project)
instrument.setAttribute("threshold", i.getThreshold());
- instruments.appendChild(instrument);
+ auto prefix = doc.createElement("prefix");
+ prefix.appendChild(doc.createTextNode(i.getPrefix()));
+ instrument.appendChild(prefix);
- auto export_path = doc.createElement("export_path");
- export_path.setAttribute("prefix", i.getPrefix());
- export_path.appendChild(doc.createTextNode(i.export_path));
- instrument.appendChild(export_path);
+ instruments.appendChild(instrument);
auto instrument_name = doc.createElement("instrument_name");
instrument_name.appendChild(doc.createTextNode(i.instrument_name));
@@ -151,12 +169,14 @@ QString ProjectSerialiser::serialise(const Project& project)
auto file_list = doc.createElement("file_list");
instrument.appendChild(file_list);
- for(const auto& f : i.file_list)
+ for(const auto& audiofile : i.audio_files)
{
auto file = doc.createElement("file");
- file.appendChild(doc.createTextNode(f.first));
- file.setAttribute("name", f.second);
- file.setAttribute("master", i.master_file == f.first);
+ file.appendChild(doc.createTextNode(audiofile.getFile()));
+ file.setAttribute("id", audiofile.getId());
+ file.setAttribute("name", audiofile.getName());
+ file.setAttribute("channel_map_id", audiofile.getChannelMapId());
+ file.setAttribute("master", i.master_file == audiofile.getAbsoluteFile());
file_list.appendChild(file);
}
@@ -201,31 +221,47 @@ bool ProjectSerialiser::deserialise(const QString& data, Project& project)
return false;
}
+ project.next_id = dom["next_id"].toInt();
project.project_name = dom("project_name").text();
project.raw_file_root = dom("raw_file_root").text();
+ project.export_path = dom("export_path").text();
+
+ auto channels = dom("channels").children("channel");
+ for(auto& channel : channels)
+ {
+ auto id = channel["id"].toInt();
+ project.channels.emplace_back(Channel(project, id));
+
+ auto& ch = project.channels.back();
+ ch.channel_name = channel["name"];
+ }
auto instruments = dom("instruments").children("instrument");
for(auto& instrument : instruments)
{
- project.instruments.emplace_back(Instrument(project, project.next_id));
- ++project.next_id;
+ auto id = instrument["id"].toInt();
+ project.instruments.emplace_back(Instrument(project, id));
auto& instr = project.instruments.back();
instr.instrument_name = instrument("instrument_name").text();
QString master_file;
- AudioFileList file_list;
auto files = instrument("file_list").children("file");
for(auto& file : files)
{
+ auto id = file["id"].toInt();
+ instr.audio_files.emplace_back(AudioFile(instr, id));
+ auto& audiofile = instr.audio_files.back();
+ audiofile.file = file.text();
+ audiofile.name = file["name"];
+ audiofile.channel_map_id = file["channel_map_id"].toInt();
+
if(file["master"] == "1")
{
- master_file = file.text();
+ master_file = audiofile.getAbsoluteFile();
}
- file_list.push_back(qMakePair(file.text(), file["name"]));
}
- instr.file_list = file_list;
instr.master_file = master_file;
instr.attack_length = instrument["attack_length"].toInt();
@@ -236,8 +272,7 @@ bool ProjectSerialiser::deserialise(const QString& data, Project& project)
instr.threshold = instrument["threshold"].toFloat();
- instr.export_path = instrument("export_path").text();
- instr.prefix = instrument("export_path")["prefix"];
+ instr.prefix = instrument("prefix").text();
auto selections = instrument("regions");
instr.selections.nextid = selections["nextid"].toInt();
diff --git a/src/renderdialog.cc b/src/renderdialog.cc
new file mode 100644
index 0000000..9dc1c05
--- /dev/null
+++ b/src/renderdialog.cc
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * renderdialog.cc
+ *
+ * Thu Sep 20 17:32:11 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "renderdialog.h"
+
+#include <QPushButton>
+#include <QVBoxLayout>
+
+RenderDialog::RenderDialog(QWidget* parent, Project& project)
+ : QDialog(parent)
+ , project(project)
+ , renderer(project)
+{
+ setLayout(new QVBoxLayout());
+
+ auto btn = new QPushButton(this);
+ btn->setText("Click me");
+ connect(btn, SIGNAL(clicked()), this, SLOT(render()));
+ //connect(btn, SIGNAL(clicked()), this, SLOT(close()));
+ layout()->addWidget(btn);
+
+ bar1 = new QProgressBar(this);
+ connect(&renderer, SIGNAL(progressStart(int)),
+ bar1, SLOT(setMaximum(int)));
+ layout()->addWidget(bar1);
+
+ bar2 = new QProgressBar(this);
+ connect(&renderer, SIGNAL(progressRenderStart(int)),
+ bar2, SLOT(setMaximum(int)));
+ connect(&renderer, SIGNAL(progressRenderTask(int)),
+ bar2, SLOT(setValue(int)));
+ layout()->addWidget(bar2);
+
+ tasks = new QListWidget(this);
+// connect(&renderer, SIGNAL(progressTask(QString)),
+// tasks, SLOT(addItem(QString)));
+ layout()->addWidget(tasks);
+
+ connect(&renderer, SIGNAL(progressTask(QString)),
+ this, SLOT(progressTask(QString)));
+ connect(&renderer, SIGNAL(progressRenderFinished(int)),
+ this, SLOT(progressRenderFinished(int)));
+}
+
+void RenderDialog::render()
+{
+ bar1->setValue(1);
+ renderer.render();
+}
+
+void RenderDialog::progressStart(int total)
+{
+}
+
+void RenderDialog::progressTask(QString text)
+{
+ tasks->addItem(text);
+}
+
+void RenderDialog::progressRenderStart(int tasktotal)
+{
+}
+
+void RenderDialog::progressRenderTask(int subtask)
+{
+}
+
+void RenderDialog::progressRenderFinished(int success)
+{
+ bar1->setValue(bar1->value() + 1);
+}
+
+void RenderDialog::progressFinished(int success)
+{
+}
diff --git a/src/renderdialog.h b/src/renderdialog.h
new file mode 100644
index 0000000..84f0b30
--- /dev/null
+++ b/src/renderdialog.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * renderdialog.h
+ *
+ * Thu Sep 20 17:32:11 CEST 2018
+ * Copyright 2018 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <QDialog>
+#include <QProgressBar>
+#include <QListWidget>
+
+#include "projectrenderer.h"
+
+class Project;
+
+class RenderDialog
+ : public QDialog
+{
+ Q_OBJECT
+public:
+ RenderDialog(QWidget* parent, Project& project);
+
+private slots:
+ void render();
+
+ void progressStart(int total);
+ void progressTask(QString text);
+
+ void progressRenderStart(int tasktotal);
+ void progressRenderTask(int subtask);
+ void progressRenderFinished(int success);
+
+ void progressFinished(int success);
+
+private:
+ Project& project;
+ ProjectRenderer renderer;
+
+ QProgressBar* bar1;
+ QProgressBar* bar2;
+
+ QListWidget* tasks;
+};