Commit 4e332b82 authored by Sandro Andrade's avatar Sandro Andrade

Add UiController and refactor main.cpp

parent 11ba8dcf
kde_enable_exceptions()
set(minuet_SRCS
main.cpp
song.cpp
wizard.cpp
minuetmainwindow.cpp
midisequencer.cpp
midisequenceroutputthread.cpp
exercisecontroller.cpp
)
kconfig_add_kcfg_files(minuet_SRCS minuetsettings.kcfgc)
ki18n_wrap_ui(minuet_SRCS
settingsmidi.ui
wizardsystemcheck.ui
)
add_executable(minuet ${minuet_SRCS})
......@@ -22,18 +8,13 @@ target_link_libraries(minuet
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Quick
KF5::I18n
KF5::XmlGui
KF5::KIOWidgets
KF5::Crash
KF5::I18n
Minuet::Shell
asound
drumstick-alsa
drumstick-file
)
install(TARGETS minuet ${INSTALL_TARGETS_DEFAULT_ARGS})
install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/minuet)
install(PROGRAMS org.kde.minuet.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
install(FILES minuetui.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/minuet)
/****************************************************************************
**
** Copyright (C) 2016 by Sandro S. Andrade <sandroandrade@kde.org>
**
** 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 <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "exercisecontroller.h"
#include "midisequencer.h"
#include <KLocalizedString>
#include <QDir>
#include <QDateTime>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QtQml> // krazy:exclude=includes
#include <drumstick/alsaevent.h>
ExerciseController::ExerciseController(MidiSequencer *midiSequencer) :
m_midiSequencer(midiSequencer),
m_minRootNote(0),
m_maxRootNote(0),
m_playMode(ScalePlayMode),
m_answerLength(1),
m_chosenRootNote(0),
m_chosenExercise(0)
{
qmlRegisterType<ExerciseController>("org.kde.minuet", 1, 0, "ExerciseController");
}
ExerciseController::~ExerciseController()
{
}
void ExerciseController::setExerciseOptions(QJsonArray exerciseOptions)
{
m_exerciseOptions = exerciseOptions;
}
void ExerciseController::setMinRootNote(unsigned int minRootNote)
{
m_minRootNote = minRootNote;
}
void ExerciseController::setMaxRootNote(unsigned int maxRootNote)
{
m_maxRootNote = maxRootNote;
}
void ExerciseController::setPlayMode(PlayMode playMode)
{
m_playMode = playMode;
}
void ExerciseController::setAnswerLength(unsigned int answerLength)
{
m_answerLength = answerLength;
}
QStringList ExerciseController::randomlyChooseExercises()
{
qsrand(QDateTime::currentDateTimeUtc().toTime_t());
QStringList chosenExercises;
Song *song = new Song;
song->setHeader(0, 1, 60);
song->setInitialTempo(600000);
m_midiSequencer->setSong(song);
m_midiSequencer->appendEvent(m_midiSequencer->SMFTempo(600000), 0);
unsigned int barStart = 0;
if (m_playMode == RhythmPlayMode) {
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 0);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 60);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 120);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 180);
barStart = 240;
}
for (unsigned int i = 0; i < m_answerLength; ++i) {
m_chosenExercise = qrand() % m_exerciseOptions.size();
QString sequence = m_exerciseOptions[m_chosenExercise].toObject()[QStringLiteral("sequence")].toString();
if (m_playMode != RhythmPlayMode) {
int minNote = INT_MAX;
int maxNote = INT_MIN;
foreach(const QString &additionalNote, sequence.split(' ')) {
int note = additionalNote.toInt();
if (note > maxNote) maxNote = note;
if (note < minNote) minNote = note;
}
do
m_chosenRootNote = m_minRootNote + qrand() % (m_maxRootNote - m_minRootNote);
while (m_chosenRootNote + maxNote > 108 || m_chosenRootNote + minNote < 21);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(1, m_chosenRootNote, 120), barStart);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOff(1, m_chosenRootNote, 120), barStart + 60);
unsigned int j = 1;
drumstick::SequencerEvent *ev;
foreach(const QString &additionalNote, sequence.split(' ')) {
m_midiSequencer->appendEvent(ev = m_midiSequencer->SMFNoteOn(1,
m_chosenRootNote + additionalNote.toInt(),
120),
(m_playMode == ScalePlayMode) ? barStart+60*j:barStart);
ev->setTag(0);
m_midiSequencer->appendEvent(ev = m_midiSequencer->SMFNoteOff(1,
m_chosenRootNote + additionalNote.toInt(),
120),
(m_playMode == ScalePlayMode) ? barStart+60*(j+1):barStart+60);
ev->setTag(0);
++j;
}
barStart += 60;
}
else {
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), barStart);
foreach(QString additionalNote, sequence.split(' ')) { // krazy:exclude=foreach
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 37, 120), barStart);
float dotted = 1;
if (additionalNote.endsWith('.')) {
dotted = 1.5;
additionalNote.chop(1);
}
barStart += dotted*60*(4.0/additionalNote.toInt());
}
}
chosenExercises << m_exerciseOptions[m_chosenExercise].toObject()[QStringLiteral("name")].toString();
}
if (m_playMode == RhythmPlayMode) {
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), barStart);
}
return chosenExercises;
}
unsigned int ExerciseController::chosenRootNote()
{
return m_chosenRootNote;
}
void ExerciseController::playChoosenExercise()
{
m_midiSequencer->play();
}
bool ExerciseController::configureExercises()
{
m_errorString.clear();
QStringList exercisesDirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("exercises"), QStandardPaths::LocateDirectory);
foreach (const QString &exercisesDirString, exercisesDirs) {
QDir exercisesDir(exercisesDirString);
foreach (const QString &exercise, exercisesDir.entryList(QDir::Files)) {
QFile exerciseFile(exercisesDir.absoluteFilePath(exercise));
if (!exerciseFile.open(QIODevice::ReadOnly)) {
m_errorString = i18n("Couldn't open exercise file \"%1\".", exercisesDir.absoluteFilePath(exercise));
return false;
}
QJsonParseError error;
QJsonDocument jsonDocument = QJsonDocument::fromJson(exerciseFile.readAll(), &error);
if (error.error != QJsonParseError::NoError) {
m_errorString = error.errorString();
exerciseFile.close();
return false;
}
else {
if (m_exercises.length() == 0)
m_exercises = jsonDocument.object();
else
m_exercises[QStringLiteral("exercises")] = mergeExercises(m_exercises[QStringLiteral("exercises")].toArray(),
jsonDocument.object()[QStringLiteral("exercises")].toArray());
}
exerciseFile.close();
}
}
return true;
}
QString ExerciseController::errorString() const
{
return m_errorString;
}
QJsonObject ExerciseController::exercises() const
{
return m_exercises;
}
QJsonArray ExerciseController::mergeExercises(QJsonArray exercises, QJsonArray newExercises)
{
for (QJsonArray::ConstIterator i1 = newExercises.constBegin(); i1 < newExercises.constEnd(); ++i1) {
if (i1->isObject()) {
QJsonArray::ConstIterator i2;
for (i2 = exercises.constBegin(); i2 < exercises.constEnd(); ++i2) {
if (i2->isObject() && i1->isObject() && i2->toObject()[QStringLiteral("name")] == i1->toObject()[QStringLiteral("name")]) {
QJsonObject jsonObject = exercises[i2-exercises.constBegin()].toObject();
jsonObject[QStringLiteral("children")] = mergeExercises(i2->toObject()[QStringLiteral("children")].toArray(), i1->toObject()[QStringLiteral("children")].toArray());
exercises[i2-exercises.constBegin()] = jsonObject;
break;
}
}
if (i2 == exercises.constEnd())
exercises.append(*i1);
}
}
return exercises;
}
/****************************************************************************
**
** Copyright (C) 2016 by Sandro S. Andrade <sandroandrade@kde.org>
**
** 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 <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#ifndef EXERCISECONTROLLER_H
#define EXERCISECONTROLLER_H
#include <QObject>
#include <QJsonArray>
#include <QJsonObject>
#include <QStringList>
class MidiSequencer;
class ExerciseController : public QObject
{
Q_OBJECT
Q_ENUMS(PlayMode)
public:
explicit ExerciseController(MidiSequencer *midiSequencer = 0);
virtual ~ExerciseController();
enum PlayMode {
ScalePlayMode = 0,
ChordPlayMode,
RhythmPlayMode
};
Q_INVOKABLE void setExerciseOptions(QJsonArray exerciseOptions);
Q_INVOKABLE void setMinRootNote(unsigned int minRootNote);
Q_INVOKABLE void setMaxRootNote(unsigned int maxRootNote);
Q_INVOKABLE void setPlayMode(PlayMode playMode);
Q_INVOKABLE void setAnswerLength(unsigned int answerLength);
Q_INVOKABLE QStringList randomlyChooseExercises();
Q_INVOKABLE unsigned int chosenRootNote();
Q_INVOKABLE void playChoosenExercise();
bool configureExercises();
QString errorString() const;
QJsonObject exercises() const;
private:
QJsonArray mergeExercises(QJsonArray exercises, QJsonArray newExercises);
private:
MidiSequencer *m_midiSequencer;
QJsonObject m_exercises;
QJsonArray m_exerciseOptions;
unsigned int m_minRootNote;
unsigned int m_maxRootNote;
PlayMode m_playMode;
unsigned int m_answerLength;
unsigned int m_chosenRootNote;
unsigned int m_chosenExercise;
QString m_errorString;
};
#endif // EXERCISECONTROLLER_H
......@@ -20,17 +20,15 @@
**
****************************************************************************/
#include "minuetmainwindow.h"
#include "minuet_version.h"
#include <KCrash>
#include <KAboutData>
#include <KLocalizedString>
#include <QCommandLineParser>
Q_DECLARE_LOGGING_CATEGORY(MINUET)
Q_LOGGING_CATEGORY(MINUET, "minuet")
#include <QApplication>
#include <QIcon>
//#include <QQmlDebuggingEnabler>
//QQmlDebuggingEnabler enabler;
......@@ -64,7 +62,5 @@ int main(int argc, char **argv)
Minuet::Core::initialize();
MinuetMainWindow *appwindow = new MinuetMainWindow;
appwindow->show();
return application.exec();
}
......@@ -2,6 +2,7 @@ set(minuetinterfaces_LIB_SRCS
icore.cpp
iplugin.cpp
iplugincontroller.cpp
iuicontroller.cpp
isoundbackend.cpp
iexercisecontroller.cpp
)
......@@ -30,6 +31,7 @@ install(FILES
icore.h
iplugin.h
iplugincontroller.h
iuicontroller.h
isoundbackend.h
iexercisecontroller.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/minuet/interfaces
......
......@@ -33,6 +33,7 @@ namespace Minuet
class IPluginController;
class ISoundBackend;
class IExerciseController;
class IUiController;
class MINUETINTERFACES_EXPORT ICore : public QObject
{
......@@ -46,6 +47,7 @@ public:
virtual Minuet::IPluginController *pluginController() = 0;
virtual Minuet::ISoundBackend *soundBackend() = 0;
virtual Minuet::IExerciseController *exerciseController() = 0;
virtual Minuet::IUiController *uiController() = 0;
protected:
ICore(QObject *parent = 0);
......
/****************************************************************************
**
** Copyright (C) 2016 by Sandro S. Andrade <sandroandrade@kde.org>
**
** 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 <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "iuicontroller.h"
namespace Minuet
{
IUiController::IUiController(QObject *parent)
: QObject(parent)
{
}
IUiController::~IUiController()
{
}
}
/****************************************************************************
**
** Copyright (C) 2016 by Sandro S. Andrade <sandroandrade@kde.org>
**
** 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 <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#ifndef MINUET_IUICONTROLLER_H
#define MINUET_IUICONTROLLER_H
#include <QtCore/QObject>
#include "minuetinterfacesexport.h"
namespace Minuet
{
class MINUETINTERFACES_EXPORT IUiController : public QObject
{
Q_OBJECT
public:
explicit IUiController(QObject *parent = 0);
~IUiController() override;
};
}
#endif
kde_enable_exceptions()
set(minuetshell_LIB_SRCS
core.cpp
plugincontroller.cpp
uicontroller.cpp
exercisecontroller.cpp
minuetmainwindow.cpp
wizard.cpp
midisequencer.cpp
song.cpp
midisequenceroutputthread.cpp
)
ki18n_wrap_ui(minuetshell_LIB_SRCS
settingsmidi.ui
wizardsystemcheck.ui
)
kconfig_add_kcfg_files(minuetshell_LIB_SRCS minuetsettings.kcfgc)
add_library(minuetshell ${minuetshell_LIB_SRCS})
add_library(Minuet::Shell ALIAS minuetshell)
generate_export_header(minuetshell EXPORT_FILE_NAME minuetshellexport.h)
target_link_libraries(minuetshell
Minuet::Interfaces
Qt5::Core
Qt5::Gui
Qt5::Quick
Qt5::Widgets
KF5::CoreAddons
KF5::WidgetsAddons
KF5::KIOWidgets
KF5::Completion
KF5::XmlGui
KF5::I18n
asound
drumstick-alsa
drumstick-file
Minuet::Interfaces
)
install(TARGETS
......@@ -28,7 +55,14 @@ install(FILES
install(FILES
core.h
plugincontroller.h
uicontroller.h
exercisecontroller.h
minuetmainwindow.h
wizard.h
midisequencer.h
song.h
midisequenceroutputthread.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/minuet/shell
COMPONENT Devel
)
install(FILES minuetui.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/minuet)
......@@ -24,6 +24,7 @@
#include "plugincontroller.h"
#include "exercisecontroller.h"
#include "uicontroller.h"
namespace Minuet
{
......@@ -57,13 +58,20 @@ IExerciseController *Core::exerciseController()
return m_exerciseController.data();
}
IUiController *Core::uiController()
{
return m_uiController.data();
}
Core::Core(QObject *parent)
: ICore(parent),
m_pluginController(new PluginController),
m_exerciseController(new ExerciseController)
m_exerciseController(new ExerciseController),
m_uiController(new UiController)
{
((PluginController *)m_pluginController.data())->initialize();
((UiController *)m_uiController.data())->initialize();
}
}
......
......@@ -42,12 +42,14 @@ public:
virtual IPluginController *pluginController() override;
virtual ISoundBackend *soundBackend() override;
virtual IExerciseController *exerciseController() override;
virtual IUiController *uiController() override;
private:
Core(QObject *parent = 0);
QScopedPointer<IPluginController> m_pluginController;
QScopedPointer<IExerciseController> m_exerciseController;
QScopedPointer<IUiController> m_uiController;
};
}
......
......@@ -22,17 +22,212 @@
#include "exercisecontroller.h"
#include "midisequencer.h"
#include <KLocalizedString>
#include <QDir>
#include <QDateTime>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QtQml> // krazy:exclude=includes
#include <drumstick/alsaevent.h>
namespace Minuet
{
ExerciseController::ExerciseController(QObject *parent)
: IExerciseController(parent)
ExerciseController::ExerciseController(MidiSequencer *midiSequencer) :
m_midiSequencer(midiSequencer),
m_minRootNote(0),
m_maxRootNote(0),
m_playMode(ScalePlayMode),
m_answerLength(1),
m_chosenRootNote(0),
m_chosenExercise(0)
{
qmlRegisterType<ExerciseController>("org.kde.minuet", 1, 0, "ExerciseController");
}
ExerciseController::~ExerciseController()
{
}
void ExerciseController::setExerciseOptions(QJsonArray exerciseOptions)
{
m_exerciseOptions = exerciseOptions;