Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step Recording feature #4544

Merged
merged 11 commits into from
Feb 9, 2019
Merged
Binary file added data/themes/classic/record_step_off.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/themes/classic/record_step_on.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/themes/default/record_step_off.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/themes/default/record_step_on.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion include/Editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ protected slots:
virtual void play() {}
virtual void record() {}
virtual void recordAccompany() {}
virtual void toggleStepRecording() {}
virtual void stop() {}

private slots:
Expand All @@ -64,7 +65,7 @@ private slots:
///
/// \param record If set true, the editor's toolbar will contain record
/// buttons in addition to the play and stop buttons.
Editor(bool record = false);
Editor(bool record = false, bool record_step = false);
virtual ~Editor();


Expand All @@ -73,6 +74,7 @@ private slots:
QAction* m_playAction;
QAction* m_recordAction;
QAction* m_recordAccompanyAction;
QAction* m_toggleStepRecordingAction;
QAction* m_stopAction;
};

Expand Down
19 changes: 18 additions & 1 deletion include/PianoRoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include "lmms_basics.h"
#include "Song.h"
#include "ToolTip.h"
#include "StepRecorder.h"
#include "StepRecorderWidget.h"

class QPainter;
class QPixmap;
Expand Down Expand Up @@ -103,6 +105,11 @@ class PianoRoll : public QWidget
return m_recording;
}

inline bool isStepRecording() const
{
return m_stepRecorder.isRecording();
}

