diff --git a/src/app/core.h b/src/app/core.h index 691f0ce..5474f6c 100644 --- a/src/app/core.h +++ b/src/app/core.h @@ -1,58 +1,58 @@ /**************************************************************************** ** ** Copyright (C) 2016 by Sandro S. Andrade ** ** 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) version 3 or any later version ** accepted by the membership of KDE e.V. (or its successor approved ** by the membership of KDE e.V.), which shall act as a proxy ** defined in Section 14 of version 3 of the license. ** ** 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, see . ** ****************************************************************************/ #ifndef MINUET_CORE_H #define MINUET_CORE_H #include namespace Minuet { class Core : public ICore { Q_OBJECT public: virtual ~Core() override; static bool initialize(); virtual IPluginController *pluginController() override; virtual ISoundController *soundController() override; virtual IExerciseController *exerciseController() override; virtual IUiController *uiController() override; void setSoundController(ISoundController *soundController); private: - Core(QObject *parent = 0); + explicit Core(QObject *parent = 0); IPluginController *m_pluginController; ISoundController *m_soundController; IExerciseController *m_exerciseController; IUiController *m_uiController; }; } #endif diff --git a/src/app/exercisecontroller.cpp b/src/app/exercisecontroller.cpp index 14e5e15..5c3d063 100644 --- a/src/app/exercisecontroller.cpp +++ b/src/app/exercisecontroller.cpp @@ -1,253 +1,253 @@ /**************************************************************************** ** ** Copyright (C) 2016 by Sandro S. Andrade ** ** 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) version 3 or any later version ** accepted by the membership of KDE e.V. (or its successor approved ** by the membership of KDE e.V.), which shall act as a proxy ** defined in Section 14 of version 3 of the license. ** ** 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, see . ** ****************************************************************************/ #include "exercisecontroller.h" #if !defined(Q_OS_ANDROID) #include #endif #include #include #include #include #include namespace Minuet { ExerciseController::ExerciseController(QObject *parent) : IExerciseController(parent), m_chosenRootNote(0) { m_exercises["exercises"] = QJsonArray(); m_definitions["definitions"] = QJsonArray(); } ExerciseController::~ExerciseController() { } bool ExerciseController::initialize(Core *core) { Q_UNUSED(core) m_errorString.clear(); bool definitionsMerge = mergeJsonFiles("definitions", m_definitions); bool exercisesMerge = mergeJsonFiles("exercises", m_exercises, true, "name", "children"); // QFile file("merged-exercises.json"); // file.open(QIODevice::WriteOnly); // file.write(QJsonDocument(m_exercises).toJson()); // file.close(); return definitionsMerge & exercisesMerge; } QString ExerciseController::errorString() const { return m_errorString; } void ExerciseController::randomlySelectExerciseOptions() { while (!m_selectedExerciseOptions.isEmpty()) m_selectedExerciseOptions.removeFirst(); qsrand(QDateTime::currentDateTimeUtc().toTime_t()); int minNote = INT_MAX; int maxNote = INT_MIN; quint8 numberOfSelectedOptions = m_currentExercise[QStringLiteral("numberOfSelectedOptions")].toInt(); for (quint8 i = 0; i < numberOfSelectedOptions; ++i) { QJsonArray exerciseOptions = QJsonObject::fromVariantMap(m_currentExercise)[QStringLiteral("options")].toArray(); quint8 chosenExerciseOption = qrand() % exerciseOptions.size(); QString sequence = exerciseOptions[chosenExerciseOption].toObject()[QStringLiteral("sequence")].toString(); foreach(const QString &additionalNote, sequence.split(' ')) { int note = additionalNote.toInt(); if (note > maxNote) maxNote = note; if (note < minNote) minNote = note; } if (m_currentExercise["playMode"].toString() != "rhythm") { QStringList exerciseRoots = m_currentExercise["root"].toString().split('.'); quint8 exerciseMinRoot = exerciseRoots.first().toInt(); quint8 exerciseMaxRoot = exerciseRoots.last().toInt(); do m_chosenRootNote = exerciseMinRoot + qrand() % (exerciseMaxRoot - exerciseMinRoot); while (m_chosenRootNote + maxNote > 108 || m_chosenRootNote + minNote < 21); } QJsonObject jsonObject = exerciseOptions[chosenExerciseOption].toObject(); jsonObject["rootNote"] = QString::number(m_chosenRootNote); exerciseOptions[chosenExerciseOption] = jsonObject; m_selectedExerciseOptions.append(exerciseOptions[chosenExerciseOption]); } emit selectedExerciseOptionsChanged(m_selectedExerciseOptions); } unsigned int ExerciseController::chosenRootNote() { return m_chosenRootNote; } QJsonArray ExerciseController::exercises() const { return m_exercises[QStringLiteral("exercises")].toArray(); } bool ExerciseController::mergeJsonFiles(const QString directoryName, QJsonObject &targetObject, bool applyDefinitionsFlag, QString commonKey, QString mergeKey) { QStringList jsonDirs; #if defined(Q_OS_ANDROID) jsonDirs << "assets:/data/" + directoryName; #elif defined(Q_OS_WIN) jsonDirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("minuet/") + directoryName, QStandardPaths::LocateDirectory); #else jsonDirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, directoryName, QStandardPaths::LocateDirectory); #endif foreach (const QString &jsonDirString, jsonDirs) { QDir jsonDir(jsonDirString); foreach (const QString &json, jsonDir.entryList(QDir::Files)) { - if (!json.endsWith(".json")) break; + if (!json.endsWith(QLatin1String(".json"))) break; QFile jsonFile(jsonDir.absoluteFilePath(json)); if (!jsonFile.open(QIODevice::ReadOnly)) { #if !defined(Q_OS_ANDROID) m_errorString = i18n("Could not open JSON file \"%1\".", jsonDir.absoluteFilePath(json)); #else m_errorString = QStringLiteral("Couldn't open json file \"%1\".").arg(jsonDir.absoluteFilePath(json)); #endif return false; } QJsonParseError error; QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonFile.readAll(), &error); if (error.error != QJsonParseError::NoError) { m_errorString += QStringLiteral("Error when parsing JSON file '%1'. ").arg(jsonDir.absoluteFilePath(json)); jsonFile.close(); return false; } else { QJsonObject jsonObject = jsonDocument.object(); if (applyDefinitionsFlag) jsonObject[directoryName] = applyDefinitions(jsonObject[directoryName].toArray(), m_definitions[QStringLiteral("definitions")].toArray()); targetObject[directoryName] = mergeJsonArrays(targetObject[directoryName].toArray(), jsonObject[directoryName].toArray(), commonKey, mergeKey); } jsonFile.close(); } } return true; } QJsonArray ExerciseController::applyDefinitions(QJsonArray exercises, QJsonArray definitions, QJsonObject collectedProperties) { QJsonArray::const_iterator exercisesBegin = exercises.constBegin(); QJsonArray::const_iterator exercisesEnd = exercises.constEnd(); for (QJsonArray::ConstIterator i1 = exercisesBegin; i1 < exercisesEnd; ++i1) { if (i1->isObject()) { QJsonObject exerciseObject = i1->toObject(); QJsonArray filteredDefinitions = definitions; QStringList exerciseObjectKeys = exerciseObject.keys(); if (exerciseObjectKeys.contains(QStringLiteral("and-tags")) && exerciseObject[QStringLiteral("and-tags")].isArray()) filterDefinitions(filteredDefinitions, exerciseObject, "and-tags", AndFiltering); if (exerciseObjectKeys.contains(QStringLiteral("or-tags")) && exerciseObject[QStringLiteral("or-tags")].isArray()) filterDefinitions(filteredDefinitions, exerciseObject, "or-tags", OrFiltering); if (exerciseObjectKeys.contains(QStringLiteral("children"))) { foreach(const QString &key, exerciseObjectKeys) if (key != "name" && key != "children" && key != "and-tags" && key != "or-tags" && !key.startsWith('_')) { collectedProperties.insert(key, exerciseObject[key]); exerciseObject.remove(key); } exerciseObject[QStringLiteral("children")] = applyDefinitions(exerciseObject[QStringLiteral("children")].toArray(), filteredDefinitions, collectedProperties); } else { foreach(const QString &key, collectedProperties.keys()) if (!exerciseObject.contains(key)) exerciseObject.insert(key, collectedProperties[key]); exerciseObject.insert("options", filteredDefinitions); } exercises[i1-exercisesBegin] = exerciseObject; } } return exercises; } void ExerciseController::filterDefinitions(QJsonArray &definitions, QJsonObject &exerciseObject, const QString &filterTagsKey, DefinitionFilteringMode definitionFilteringMode) { QJsonArray filterTags = exerciseObject[filterTagsKey].toArray(); exerciseObject.remove(filterTagsKey); for (QJsonArray::Iterator i2 = definitions.begin(); i2 < definitions.end(); ++i2) { bool remove = (definitionFilteringMode == AndFiltering) ? false:true; QJsonArray::const_iterator filterTagsEnd = filterTags.constEnd(); for (QJsonArray::ConstIterator i3 = filterTags.constBegin(); i3 < filterTagsEnd; ++i3) { QJsonArray tagArray = i2->toObject()["tags"].toArray(); if (definitionFilteringMode == AndFiltering && !tagArray.contains(*i3)) { remove = true; break; } if (definitionFilteringMode == OrFiltering && tagArray.contains(*i3)) remove = false; } if (remove) { i2 = definitions.erase(i2); i2--; } } } QJsonArray ExerciseController::mergeJsonArrays(QJsonArray oldFile, QJsonArray newFile, QString commonKey, QString mergeKey) { QJsonArray::const_iterator newFileEnd = newFile.constEnd();; for (QJsonArray::ConstIterator i1 = newFile.constBegin(); i1 < newFileEnd; ++i1) { if (i1->isObject()) { QJsonArray::ConstIterator i2; QJsonArray::const_iterator oldFileEnd = oldFile.constEnd(); for (i2 = oldFile.constBegin(); i2 < oldFileEnd; ++i2) { QJsonObject newFileObject = i1->toObject(); QJsonObject oldFileObject = i2->toObject(); if (i2->isObject() && i1->isObject() && !commonKey.isEmpty() && oldFileObject[commonKey] == newFileObject[commonKey]) { QJsonObject jsonObject = oldFile[i2-oldFile.constBegin()].toObject(); jsonObject[mergeKey] = mergeJsonArrays(oldFileObject[mergeKey].toArray(), newFileObject[mergeKey].toArray(), commonKey, mergeKey); oldFile[i2-oldFile.constBegin()] = jsonObject; break; } } if (i2 == oldFile.constEnd()) oldFile.append(*i1); } } return oldFile; } } diff --git a/src/app/plugincontroller.h b/src/app/plugincontroller.h index 3acd1d4..838439b 100644 --- a/src/app/plugincontroller.h +++ b/src/app/plugincontroller.h @@ -1,62 +1,62 @@ /**************************************************************************** ** ** Copyright (C) 2016 by Sandro S. Andrade ** ** 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) version 3 or any later version ** accepted by the membership of KDE e.V. (or its successor approved ** by the membership of KDE e.V.), which shall act as a proxy ** defined in Section 14 of version 3 of the license. ** ** 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, see . ** ****************************************************************************/ #ifndef MINUET_PLUGINCONTROLLER_H #define MINUET_PLUGINCONTROLLER_H #include #ifndef Q_OS_ANDROID #include #include #endif namespace Minuet { class Core; class IPlugin; class PluginController : public IPluginController { Q_OBJECT public: - PluginController(QObject *parent = 0); + explicit PluginController(QObject *parent = 0); ~PluginController() override; bool initialize(Core *core); virtual QString errorString() const; private: #ifndef Q_OS_ANDROID QVector m_plugins; typedef QHash InfoToPluginMap; InfoToPluginMap m_loadedPlugins; #endif QString m_errorString; }; } #endif diff --git a/src/app/uicontroller.h b/src/app/uicontroller.h index a6149c3..145d014 100644 --- a/src/app/uicontroller.h +++ b/src/app/uicontroller.h @@ -1,72 +1,72 @@ /**************************************************************************** ** ** Copyright (C) 2016 by Sandro S. Andrade ** ** 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) version 3 or any later version ** accepted by the membership of KDE e.V. (or its successor approved ** by the membership of KDE e.V.), which shall act as a proxy ** defined in Section 14 of version 3 of the license. ** ** 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, see . ** ****************************************************************************/ #ifndef MINUET_UICONTROLLER_H #define MINUET_UICONTROLLER_H #include #ifdef Q_OS_ANDROID #include class DummyAndroidLocalizer : public QObject { Q_OBJECT public: explicit DummyAndroidLocalizer(QObject *parent = 0) : QObject(parent) { } Q_INVOKABLE QString i18n (const QString &message, const QVariant &p1=QVariant(), const QVariant &p2=QVariant(), const QVariant &p3=QVariant(), const QVariant &p4=QVariant(), const QVariant &p5=QVariant(), const QVariant &p6=QVariant(), const QVariant &p7=QVariant(), const QVariant &p8=QVariant(), const QVariant &p9=QVariant(), const QVariant &p10=QVariant()) const { return message; } Q_INVOKABLE QString i18nc (const QString &context, const QString &message, const QVariant &p1=QVariant(), const QVariant &p2=QVariant(), const QVariant &p3=QVariant(), const QVariant &p4=QVariant(), const QVariant &p5=QVariant(), const QVariant &p6=QVariant(), const QVariant &p7=QVariant(), const QVariant &p8=QVariant(), const QVariant &p9=QVariant(), const QVariant &p10=QVariant()) const { return message; } }; #endif namespace Minuet { class Core; class UiController : public IUiController { Q_OBJECT public: - UiController(QObject *parent = 0); + explicit UiController(QObject *parent = 0); ~UiController() override; bool initialize(Core *core); virtual QString errorString() const; private: QString m_errorString; }; } #endif diff --git a/src/plugins/csoundsoundcontroller/csoundsoundcontroller.cpp b/src/plugins/csoundsoundcontroller/csoundsoundcontroller.cpp index bdd8773..9edcd6d 100644 --- a/src/plugins/csoundsoundcontroller/csoundsoundcontroller.cpp +++ b/src/plugins/csoundsoundcontroller/csoundsoundcontroller.cpp @@ -1,234 +1,234 @@ /**************************************************************************** ** ** Copyright (C) 2016 by Sandro S. Andrade ** ** 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) version 3 or any later version ** accepted by the membership of KDE e.V. (or its successor approved ** by the membership of KDE e.V.), which shall act as a proxy ** defined in Section 14 of version 3 of the license. ** ** 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, see . ** ****************************************************************************/ #include "csoundsoundcontroller.h" #include "csengine.h" #include #include #include Q_DECLARE_LOGGING_CATEGORY(MINUETANDROID) CsoundSoundController::CsoundSoundController(QObject *parent): Minuet::ISoundController(parent), m_csoundEngine(new CsEngine) { qmlRegisterType("org.kde.minuet", 1, 0, "CsoundSoundController"); openExerciseFile(); // setQuestionLabel("new question"); } void CsoundSoundController::openExerciseFile() { QStringList templateList; templateList.append(QStringLiteral("assets:/share/template.csd")); // templateList.append(QStringLiteral("assets:/share/template_rhythm.csd")); qDebug() << "DIRPATH: " << QCoreApplication::applicationDirPath(); qDebug() << "ASSETSPATH: " << QDir("assets:/").canonicalPath(); qDebug() << "QStandardPaths::ApplicationsLocation: " << QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation); qDebug() << "QStandardPaths::GenericDataLocation: " << QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); qDebug() << "QStandardPaths::AppDataLocation: " << QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); qDebug() << "QStandardPaths::AppLocalDataLocation: " << QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation); qDebug() << "QStandardPaths::AppConfigLocation: " << QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation); QDir appDir(QCoreApplication::applicationDirPath()); qDebug() << "Contains libfluidOpcodes.so? " << appDir.entryList(QDir::Files).contains("libfluidOpcodes.so"); qDebug() << "DIRPATH: " << appDir << " Contents: " << appDir.entryList(QDir::AllEntries); appDir.cdUp(); qDebug() << "DIRPATH: " << appDir << " Contents: " << appDir.entryList(QDir::AllEntries); appDir.cdUp(); qDebug() << "DIRPATH: " << appDir << " Contents: " << appDir.entryList(QDir::AllEntries); QDir reserved("/data/data/org.kde.minuet/qt-reserved-files/"); qDebug() << "RESERVED: " << reserved << " Contents: " << reserved.entryList(QDir::AllEntries); QDirIterator it("/", QDirIterator::Subdirectories); while (it.hasNext()) qDebug() << "FILE: " << it.next(); foreach (const QString &templateString, templateList) { QFile sfile(templateString); if (!sfile.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&sfile); QString lineData; QString tempBeginLine; QString tempEndLine; while (!in.atEnd()) { lineData = in.readLine(); lineData.replace("APPDIRPATH", QCoreApplication::applicationDirPath()); - tempBeginLine = tempBeginLine + lineData + "\n"; + tempBeginLine = tempBeginLine + lineData + '\n'; if (lineData.contains("")) { m_begLine.append(tempBeginLine); break; } } while (!in.atEnd()) { lineData = in.readLine(); - tempEndLine += lineData + "\n"; + tempEndLine += lineData + '\n'; } m_endLine.append(tempEndLine); } qDebug() << "m_begLine: " << m_begLine; qDebug() << "m_endLine: " << m_endLine; } void CsoundSoundController::appendEvent(QList midiNotes, QList barStartInfo, QString playMode) { //TODO : use grantlee processing or any other text template library int templateNumber = playMode == "rhythm" ? 1:0; QString content; QString fifthParam = QStringLiteral("100"); QFile m_csdFileOpen(QStringLiteral("./template.csd")); qDebug() << "CREATING " << QDir::currentPath() + "/template.csd"; if(!m_csdFileOpen.isOpen()) { m_csdFileOpen.open(QIODevice::ReadWrite | QIODevice::Text); } m_csdFileOpen.resize(0); if (playMode == "rhythm") { QString wave = QStringLiteral("f 1 0 16384 10 1\n\n"); content += wave; fifthParam = QStringLiteral(""); } for(int i=0; i midiNotes; QList barStartInfo; if (m_playMode == "rhythm") { for(int k = 0; k < 4; ++k) { midiNotes.append(80); barStartInfo.append(barStart++); } } int exerciseOptionsSize = selectedExerciseOptions.size(); for (int i = 0; i < exerciseOptionsSize; ++i) { QString sequence = selectedExerciseOptions[i].toObject()[QStringLiteral("sequence")].toString(); unsigned int chosenRootNote = selectedExerciseOptions[i].toObject()[QStringLiteral("rootNote")].toString().toInt(); if (m_playMode != "rhythm") { midiNotes.append(chosenRootNote); barStartInfo.append(barStart); unsigned int j = 1; foreach(const QString &additionalNote, sequence.split(' ')) { midiNotes.append(chosenRootNote+additionalNote.toInt()); barStartInfo.append((m_playMode == "scale") ? barStart+j:barStart); ++j; } barStart++; } else { midiNotes.append(80); barStartInfo.append(barStart); foreach(QString additionalNote, sequence.split(' ')) { // krazy:exclude=foreach midiNotes.append(37); barStartInfo.append(barStart); float dotted = 1; if (additionalNote.endsWith('.')) { dotted = 1.5; additionalNote.chop(1); } barStart += dotted*1*(4.0/additionalNote.toInt()); } } } if (m_playMode == "rhythm") { midiNotes.append(80); barStartInfo.append(barStart); } appendEvent(midiNotes, barStartInfo, m_playMode); } void CsoundSoundController::prepareFromMidiFile(const QString &fileName) { Q_UNUSED(fileName) } void CsoundSoundController::play() { m_csoundEngine->start(); setState(PlayingState); } void CsoundSoundController::pause() { } void CsoundSoundController::stop() { m_csoundEngine->stop(); setState(StoppedState); } void CsoundSoundController::reset() { } void CsoundSoundController::setPitch (qint8 pitch) { Q_UNUSED(pitch) } void CsoundSoundController::setVolume (quint8 volume) { Q_UNUSED(volume) } void CsoundSoundController::setTempo (quint8 tempo) { Q_UNUSED(tempo) } //#include "moc_csoundsoundcontroller.cpp"