/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * mainwindow.cc * * Tue Nov 10 10:21:04 CET 2009 * Copyright 2009 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 "mainwindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sleep.h" #include "canvastool.h" #include "canvastoolthreshold.h" #include "volumefader.h" #include "selectioneditor.h" #define MAXVAL 10000000L #define SINGLESTEP MAXVAL/100000 #define PAGESTEP MAXVAL/10000 static void addTool(QToolBar *toolbar, Canvas *canvas, CanvasTool *tool) { QAction *action = new QAction(tool->name(), toolbar); action->setCheckable(true); toolbar->addAction(action); tool->connect(action, SIGNAL(toggled(bool)), tool, SLOT(setActive(bool))); tool->setActive(false); canvas->tools.push_back(tool); } MainWindow::MainWindow() { { int start = 44100 * 60; Selection p(start, start + 44100 * 60, 0, 0); // one minute selection selections_preview.add(p); } QWidget *central = new QWidget(); QHBoxLayout *lh = new QHBoxLayout(); QVBoxLayout *lv = new QVBoxLayout(); central->setLayout(lv); setCentralWidget(central); extractor = new AudioExtractor(selections, this); canvas = new Canvas(this); QToolBar *toolbar = addToolBar("Tools"); listen = new CanvasToolListen(canvas, player); addTool(toolbar, canvas, listen); threshold = new CanvasToolThreshold(canvas); canvas->tools.push_back(threshold);//addTool(toolbar, canvas, threshold); tool_selections = new CanvasToolSelections(canvas, selections, selections_preview); connect(threshold, SIGNAL(thresholdChanged(double)), tool_selections, SLOT(thresholdChanged(double))); connect(threshold, SIGNAL(thresholdChanging(double)), tool_selections, SLOT(thresholdChanged(double))); connect(&selections, SIGNAL(activeChanged(sel_id_t)), canvas, SLOT(update())); connect(&selections, SIGNAL(updated(sel_id_t)), canvas, SLOT(update())); addTool(toolbar, canvas, tool_selections); QMenu *fileMenu = menuBar()->addMenu("&File"); QAction *act_quit = new QAction("&Quit", this); fileMenu->addAction(act_quit); connect(act_quit, SIGNAL(triggered()), this, SLOT(close())); // QWidget *dock = new QWidget(); yoffset = new QScrollBar(Qt::Vertical); yoffset->setRange(0, MAXVAL); yoffset->setPageStep(PAGESTEP); yoffset->setSingleStep(SINGLESTEP); connect(yoffset, SIGNAL(valueChanged(int)), this, SLOT(setYOffset(int))); yscale = new QScrollBar(Qt::Vertical); yscale->setRange(0, MAXVAL); yscale->setPageStep(PAGESTEP); yscale->setSingleStep(SINGLESTEP); connect(yscale, SIGNAL(valueChanged(int)), this, SLOT(setYScale(int))); xscale = new QScrollBar(Qt::Horizontal); xscale->setRange(0, MAXVAL); xscale->setPageStep(PAGESTEP); xscale->setSingleStep(SINGLESTEP); connect(xscale, SIGNAL(valueChanged(int)), this, SLOT(setXScale(int))); xoffset = new QScrollBar(Qt::Horizontal); xoffset->setRange(0, MAXVAL); xoffset->setPageStep(PAGESTEP); xoffset->setSingleStep(SINGLESTEP); connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int))); sorter = new SampleSorter(selections, selections_preview); connect(&selections, SIGNAL(added(sel_id_t)), sorter, SLOT(addSelection(sel_id_t))); connect(&selections_preview, SIGNAL(added(sel_id_t)), sorter, SLOT(addSelectionPreview(sel_id_t))); connect(&selections, SIGNAL(updated(sel_id_t)), sorter, SLOT(relayout())); connect(&selections_preview, SIGNAL(updated(sel_id_t)), sorter, SLOT(relayout())); connect(&selections, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout())); connect(&selections_preview, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout())); connect(&selections, SIGNAL(activeChanged(sel_id_t)), sorter, SLOT(relayout())); QPushButton *btn_playsamples = new QPushButton("Play samples"); connect(btn_playsamples, SIGNAL(clicked()), this, SLOT(playSamples())); sb_playsamples = new QScrollBar(Qt::Horizontal); sb_playsamples->setRange(100, 4000); // ms lh->addWidget(canvas); lh->addWidget(yscale); lh->addWidget(yoffset); lv->addLayout(lh, 100); lv->addWidget(xscale, 100); lv->addWidget(xoffset, 100); lv->addWidget(sorter, 15); lv->addWidget(btn_playsamples); lv->addWidget(sb_playsamples); QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this); dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); dockWidget->setWidget(new QWidget()); dockWidget->widget()->setLayout(new QVBoxLayout()); // dockWidget->widget()->layout()->addWidget(new QLabel("Presets:")); // presets = new QComboBox(); // connect(presets, SIGNAL(currentIndexChanged(int)), // this, SLOT(setPreset(int))); // dockWidget->widget()->layout()->addWidget(presets); tabs = new QTabWidget(this); tabs->addTab(createFilesTab(), "Files"); generateTabId = tabs->addTab(createGenerateTab(), "Generate"); tabs->addTab(createEditTab(), "Edit"); tabs->addTab(createExportTab(), "Export"); connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); tabChanged(tabs->currentIndex()); dockWidget->widget()->layout()->addWidget(tabs); VolumeFader *vol = new VolumeFader(); connect(vol, SIGNAL(volumeChangedDb(double)), &player, SLOT(setGainDB(double))); connect(&player, SIGNAL(peakUpdate(double)), vol, SLOT(updatePeakPower(double))); // connect(&player, SIGNAL(peakUpdateDB(double)), // vol, SLOT(updatePeakDb(double))); vol->setVolumeDb(0); dockWidget->widget()->layout()->addWidget(vol); addDockWidget(Qt::LeftDockWidgetArea, dockWidget); yscale->setValue(MAXVAL); yoffset->setValue(MAXVAL/2); xscale->setValue(0); xoffset->setValue(0); loadSettings(); /* QSettings settings("presets.ini", QSettings::IniFormat); QStringList list = settings.childGroups(); for(int i = 0; i != list.size(); i++) { QString presetname = list.at(i); Preset p; settings.beginGroup(presetname); p.prefix = settings.value("prefix", "unknown").toString(); p.attacklength = settings.value("attacklength", 0).toInt(); p.falloff = settings.value("falloff", 0).toInt(); p.fadelength = settings.value("fadelength", 0).toInt(); settings.endGroup(); QVariant v; v.setValue(p); presets->addItem(presetname, v); } */ statusBar()->showMessage("Ready"); } MainWindow::~MainWindow() { } void MainWindow::tabChanged(int tabid) { tool_selections->setShowPreview(tabid == generateTabId); sorter->setShowPreview(tabid == generateTabId); tool_selections->autoCreateSelectionsPreview(); threshold->setActive(tabid == generateTabId); } QWidget *MainWindow::createFilesTab() { QWidget *w = new QWidget(); QVBoxLayout *l = new QVBoxLayout(); w->setLayout(l); l->addWidget(new QLabel("Files: (double-click to set as master)")); QPushButton *loadbtn = new QPushButton(); loadbtn->setText("Add files..."); l->addWidget(loadbtn); filelist = new FileList(); 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); return w; } QWidget *MainWindow::createEditTab() { SelectionEditor *se = new SelectionEditor(selections); connect(&selections, SIGNAL(added(sel_id_t)), se, SLOT(added(sel_id_t))); connect(&selections, SIGNAL(updated(sel_id_t)), se, SLOT(updated(sel_id_t))); connect(&selections, SIGNAL(removed(sel_id_t)), se, SLOT(removed(sel_id_t))); connect(&selections, SIGNAL(activeChanged(sel_id_t)), se, SLOT(activeChanged(sel_id_t))); return se; } QSlider *createAttribute(QWidget *parent, QString name, int range_from, int range_to) { QSlider *slider; QGridLayout *l = new QGridLayout(); l->addWidget(new QLabel(name), 0, 0, 1, 2); QSpinBox *spin = new QSpinBox(); spin->setRange(range_from, range_to); l->addWidget(spin, 1, 0, 1, 1); slider = new QSlider(Qt::Horizontal); slider->setRange(range_from, range_to); l->addWidget(slider, 1, 1, 1,1); QObject::connect(spin, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int))); QObject::connect(slider, SIGNAL(valueChanged(int)), spin, SLOT(setValue(int))); ((QBoxLayout *)parent->layout())->addLayout(l); return slider; } QWidget *MainWindow::createGenerateTab() { QWidget *w = new QWidget(); QVBoxLayout *l = new QVBoxLayout(); w->setLayout(l); QHBoxLayout *btns = new QHBoxLayout(); QPushButton *autosel = new QPushButton(); autosel->setText("Generate"); connect(autosel, SIGNAL(clicked()), tool_selections, SLOT(clearSelections())); connect(autosel, SIGNAL(clicked()), tool_selections, SLOT(autoCreateSelections())); connect(threshold, SIGNAL(thresholdChanged(double)), tool_selections, SLOT(autoCreateSelectionsPreview())); connect(threshold, SIGNAL(thresholdChanging(double)), tool_selections, SLOT(autoCreateSelectionsPreview())); QPushButton *clearsel = new QPushButton(); clearsel->setText("Clear"); connect(clearsel, SIGNAL(clicked()), tool_selections, SLOT(clearSelections())); btns->addWidget(autosel); btns->addWidget(clearsel); l->addLayout(btns); slider_attacklength = createAttribute(w, "Attack length:", 10, 1000); connect(slider_attacklength, SIGNAL(valueChanged(int)), sorter, SLOT(setAttackLength(int))); connect(slider_attacklength, SIGNAL(valueChanged(int)), tool_selections, SLOT(autoCreateSelectionsPreview())); slider_attacklength->setValue(300); slider_hold = createAttribute(w, "Minimum size (samples):", 0, 200000); connect(slider_hold, SIGNAL(valueChanged(int)), tool_selections, SLOT(holdChanged(int))); connect(slider_hold, SIGNAL(valueChanged(int)), tool_selections, SLOT(autoCreateSelectionsPreview())); slider_hold->setValue(100); slider_falloff = createAttribute(w, "Falloff:", 10, 5000); connect(slider_falloff, SIGNAL(valueChanged(int)), tool_selections, SLOT(noiseFloorChanged(int))); connect(slider_falloff, SIGNAL(valueChanged(int)), tool_selections, SLOT(autoCreateSelectionsPreview())); slider_falloff->setValue(300); slider_fadelength = createAttribute(w, "Fadelength:", 0, 2000); connect(slider_fadelength, SIGNAL(valueChanged(int)), tool_selections, SLOT(fadeoutChanged(int))); connect(slider_fadelength, SIGNAL(valueChanged(int)), tool_selections, SLOT(autoCreateSelectionsPreview())); slider_fadelength->setValue(666); l->addStretch(); return w; } QWidget *MainWindow::createExportTab() { QWidget *w = new QWidget(); QVBoxLayout *l = new QVBoxLayout(); w->setLayout(l); l->addWidget(new QLabel("Prefix:")); prefix = new QLineEdit(); connect(prefix, SIGNAL(textChanged(const QString &)), extractor, SLOT(setOutputPrefix(const QString &))); l->addWidget(prefix); l->addWidget(new QLabel("Export path:")); QHBoxLayout *lo_exportp = new QHBoxLayout(); lineed_exportp = new QLineEdit(); connect(lineed_exportp, SIGNAL(textChanged(const QString &)), extractor, SLOT(setExportPath(const QString &))); lo_exportp->addWidget(lineed_exportp); QPushButton *btn_browse = new QPushButton("..."); connect(btn_browse, SIGNAL(clicked()), this, SLOT(browse())); lo_exportp->addWidget(btn_browse); l->addLayout(lo_exportp); QPushButton *exportsel = new QPushButton(); exportsel->setText("Export"); connect(exportsel, SIGNAL(clicked()), this, SLOT(doExport())); l->addWidget(exportsel); QProgressBar *bar = new QProgressBar(); connect(extractor, SIGNAL(progressUpdate(int)), bar, SLOT(setValue(int))); connect(extractor, SIGNAL(setMaximumProgress(int)), bar, SLOT(setMaximum(int))); l->addWidget(bar); l->addStretch(); return w; } void MainWindow::playSamples() { Selections *sels = &selections; if(tabs->currentIndex() == generateTabId) sels = &selections_preview; QVector ids = sels->ids(); for(int v1 = 0; v1 < ids.size(); v1++) { for(int v2 = 0; v2 < ids.size(); v2++) { Selection sel1 = sels->get(ids[v1]); Selection sel2 = sels->get(ids[v2]); if(sel1.energy < sel2.energy) { sel_id_t vtmp = ids[v1]; ids[v1] = ids[v2]; ids[v2] = vtmp; } } } QVector::iterator i = ids.begin(); while(i != ids.end()) { Selection sel = sels->get(*i); unsigned int length = sb_playsamples->value() * 44100 / 1000; unsigned int sample_length = sel.to - sel.from; unsigned int to = sel.to; if(sample_length > length) to = sel.from + length; sels->setActive(*i); connect(&player, SIGNAL(positionUpdate(size_t)), listen, SLOT(update(size_t))); player.playSelection(sel, to - sel.from); QTime t; t.start(); while(t.elapsed() < sb_playsamples->value()) { qApp->processEvents(); q_usleep(25 * 1000); } player.stop(); disconnect(&player, SIGNAL(positionUpdate(size_t)), listen, SLOT(update(size_t))); i++; } } void MainWindow::closeEvent(QCloseEvent *) { saveSettings(); QApplication::quit(); } void MainWindow::loadSettings() { QSettings settings; settings.beginGroup("MainWindow"); lineed_exportp->setText(settings.value("exportpath", "").toString()); filelist->path = settings.value("loadpath", "").toString(); resize(settings.value("size", QSize(700, 800)).toSize()); move(settings.value("pos", QPoint(0, 0)).toPoint()); settings.endGroup(); } void MainWindow::saveSettings() { QSettings settings; settings.beginGroup("MainWindow"); settings.setValue("loadpath", filelist->path); settings.setValue("exportpath", lineed_exportp->text()); settings.setValue("size", size()); settings.setValue("pos", pos()); settings.endGroup(); } void MainWindow::setXScale(int sz) { // range 0.0 - 1.0 float val = (float)(sz * -1 + MAXVAL)/(float)MAXVAL; canvas->setXScale(val); if(val < 0.001) val = 0.001; xoffset->setPageStep(PAGESTEP * 10 * val); xoffset->setSingleStep(SINGLESTEP * 10 * val); } void MainWindow::setYScale(int sz) { // range 0.0 - 1.0 float val = (float)(sz * -1 + MAXVAL)/(float)MAXVAL; canvas->setYScale(val); } void MainWindow::setXOffset(int of) { // range 0.0 - 1.0 float val = (float)of/(float)MAXVAL; canvas->setXOffset(val); } void MainWindow::setYOffset(int of) { // range 0.0 - 1.0 float val = (float)(of * -1 + MAXVAL)/(float)MAXVAL; canvas->setYOffset(val); } void MainWindow::doExport() { extractor->exportSelections(); } void MainWindow::loadFile(QString filename) { setCursor(Qt::WaitCursor); statusBar()->showMessage("Loading..."); qApp->processEvents(); sorter->setWavData(NULL, 0); player.setPcmData(NULL, 0); canvas->load(filename); sorter->setWavData(canvas->data, canvas->size); player.setPcmData(canvas->data, canvas->size); statusBar()->showMessage("Ready"); setCursor(Qt::ArrowCursor); } void MainWindow::setPreset(int index) { /* QVariant v = presets->itemData(index); Preset p = v.value(); slider_attacklength->setValue(p.attacklength); slider_falloff->setValue(p.falloff); slider_fadelength->setValue(p.fadelength); prefix->setText(p.prefix); */ } void MainWindow::browse() { QString path = QFileDialog::getExistingDirectory(this, "Select export path", lineed_exportp->text()); lineed_exportp->setText(path); }