const Pattern* currentPattern() const
{
return m_pattern;
Expand Down Expand Up @@ -188,6 +195,7 @@ protected slots:
void play();
void record();
void recordAccompany();
bool toggleStepRecording();
void stop();

void startRecordNote( const Note & n );
Expand All @@ -205,9 +213,11 @@ protected slots:

void updatePosition(const MidiTime & t );
void updatePositionAccompany(const MidiTime & t );
void updatePositionStepRecording(const MidiTime & t );

void zoomingChanged();
void quantizeChanged();
void noteLengthChanged();
void quantizeNotes();

void updateSemiToneMarkerMenu();
Expand Down Expand Up @@ -398,6 +408,9 @@ protected slots:

friend class PianoRollWindow;

StepRecorderWidget m_stepRecorderWidget;
StepRecorder m_stepRecorder;

// qproperty fields
QColor m_barLineColor;
QColor m_beatLineColor;
Expand Down Expand Up @@ -442,6 +455,7 @@ class PianoRollWindow : public Editor, SerializingObject
void stop();
void record();
void recordAccompany();
void toggleStepRecording();
void stopRecording();

bool isRecording() const;
Expand All @@ -466,11 +480,14 @@ class PianoRollWindow : public Editor, SerializingObject


private slots:
void patternRenamed();
void updateAfterPatternChange();
void ghostPatternSet( bool state );

private:
void patternRenamed();
void focusInEvent(QFocusEvent * event);
void stopStepRecording();
void updateStepRecordingIcon();

PianoRoll* m_editor;

Expand Down
143 changes: 143 additions & 0 deletions include/StepRecorder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* This file is part of LMMS - https://lmms.io
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#ifndef STEP_RECORDER_H
#define STEP_RECORDER_H

#include <QTime>
#include <QTimer>
#include <QObject>
#include <QKeyEvent>

#include "Note.h"
#include "lmms_basics.h"
#include "Pattern.h"

class PianoRoll;
class StepRecorderWidget;

class StepRecorder : public QObject
{
Q_OBJECT

public:
StepRecorder(PianoRoll& pianoRoll, StepRecorderWidget& stepRecorderWidget);

void initialize();
void start(const MidiTime& currentPosition,const MidiTime& stepLength);
void stop();
void notePressed(const Note & n);
void noteReleased(const Note & n);
bool keyPressEvent(QKeyEvent* ke);
bool mousePressEvent(QMouseEvent* ke);
void setCurrentPattern(Pattern* newPattern);
void setStepsLength(const MidiTime& newLength);

QVector<Note*> getCurStepNotes();

bool isRecording() const
{
return m_isRecording;
}

QColor curStepNoteColor() const
{
return QColor(245,3,139); // radiant pink
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can move this to stylesheets later.

}

private slots:
void removeNotesReleasedForTooLong();

private:
void stepForwards();
void stepBackwards();

void applyStep();
void dismissStep();
void prepareNewStep();

MidiTime getCurStepEndPos();

void updateCurStepNotes();
void updateWidget();

bool allCurStepNotesReleased();

PianoRoll& m_pianoRoll;
StepRecorderWidget& m_stepRecorderWidget;

bool m_isRecording = false;
MidiTime m_curStepStartPos = 0;
MidiTime m_curStepEndPos = 0;

MidiTime m_stepsLength;
MidiTime m_curStepLength; // current step length refers to the step currently recorded. it may defer from m_stepsLength
// since the user can make current step larger

QTimer m_updateReleasedTimer;

Pattern* m_pattern;

class StepNote
{
public:
StepNote(const Note & note) : m_note(note), m_pressed(true) {};

void setPressed()
{
m_pressed = true;
}

void setReleased()
{
m_pressed = false;
releasedTimer.start();
}

int timeSinceReleased()
{
return releasedTimer.elapsed();
}

bool isPressed() const
{
return m_pressed;
}

bool isReleased() const
{
return !m_pressed;
}

Note m_note;

private:
bool m_pressed;
QTime releasedTimer;
} ;

QVector<StepNote*> m_curStepNotes; // contains the current recorded step notes (i.e. while user still press the notes; before they are applied to the pattern)

StepNote* findCurStepNote(const int key);

bool m_isStepInProgress = false;
};

#endif //STEP_RECORDER_H
92 changes: 92 additions & 0 deletions include/StepRecorderWidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* StepRecorderWidget.h - widget that provide gui markers for step recording
*
* This file is part of LMMS - https://lmms.io
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef STEP_RECOREDER_WIDGET_H
#define STEP_RECOREDER_WIDGET_H

#include "lmms_basics.h"
#include "Note.h"

#include <QWidget>
#include <QColor>
#include <QPainter>

class StepRecorderWidget : public QWidget
{
Q_OBJECT

public:
StepRecorderWidget(
QWidget * parent,
const int ppt,
const int marginTop,
const int marginBottom,
const int marginLeft,
const int marginRight);

//API used by PianoRoll
void setPixelsPerTact(int ppt);
void setCurrentPosition(MidiTime currentPosition);
void setBottomMargin(const int marginBottom);

//API used by StepRecorder
void setStepsLength(MidiTime stepsLength);
void setStartPosition(MidiTime pos);
void setEndPosition(MidiTime pos);

void showHint();

private:
virtual void paintEvent(QPaintEvent * pe);

int xCoordOfTick(int tick);

void drawVerLine(QPainter* painter, int x, const QColor& color, int top, int bottom);
void drawVerLine(QPainter* painter, const MidiTime& pos, const QColor& color, int top, int bottom);

void updateBoundaries();

MidiTime m_stepsLength;
MidiTime m_curStepStartPos;
MidiTime m_curStepEndPos;

int m_ppt; // pixels per tact
MidiTime m_currentPosition; // current position showed by on PianoRoll

QColor m_colorLineStart;
QColor m_colorLineEnd;

// boundaries within piano roll window
int m_top;
int m_bottom;
int m_left;
int m_right;

const int m_marginTop;
int m_marginBottom; // not const since can change on resize of edit-note area
const int m_marginLeft;
const int m_marginRight;

signals:
void positionChanged(const MidiTime & t);
} ;

#endif //STEP_RECOREDER_WIDGET_H
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ set(LMMS_SRCS
core/TrackContainer.cpp
core/ValueBuffer.cpp
core/VstSyncController.cpp
core/StepRecorder.cpp

core/audio/AudioAlsa.cpp
core/audio/AudioDevice.cpp
Expand Down
Loading