Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:fritz_van_tom:stringtune
stringtune
stringtune.cpp
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File stringtune.cpp of Package stringtune
/* Stringtune - Plasmoid to tune your string instruments Copyright (C) 2010 Nessmo Tröscher (fritz_van_tom@hotmail.com) This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "stringtune.h" #include <plasma/theme.h> #include <plasma/widgets/pushbutton.h> #include <plasma/widgets/combobox.h> #include <KConfigDialog> #include <KLocale> #include <KSharedConfig> #include <KFileDialog> #include <KUser> #include <KComboBox> #include <KIO/NetAccess> #include <KTemporaryFile> #include <vector> #include <QFile> const QString notesNames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; stringtune::stringtune(QObject *parent, const QVariantList &args) : Plasma::Applet(parent, args), mainLayout(0), layoutControls(0), layoutStrings(0), btnConfig(0), btnEditInstrument(0), btnAbortEdit(0), btnAddString(0), btnRemString(0), midiOut(0) { edit = false; midiWorks = false; currentInstrument = 0; LastStringPlayed = 255; setHasConfigurationInterface(true); setBackgroundHints(DefaultBackground); setMaximumHeight(100); setAspectRatioMode(Plasma::IgnoreAspectRatio); resize(250, 100); } stringtune::~stringtune() { delete midiOut; } void stringtune::init() { mainLayout = new QGraphicsLinearLayout(this); mainLayout->setOrientation(Qt::Vertical); layoutControls = new QGraphicsLinearLayout; layoutStrings = new QGraphicsLinearLayout; btnConfig = new Plasma::PushButton; btnConfig->setText(i18n("Configure")); btnConfig->setToolTip(i18n("Configure")); btnConfig->setVisible(false); connect(btnConfig, SIGNAL(clicked()), this, SLOT(showConfigurationInterface())); btnEditInstrument = new Plasma::PushButton(this); btnEditInstrument->setIcon(KIcon("document-edit")); btnEditInstrument->setToolTip(i18n("edit Instrument")); btnEditInstrument->setMaximumWidth(40); connect(btnEditInstrument, SIGNAL(clicked()), this, SLOT(editTuning())); btnAbortEdit = new Plasma::PushButton; btnAbortEdit->setIcon(KIcon("dialog-cancel")); btnAbortEdit->setToolTip(i18n("cancel")); btnAbortEdit->setVisible(false); btnAbortEdit->setMaximumWidth(40); connect(btnAbortEdit, SIGNAL(clicked()), this, SLOT(abortEdit())); btnAddString = new Plasma::PushButton(this); btnAddString->setIcon(KIcon("list-add")); btnAddString->setToolTip(i18n("add string")); btnAddString->setVisible(false); btnAddString->setMaximumWidth(40); connect(btnAddString, SIGNAL(clicked()), this, SLOT(addString())); btnRemString = new Plasma::PushButton(this); btnRemString->setIcon(KIcon("list-remove")); btnRemString->setToolTip(i18n("remove string")); btnRemString->setVisible(false); btnRemString->setMaximumWidth(40); connect(btnRemString, SIGNAL(clicked()), this, SLOT(remString())); cmbInstruments = new Plasma::ComboBox(this); cmbInstruments->setToolTip(i18n("change instrument")); connect(cmbInstruments->nativeWidget(), SIGNAL(currentIndexChanged(int)), this, SLOT(changeInstrument(int))); layoutControls->addItem(cmbInstruments); layoutControls->addItem(btnEditInstrument); DontKnowANameYetForThisOne(); } //////////////////////////////////////////// //////////////GUIStuff////////////////////// void stringtune::doLayout() { if (edit) { for (int i = 0; i < btnPlayString.count(); i++) { btnPlayString[i]->setVisible(false); layoutStrings->removeItem(btnPlayString[i]); } for (int i = 0; i < cmbChangeTuning.count(); i++) { layoutStrings->insertItem(i,cmbChangeTuning[i]); cmbChangeTuning[i]->setVisible(true); } layoutControls->addItem(btnAbortEdit); layoutStrings->addItem(btnAddString); layoutStrings->addItem(btnRemString); } else { layoutControls->removeItem(btnAbortEdit); layoutStrings->removeItem(btnAddString); layoutStrings->removeItem(btnRemString); for (int i = 0; i < cmbChangeTuning.count(); i++) { cmbChangeTuning[i]->setVisible(false); layoutStrings->removeItem(cmbChangeTuning[i]); } for (int i = 0; i < btnPlayString.count(); i++) { layoutStrings->insertItem(i,btnPlayString[i]); btnPlayString[i]->setVisible(true); } } } void stringtune::DontKnowANameYetForThisOne() { if (!loadConfig()) { mainLayout->addItem(btnConfig); btnConfig->setVisible(true); if (layoutControls->parentLayoutItem() == mainLayout) { mainLayout->removeItem(layoutControls); mainLayout->removeItem(layoutStrings); } cmbInstruments->setVisible(false); btnEditInstrument->setVisible(false); } else { btnConfig->setVisible(false); if (btnConfig->parentLayoutItem() == mainLayout) { mainLayout->removeItem(btnConfig); } if (layoutControls->parentLayoutItem() != mainLayout) { mainLayout->addItem(layoutControls); mainLayout->addItem(layoutStrings); } cmbInstruments->setVisible(true); btnEditInstrument->setVisible(true); } } void stringtune::redimControls() { QSignalMapper *SignalMapper = new QSignalMapper(this); //btnPlayString if (tmpTuning.count() == 2) { btnRemString->setEnabled(true); } if (tmpTuning.count() == 1) { btnRemString->setEnabled(false); } while (btnPlayString.count() < instruments[currentInstrument].stringCount()) { btnPlayString.push_back(new Plasma::PushButton); } while (btnPlayString.count() > instruments[currentInstrument].stringCount()) { delete btnPlayString[btnPlayString.count()-1]; btnPlayString.pop_back(); } for (int i = 0; i < instruments[currentInstrument].stringCount() && edit == false; i++) { SignalMapper->removeMappings(btnPlayString[i]); btnPlayString[i]->disconnect(); btnPlayString[i]->setMaximumWidth(40); btnPlayString[i]->setText(note_midinumberConversion(instruments[currentInstrument].strings[i])); connect(btnPlayString[i], SIGNAL(clicked()), SignalMapper, SLOT(map())); SignalMapper->setMapping(btnPlayString[i], i); } //cmbChangeTuning while (cmbChangeTuning.count() < tmpTuning.count()) { cmbChangeTuning.push_back(new Plasma::ComboBox); cmbChangeTuning[cmbChangeTuning.count() -1]->setMaximumWidth(60); } while (cmbChangeTuning.count() > tmpTuning.count()) { delete cmbChangeTuning[cmbChangeTuning.count()-1]; cmbChangeTuning.pop_back(); } for (int i = 0; i < cmbChangeTuning.count() && edit == true; i++) { cmbChangeTuning[i]->clear(); for (int j = 21; j <= 108; j++) { cmbChangeTuning[i]->addItem(note_midinumberConversion(j)); } cmbChangeTuning[i]->nativeWidget()->setCurrentIndex(tmpTuning[i] - 21); } connect(SignalMapper, SIGNAL(mapped(int)), this, SLOT(playString(int))); doLayout(); } void stringtune::fill_cmbInstruments() { cmbInstruments->nativeWidget()->clear(); for (int i = 0; i < instruments.count(); i++) { cmbInstruments->addItem(instruments[i].name); } } ///////////////////////////////////////////// /////////////Actions///////////////////////// void stringtune::editTuning() { if (!edit) { edit = true; playString(LastStringPlayed); tmpTuning = instruments[currentInstrument].strings; btnEditInstrument->setIcon(KIcon("document-save")); btnEditInstrument->setToolTip(i18n("save")); btnAbortEdit->setVisible(true); btnAddString->setVisible(true); btnRemString->setVisible(true); cmbInstruments->nativeWidget()->setEditable(true); } else { edit = false; btnEditInstrument->setIcon(KIcon("document-edit")); btnEditInstrument->setToolTip(i18n("edit instrument")); btnAbortEdit->setVisible(false); btnAddString->setVisible(false); btnRemString->setVisible(false); for (int i = 0; i < tmpTuning.count(); i++) { tmpTuning[i] = cmbChangeTuning[i]->nativeWidget()->currentIndex() + 21; } if (cmbInstruments->nativeWidget()->findText(cmbInstruments->text()) == -1) { instruments.push_back(instrument()); instruments[instruments.count() -1].name = cmbInstruments->text(); instruments[instruments.count() -1].strings = tmpTuning; fill_cmbInstruments(); } else { instruments[cmbInstruments->nativeWidget()->findText(cmbInstruments->text())].strings = tmpTuning; } cmbInstruments->nativeWidget()->setEditable(false); saveInstruments(); } redimControls(); } void stringtune::abortEdit() { edit = false; btnEditInstrument->setIcon(KIcon("document-edit")); btnAbortEdit->setVisible(false); btnAddString->setVisible(false); btnRemString->setVisible(false); cmbInstruments->nativeWidget()->setEditable(false); if (cmbInstruments->nativeWidget()->findText(cmbInstruments->text()) == -1) { currentInstrument = 0; } else { currentInstrument = cmbInstruments->nativeWidget()->findText(cmbInstruments->text()); } redimControls(); } void stringtune::addString() { tmpTuning.push_back(48); redimControls(); } void stringtune::remString() { tmpTuning.pop_back(); redimControls(); } void stringtune::changeInstrument(int instrument) { if (instrument != -1) { playString(LastStringPlayed); currentInstrument = instrument; tmpTuning = instruments[currentInstrument].strings; redimControls(); } } ///////////////////////////////////////////// /////////////MidiStuff/////////////////////// bool stringtune::initMidi() { if (midiOut != 0) { delete midiOut; midiOut = 0; } try { midiOut = new RtMidiOut; } catch (RtError &error) { showMessage(KIcon("dialog-warning"), QString(error.getMessageString()) , Plasma::ButtonOk); return false; } QString portName; midiOutPorts.clear(); for (unsigned int i = 0; i < midiOut->getPortCount(); i++) { try { portName = midiOut->getPortName(i).c_str(); midiOutPorts.append(portName); } catch ( RtError &error) { showMessage(KIcon("dialog-warning"), QString(error.getMessageString()) , Plasma::ButtonOk); return false; } } return true; } void stringtune::playString(int index) { std::vector <unsigned char> message; if (midiWorks) { if (LastStringPlayed != 255) { message.push_back(128); message.push_back(instruments[currentInstrument].strings[LastStringPlayed]); message.push_back(40); midiOut->sendMessage(&message); message.clear(); btnPlayString[LastStringPlayed]->setIcon(KIcon()); btnPlayString[LastStringPlayed]->setText(note_midinumberConversion(instruments[currentInstrument].strings[LastStringPlayed])); } if (index != LastStringPlayed) { message.push_back(144); message.push_back(instruments[currentInstrument].strings[index]); message.push_back(127); midiOut->sendMessage(&message); LastStringPlayed = index; btnPlayString[index]->setText(""); btnPlayString[index]->setIcon(KIcon("media-playback-pause")); } else { LastStringPlayed = 255; } } } int stringtune::note_midinumberConversion(QString noteName) { if (noteName.count() >= 2 && noteName.count() <= 3) { int octav = QString(noteName[noteName.count()-1]).toInt(); int note = -1; noteName.remove(noteName.count()-1,1); for (int i = 0; i <= 11; i++) { if (noteName == notesNames[i]) { note = i; } } if (note == -1) { octav = 0; } return (octav +1) * 12 + note; } else { return 0; } } QString stringtune::note_midinumberConversion(int midiNumber) { QStringList noteName; noteName.push_back(notesNames[midiNumber % 12]); noteName.push_back(QString::number(midiNumber / 12 - 1)); return noteName.join(""); } ///////////////////////////////////////////// /////////////Configuration/////////////////// void stringtune::createConfigurationInterface(KConfigDialog* parent) { QWidget *widget = new QWidget(); KFileDialog *fd = new KFileDialog(KUser().homeDir(), QString("*.txt"), parent); ui.setupUi(widget); parent->addPage(widget, i18n("General")); fd->setMode(KFile::File); connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted())); connect(ui.btnOpenInstFile, SIGNAL(clicked(bool)), fd, SLOT(show())); connect(fd, SIGNAL(fileSelected(QString)), ui.tbxInstFilePath, SLOT(setText(QString))); ui.tbxInstFilePath->setText(instrumentFilePath); ui.btnOpenInstFile->setIcon(KIcon("document-open")); for (int i = 0; i < midiOutPorts.count(); i++) { ui.cmbMidiOut->addItem(midiOutPorts[i]); } ui.cmbMidiOut->setCurrentIndex(currentMidiPort); } void stringtune::configAccepted() { KConfigGroup cg = config(); if (ui.tbxInstFilePath->text() != QString()) { instrumentFilePath = ui.tbxInstFilePath->text(); } if (ui.cmbMidiOut->currentIndex() != -1) { currentMidiPort = ui.cmbMidiOut->currentIndex(); } saveConfig(); emit configNeedsSaving(); DontKnowANameYetForThisOne(); } bool stringtune::loadConfig() { KConfigGroup cg = config(); if (configurationRequired()) { return false; } if (initMidi()) { midiWorks = true; if (cg.readEntry("MidiOutPort").toInt() < midiOutPorts.count()) { currentMidiPort = cg.readEntry("MidiOutPort").toInt(); } else { currentMidiPort = 0; } midiOut->openPort(currentMidiPort); } else { midiWorks = false; } instrumentFilePath = cg.readEntry("InstrumentFilePath"); if (!loadInstruments()) { return false; } currentInstrument = cg.readEntry("CurrentInstrument").toInt(); if (currentInstrument < cmbChangeTuning.count() - 1) { cmbInstruments->nativeWidget()->setCurrentIndex(currentInstrument); } else { currentInstrument = 0; } return true; } void stringtune::saveConfig() { KConfigGroup cg = config(); cg.writeEntry("InstrumentFilePath", instrumentFilePath); cg.writeEntry("MidiOutPort", currentMidiPort); cg.writeEntry("CurrentInstrument", currentInstrument); } void stringtune::saveInstruments() { QString fileName; KTemporaryFile tmpFile; if (KUrl(instrumentFilePath).isLocalFile()) { fileName = KUrl(instrumentFilePath).path(); } else { tmpFile.open(); fileName = tmpFile.fileName(); } if (KIO::NetAccess::upload(fileName, instrumentFilePath, 0)) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { return; } QTextStream out(&file); for (int i = 0; i < instruments.count(); i++) { out << instruments[i].name; for (int j = 0; j < instruments[i].stringCount(); j++) { out << "," << note_midinumberConversion(instruments[i].strings[j]); } out << "\n"; } if (tmpFile.isOpen()) { tmpFile.close(); } } } bool stringtune::loadInstruments() { QStringList tmp; QString tmpFile; int tmpMidiNumber; QVector<instrument> tmpInstruments; if (KIO::NetAccess::download(instrumentFilePath, tmpFile, 0)) { QFile file(tmpFile); if (!file.open(QFile::ReadOnly | QFile::Text)) { showMessage(KIcon("document-edit"),file.errorString(),Plasma::ButtonOk); return false; } QTextStream in(&file); while (!in.atEnd()) { tmp = in.readLine().split(","); if (tmp.count() < 2) { showMessage(KIcon("dialog-warning"), i18n("Instrument File is corrupt!"), Plasma::ButtonOk); return false; } tmpInstruments.push_back(instrument()); tmpInstruments[tmpInstruments.count() -1].name = tmp[0]; for (int i = 1; i < tmp.count(); i++) { tmpMidiNumber = note_midinumberConversion(tmp[i]); if (tmpMidiNumber == 0) { showMessage(KIcon("dialog-warning"), i18n("Instrument File is corrupt!"), Plasma::ButtonOk); return false; } tmpInstruments[tmpInstruments.count() -1].strings.push_back(tmpMidiNumber); } } instruments = tmpInstruments; tmpTuning = instruments[0].strings; fill_cmbInstruments(); return true; } else { return false; } } K_EXPORT_PLASMA_APPLET(stringtune, stringtune) #include "stringtune.moc"
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor