Compare commits
46 Commits
v1.3.0-alp
...
feature/be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c21d0b4d8 | ||
|
|
0dfdbc956a | ||
|
|
d3cd704396 | ||
|
|
040fb48867 | ||
|
|
2f66449092 | ||
|
|
cd2366a21c | ||
|
|
118d63bada | ||
|
|
53a733ba66 | ||
|
|
3ad0462d44 | ||
|
|
b701e82e3b | ||
|
|
ddf69feebc | ||
|
|
827d44be32 | ||
|
|
3c36365afa | ||
|
|
4f74151f00 | ||
|
|
9f0dc0fb1b | ||
|
|
d6b9853426 | ||
|
|
d73ede58a3 | ||
|
|
aff2ebcce0 | ||
|
|
c49ca376bf | ||
|
|
6e081265ba | ||
|
|
a2e71c81de | ||
|
|
7a85b4d547 | ||
|
|
f7128700b4 | ||
|
|
ee7175be75 | ||
|
|
246b822a6f | ||
|
|
9ca5497202 | ||
|
|
1949f93f10 | ||
|
|
571c425f4a | ||
|
|
ed9abe58c6 | ||
|
|
8d4bcd7105 | ||
|
|
b00adeadc5 | ||
|
|
53b003bc8f | ||
|
|
83e51ffc45 | ||
|
|
87875a18e3 | ||
|
|
f26296037a | ||
|
|
a42d2d2d70 | ||
|
|
060d0dc5dc | ||
|
|
3a74bad0c9 | ||
|
|
1c2107f4c6 | ||
|
|
48bc9db71d | ||
|
|
01f2fa5c29 | ||
|
|
7dd6a39366 | ||
|
|
4fb66542a0 | ||
|
|
28a394413f | ||
|
|
e1d1878108 | ||
|
|
5864aea3d3 |
@@ -170,7 +170,7 @@ jobs:
|
||||
environment:
|
||||
<<: *common_environment
|
||||
macos:
|
||||
xcode: "9.4.1"
|
||||
xcode: "10.3.0"
|
||||
steps:
|
||||
- checkout
|
||||
- *init
|
||||
|
||||
@@ -22,7 +22,7 @@ matrix:
|
||||
git:
|
||||
depth: false
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
osx_image: xcode10.3
|
||||
before_install:
|
||||
# appdmg doesn't work with old Node.js
|
||||
- if [ "$TRAVIS_OS_NAME" = osx ]; then nvm install 10; fi
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
[](https://discord.gg/3sc5su7)
|
||||
[](https://www.transifex.com/lmms/lmms/)
|
||||
|
||||
**A soft PR-Freeze is currently underway to prepare for refactoring ([#5592](https://github.com/LMMS/lmms/issues/5592)). Please do not open non-essential PRs at this time.**
|
||||
|
||||
What is LMMS?
|
||||
--------------
|
||||
|
||||
|
||||
BIN
data/themes/classic/midi_cc_rack.png
Normal file
BIN
data/themes/classic/midi_cc_rack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 554 B |
BIN
data/themes/classic/progression_bezier.png
Normal file
BIN
data/themes/classic/progression_bezier.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 677 B |
@@ -129,6 +129,12 @@ QMenu::indicator:selected {
|
||||
background-color: #747474;
|
||||
}
|
||||
|
||||
FileBrowser QCheckBox
|
||||
{
|
||||
font-size: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
PositionLine {
|
||||
qproperty-tailGradient: false;
|
||||
qproperty-lineColor: rgb(255, 255, 255);
|
||||
|
||||
BIN
data/themes/default/midi_cc_rack.png
Normal file
BIN
data/themes/default/midi_cc_rack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 554 B |
BIN
data/themes/default/progression_bezier.png
Normal file
BIN
data/themes/default/progression_bezier.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 B |
@@ -40,6 +40,12 @@ QMdiArea {
|
||||
background-color: #111314;
|
||||
}
|
||||
|
||||
FileBrowser QCheckBox
|
||||
{
|
||||
font-size: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
Knob {
|
||||
qproperty-lineInactiveColor: rgb(120, 120, 120);
|
||||
qproperty-arcInactiveColor: rgba(120, 120, 120, 70);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "Model.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "ValueBuffer.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ModelVisitor.h"
|
||||
@@ -281,7 +281,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
float globalAutomationValueAt( const MidiTime& time );
|
||||
float globalAutomationValueAt( const TimePos& time );
|
||||
|
||||
void setStrictStepSize( const bool b )
|
||||
{
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
}
|
||||
|
||||
void setModel( Model* model, bool isOldModelValid = true ) override;
|
||||
void unsetModel() override;
|
||||
|
||||
template<typename T>
|
||||
inline T value() const
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "AutomationPattern.h"
|
||||
#include "ComboBoxModel.h"
|
||||
#include "Knob.h"
|
||||
@@ -56,6 +56,7 @@ class AutomationEditor : public QWidget, public JournallingObject
|
||||
Q_PROPERTY(QColor beatLineColor READ beatLineColor WRITE setBeatLineColor)
|
||||
Q_PROPERTY(QColor lineColor READ lineColor WRITE setLineColor)
|
||||
Q_PROPERTY(QColor vertexColor READ vertexColor WRITE setVertexColor)
|
||||
Q_PROPERTY(QColor controlPointColor READ controlPointColor WRITE setControlPointColor)
|
||||
Q_PROPERTY(QBrush scaleColor READ scaleColor WRITE setScaleColor)
|
||||
Q_PROPERTY(QBrush graphColor READ graphColor WRITE setGraphColor)
|
||||
Q_PROPERTY(QColor crossColor READ crossColor WRITE setCrossColor)
|
||||
@@ -91,6 +92,8 @@ public:
|
||||
void setGraphColor(const QBrush & c);
|
||||
QColor vertexColor() const;
|
||||
void setVertexColor(const QColor & c);
|
||||
QColor controlPointColor() const;
|
||||
void setControlPointColor(const QColor& c);
|
||||
QBrush scaleColor() const;
|
||||
void setScaleColor(const QBrush & c);
|
||||
QColor crossColor() const;
|
||||
@@ -113,6 +116,7 @@ public slots:
|
||||
|
||||
protected:
|
||||
typedef AutomationPattern::timeMap timeMap;
|
||||
typedef AutomationPattern::controlPointTimeMap controlPointTimeMap;
|
||||
|
||||
void keyPressEvent(QKeyEvent * ke) override;
|
||||
void leaveEvent(QEvent * e) override;
|
||||
@@ -153,7 +157,7 @@ protected slots:
|
||||
void pasteValues();
|
||||
void deleteSelectedValues();
|
||||
|
||||
void updatePosition( const MidiTime & t );
|
||||
void updatePosition( const TimePos & t );
|
||||
|
||||
void zoomingXChanged();
|
||||
void zoomingYChanged();
|
||||
@@ -167,6 +171,7 @@ private:
|
||||
{
|
||||
NONE,
|
||||
MOVE_VALUE,
|
||||
MOVE_CONTROL_POINT,
|
||||
SELECT_VALUES,
|
||||
MOVE_SELECTION
|
||||
} ;
|
||||
@@ -215,7 +220,7 @@ private:
|
||||
QScrollBar * m_leftRightScroll;
|
||||
QScrollBar * m_topBottomScroll;
|
||||
|
||||
MidiTime m_currentPosition;
|
||||
TimePos m_currentPosition;
|
||||
|
||||
Actions m_action;
|
||||
|
||||
@@ -249,6 +254,7 @@ private:
|
||||
|
||||
void drawCross(QPainter & p );
|
||||
void drawAutomationPoint( QPainter & p, timeMap::iterator it );
|
||||
void drawControlPoint( QPainter & p, controlPointTimeMap::iterator it, float key_y );
|
||||
bool inBBEditor();
|
||||
|
||||
QColor m_barLineColor;
|
||||
@@ -256,6 +262,7 @@ private:
|
||||
QColor m_lineColor;
|
||||
QBrush m_graphColor;
|
||||
QColor m_vertexColor;
|
||||
QColor m_controlPointColor;
|
||||
QBrush m_scaleColor;
|
||||
QColor m_crossColor;
|
||||
QColor m_backgroundShade;
|
||||
@@ -265,7 +272,7 @@ private:
|
||||
|
||||
signals:
|
||||
void currentPatternChanged();
|
||||
void positionChanged( const MidiTime & );
|
||||
void positionChanged( const TimePos & );
|
||||
} ;
|
||||
|
||||
|
||||
@@ -313,6 +320,7 @@ private:
|
||||
QAction* m_discreteAction;
|
||||
QAction* m_linearAction;
|
||||
QAction* m_cubicHermiteAction;
|
||||
QAction* m_bezierAction;
|
||||
|
||||
QAction* m_flipYAction;
|
||||
QAction* m_flipXAction;
|
||||
|
||||
@@ -27,14 +27,15 @@
|
||||
#ifndef AUTOMATION_PATTERN_H
|
||||
#define AUTOMATION_PATTERN_H
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QMap>
|
||||
#include <QPair>
|
||||
#include <QPointer>
|
||||
|
||||
#include "Track.h"
|
||||
#include "TrackContentObject.h"
|
||||
|
||||
|
||||
class AutomationTrack;
|
||||
class MidiTime;
|
||||
class TimePos;
|
||||
|
||||
|
||||
|
||||
@@ -46,10 +47,12 @@ public:
|
||||
{
|
||||
DiscreteProgression,
|
||||
LinearProgression,
|
||||
CubicHermiteProgression
|
||||
CubicHermiteProgression,
|
||||
BezierProgression
|
||||
} ;
|
||||
|
||||
typedef QMap<int, float> timeMap;
|
||||
typedef QMap<int, QPair<int, float> > controlPointTimeMap;
|
||||
typedef QVector<QPointer<AutomatableModel> > objectVector;
|
||||
|
||||
AutomationPattern( AutomationTrack * _auto_track );
|
||||
@@ -74,25 +77,39 @@ public:
|
||||
}
|
||||
void setTension( QString _new_tension );
|
||||
|
||||
MidiTime timeMapLength() const;
|
||||
TimePos timeMapLength() const;
|
||||
void updateLength();
|
||||
|
||||
MidiTime putValue( const MidiTime & time,
|
||||
TimePos putValue( const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos = true,
|
||||
const bool ignoreSurroundingPoints = true );
|
||||
|
||||
void removeValue( const MidiTime & time );
|
||||
TimePos putControlPoint( timeMap::const_iterator it,
|
||||
const float _value);
|
||||
|
||||
void recordValue(MidiTime time, float value);
|
||||
TimePos putControlPoint(timeMap::const_iterator it,
|
||||
const int time, const float _value);
|
||||
|
||||
MidiTime setDragValue( const MidiTime & time,
|
||||
TimePos putControlPoint(timeMap::const_iterator it,
|
||||
const int time, const float _value, const bool flip);
|
||||
|
||||
void removeValue( const TimePos & time );
|
||||
|
||||
void recordValue(TimePos time, float value);
|
||||
|
||||
TimePos setDragValue( const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos = true,
|
||||
const bool controlKey = false );
|
||||
|
||||
TimePos setControlPointDragValue( const TimePos & _time, const float _value, const int _x,
|
||||
const bool _quant_pos = true );
|
||||
|
||||
void applyDragValue();
|
||||
|
||||
void flipControlPoint(bool flip);
|
||||
|
||||
|
||||
bool isDragging() const
|
||||
{
|
||||
@@ -119,6 +136,27 @@ public:
|
||||
return m_tangents;
|
||||
}
|
||||
|
||||
inline const controlPointTimeMap & getControlPoints() const
|
||||
{
|
||||
return m_controlPoints;
|
||||
}
|
||||
|
||||
inline controlPointTimeMap & getControlPoints()
|
||||
{
|
||||
return m_controlPoints;
|
||||
}
|
||||
|
||||
// This is for getting the node of the control point that is being dragged
|
||||
inline const timeMap::ConstIterator & getControlPointNode() const
|
||||
{
|
||||
return m_oldControlPointNode;
|
||||
}
|
||||
|
||||
inline timeMap::ConstIterator & getControlPointNode()
|
||||
{
|
||||
return m_oldControlPointNode;
|
||||
}
|
||||
|
||||
inline float getMin() const
|
||||
{
|
||||
return firstObject()->minValue<float>();
|
||||
@@ -134,8 +172,8 @@ public:
|
||||
return m_timeMap.isEmpty() == false;
|
||||
}
|
||||
|
||||
float valueAt( const MidiTime & _time ) const;
|
||||
float *valuesAfter( const MidiTime & _time ) const;
|
||||
float valueAt( const TimePos & _time ) const;
|
||||
float *valuesAfter( const TimePos & _time ) const;
|
||||
|
||||
const QString name() const;
|
||||
|
||||
@@ -160,6 +198,8 @@ public:
|
||||
static int quantization() { return s_quantization; }
|
||||
static void setQuantization(int q) { s_quantization = q; }
|
||||
|
||||
void clampControlPoints(bool clampVertical=true);
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
void objectDestroyed( jo_id_t );
|
||||
@@ -169,6 +209,7 @@ public slots:
|
||||
|
||||
private:
|
||||
void cleanObjects();
|
||||
void cleanControlPoints();
|
||||
void generateTangents();
|
||||
void generateTangents( timeMap::const_iterator it, int numToGenerate );
|
||||
float valueAt( timeMap::const_iterator v, int offset ) const;
|
||||
@@ -179,12 +220,20 @@ private:
|
||||
timeMap m_timeMap; // actual values
|
||||
timeMap m_oldTimeMap; // old values for storing the values before setDragValue() is called.
|
||||
timeMap m_tangents; // slope at each point for calculating spline
|
||||
controlPointTimeMap m_controlPoints; // control points for calculating the bezier curve
|
||||
controlPointTimeMap m_oldControlPoints; // old values for storing the values before setDragValue() is called.
|
||||
// m_oldControlPoints is similar to m_oldTimeMap, since the control points need to be dragged as well or something
|
||||
timeMap::const_iterator m_oldControlPointNode; // Which automation point was the control point connected to?
|
||||
bool m_controlFlip; // If the lefthand control point is grabbed, the value must be flipped around the automation point
|
||||
|
||||
float m_controlPointDragOffset[2];
|
||||
|
||||
float m_tension;
|
||||
bool m_hasAutomation;
|
||||
ProgressionTypes m_progressionType;
|
||||
|
||||
bool m_dragging;
|
||||
|
||||
|
||||
bool m_isRecording;
|
||||
float m_lastRecordedValue;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "AutomationPattern.h"
|
||||
#include "Song.h"
|
||||
#include "SongEditor.h"
|
||||
#include "Track.h"
|
||||
#include "TrackContentObjectView.h"
|
||||
|
||||
|
||||
class AutomationPatternView : public TrackContentObjectView
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define AUTOMATION_TRACK_H
|
||||
|
||||
#include "Track.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
|
||||
class AutomationTrack : public Track
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
AutomationTrack( TrackContainer* tc, bool _hidden = false );
|
||||
virtual ~AutomationTrack() = default;
|
||||
|
||||
virtual bool play( const MidiTime & _start, const fpp_t _frames,
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
@@ -46,7 +47,7 @@ public:
|
||||
}
|
||||
|
||||
TrackView * createView( TrackContainerView* ) override;
|
||||
TrackContentObject* createTCO(const MidiTime & pos) override;
|
||||
TrackContentObject* createTCO(const TimePos & pos) override;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent ) override;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef BB_EDITOR_H
|
||||
#define BB_EDITOR_H
|
||||
|
||||
|
||||
#include "Editor.h"
|
||||
#include "TrackContainerView.h"
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
#include <QtCore/QMap>
|
||||
#include <QStaticText>
|
||||
|
||||
#include "TrackContentObjectView.h"
|
||||
#include "Track.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
class TrackLabelButton;
|
||||
class TrackContainer;
|
||||
@@ -103,10 +105,10 @@ public:
|
||||
BBTrack( TrackContainer* tc );
|
||||
virtual ~BBTrack();
|
||||
|
||||
virtual bool play( const MidiTime & _start, const fpp_t _frames,
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
TrackView * createView( TrackContainerView* tcv ) override;
|
||||
TrackContentObject* createTCO(const MidiTime & pos) override;
|
||||
TrackContentObject* createTCO(const TimePos & pos) override;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent ) override;
|
||||
|
||||
@@ -38,8 +38,7 @@ public:
|
||||
BBTrackContainer();
|
||||
virtual ~BBTrackContainer();
|
||||
|
||||
virtual bool play( MidiTime _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 );
|
||||
virtual bool play(TimePos start, const fpp_t frames, const f_cnt_t frameBase, int tcoNum = -1);
|
||||
|
||||
void updateAfterTrackAdd() override;
|
||||
|
||||
@@ -48,21 +47,21 @@ public:
|
||||
return "bbtrackcontainer";
|
||||
}
|
||||
|
||||
bar_t lengthOfBB( int _bb ) const;
|
||||
bar_t lengthOfBB(int bb) const;
|
||||
inline bar_t lengthOfCurrentBB()
|
||||
{
|
||||
return lengthOfBB( currentBB() );
|
||||
return lengthOfBB(currentBB());
|
||||
}
|
||||
int numOfBBs() const;
|
||||
void removeBB( int _bb );
|
||||
void removeBB(int bb);
|
||||
|
||||
void swapBB( int _bb1, int _bb2 );
|
||||
void swapBB(int bb1, int bb2);
|
||||
|
||||
void updateBBTrack( TrackContentObject * _tco );
|
||||
void updateBBTrack(TrackContentObject * tco);
|
||||
void fixIncorrectPositions();
|
||||
void createTCOsForBB( int _bb );
|
||||
void createTCOsForBB(int bb);
|
||||
|
||||
AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum) const override;
|
||||
AutomatedValueMap automatedValuesAt(TimePos time, int tcoNum) const override;
|
||||
|
||||
public slots:
|
||||
void play();
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class BBTrackContainer;
|
||||
class DummyTrackContainer;
|
||||
class FxMixer;
|
||||
class ProjectJournal;
|
||||
class Mixer;
|
||||
@@ -88,6 +87,8 @@ public:
|
||||
return s_projectJournal;
|
||||
}
|
||||
|
||||
static bool ignorePluginBlacklist();
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
static class Lv2Manager * getLv2Manager()
|
||||
{
|
||||
@@ -100,11 +101,6 @@ public:
|
||||
return s_ladspaManager;
|
||||
}
|
||||
|
||||
static DummyTrackContainer * dummyTrackContainer()
|
||||
{
|
||||
return s_dummyTC;
|
||||
}
|
||||
|
||||
static float framesPerTick()
|
||||
{
|
||||
return s_framesPerTick;
|
||||
@@ -149,7 +145,6 @@ private:
|
||||
static Song * s_song;
|
||||
static BBTrackContainer * s_bbTrackContainer;
|
||||
static ProjectJournal * s_projectJournal;
|
||||
static DummyTrackContainer * s_dummyTC;
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
static class Lv2Manager* s_lv2Manager;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef FILE_BROWSER_H
|
||||
#define FILE_BROWSER_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QTreeWidget>
|
||||
@@ -58,7 +59,10 @@ public:
|
||||
*/
|
||||
FileBrowser( const QString & directories, const QString & filter,
|
||||
const QString & title, const QPixmap & pm,
|
||||
QWidget * parent, bool dirs_as_items = false, bool recurse = false );
|
||||
QWidget * parent, bool dirs_as_items = false, bool recurse = false,
|
||||
const QString& userDir = "",
|
||||
const QString& factoryDir = "");
|
||||
|
||||
virtual ~FileBrowser() = default;
|
||||
|
||||
private slots:
|
||||
@@ -83,6 +87,11 @@ private:
|
||||
bool m_dirsAsItems;
|
||||
bool m_recurse;
|
||||
|
||||
void addContentCheckBox();
|
||||
QCheckBox* m_showUserContent = nullptr;
|
||||
QCheckBox* m_showFactoryContent = nullptr;
|
||||
QString m_userDir;
|
||||
QString m_factoryDir;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,13 @@ class FxChannel : public ThreadableJob
|
||||
void unmuteForSolo();
|
||||
|
||||
|
||||
// TODO C++17 and above: use std::optional insteads
|
||||
void setColor (QColor newColor)
|
||||
{
|
||||
m_color = newColor;
|
||||
m_hasColor = true;
|
||||
}
|
||||
|
||||
// TODO C++17 and above: use std::optional instead
|
||||
QColor m_color;
|
||||
bool m_hasColor;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
class QLabel;
|
||||
|
||||
@@ -48,6 +49,9 @@ public:
|
||||
~GuiApplication();
|
||||
|
||||
static GuiApplication* instance();
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
static QFont getWin32SystemFont();
|
||||
#endif
|
||||
|
||||
MainWindow* mainWindow() { return m_mainWindow; }
|
||||
FxMixerView* fxMixerView() { return m_fxMixerView; }
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "MidiTime.h"
|
||||
#include "Plugin.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
|
||||
// forward-declarations
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
|
||||
// sub-classes can re-implement this for receiving all incoming
|
||||
// MIDI-events
|
||||
inline virtual bool handleMidiEvent( const MidiEvent&, const MidiTime& = MidiTime(), f_cnt_t offset = 0 )
|
||||
inline virtual bool handleMidiEvent( const MidiEvent&, const TimePos& = TimePos(), f_cnt_t offset = 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "GroupBox.h"
|
||||
#include "InstrumentFunctions.h"
|
||||
#include "InstrumentSoundShaping.h"
|
||||
#include "Midi.h"
|
||||
#include "MidiCCRackView.h"
|
||||
#include "MidiEventProcessor.h"
|
||||
#include "MidiPort.h"
|
||||
#include "NotePlayHandle.h"
|
||||
@@ -38,11 +40,11 @@
|
||||
#include "Pitch.h"
|
||||
#include "Plugin.h"
|
||||
#include "Track.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
|
||||
|
||||
class QLineEdit;
|
||||
template<class T> class QQueue;
|
||||
class InstrumentFunctionArpeggioView;
|
||||
class InstrumentFunctionNoteStackingView;
|
||||
class EffectRackView;
|
||||
@@ -80,8 +82,8 @@ public:
|
||||
|
||||
MidiEvent applyMasterKey( const MidiEvent& event );
|
||||
|
||||
void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override;
|
||||
void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override;
|
||||
void processInEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 ) override;
|
||||
void processOutEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 ) override;
|
||||
// silence all running notes played by this track
|
||||
void silenceAllNotes( bool removeIPH = false );
|
||||
|
||||
@@ -130,13 +132,13 @@ public:
|
||||
}
|
||||
|
||||
// play everything in given frame-range - creates note-play-handles
|
||||
virtual bool play( const MidiTime & _start, const fpp_t _frames,
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
// create new view for me
|
||||
TrackView * createView( TrackContainerView* tcv ) override;
|
||||
|
||||
// create new track-content-object = pattern
|
||||
TrackContentObject* createTCO(const MidiTime & pos) override;
|
||||
TrackContentObject* createTCO(const TimePos & pos) override;
|
||||
|
||||
|
||||
// called by track
|
||||
@@ -229,7 +231,6 @@ signals:
|
||||
void newNote();
|
||||
void endNote();
|
||||
|
||||
|
||||
protected:
|
||||
QString nodeName() const override
|
||||
{
|
||||
@@ -248,6 +249,8 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
void processCCEvent(int controller);
|
||||
|
||||
MidiPort m_midiPort;
|
||||
|
||||
NotePlayHandle* m_notes[NumKeys];
|
||||
@@ -287,11 +290,14 @@ private:
|
||||
|
||||
Piano m_piano;
|
||||
|
||||
std::unique_ptr<BoolModel> m_midiCCEnable;
|
||||
std::unique_ptr<FloatModel> m_midiCCModel[MidiControllerCount];
|
||||
|
||||
friend class InstrumentTrackView;
|
||||
friend class InstrumentTrackWindow;
|
||||
friend class NotePlayHandle;
|
||||
friend class InstrumentMiscView;
|
||||
friend class MidiCCRackView;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -324,10 +330,6 @@ public:
|
||||
return m_midiMenu;
|
||||
}
|
||||
|
||||
void freeInstrumentTrackWindow();
|
||||
|
||||
static void cleanupWindowCache();
|
||||
|
||||
// Create a menu for assigning/creating channels for this track
|
||||
QMenu * createFxMenu( QString title, QString newFxLabel ) override;
|
||||
|
||||
@@ -339,6 +341,7 @@ protected:
|
||||
|
||||
private slots:
|
||||
void toggleInstrumentWindow( bool _on );
|
||||
void toggleMidiCCRack();
|
||||
void activityIndicatorPressed();
|
||||
void activityIndicatorReleased();
|
||||
|
||||
@@ -349,12 +352,12 @@ private slots:
|
||||
void assignFxLine( int channelIndex );
|
||||
void createFxLine();
|
||||
|
||||
void handleConfigChange(QString cls, QString attr, QString value);
|
||||
|
||||
|
||||
private:
|
||||
InstrumentTrackWindow * m_window;
|
||||
|
||||
static QQueue<InstrumentTrackWindow *> s_windowCache;
|
||||
|
||||
// widgets in track-settings-widget
|
||||
TrackLabelButton * m_tlb;
|
||||
Knob * m_volumeKnob;
|
||||
@@ -366,9 +369,11 @@ private:
|
||||
QAction * m_midiInputAction;
|
||||
QAction * m_midiOutputAction;
|
||||
|
||||
std::unique_ptr<MidiCCRackView> m_midiCCRackView;
|
||||
|
||||
QPoint m_lastPos;
|
||||
|
||||
FadeButton * getActivityIndicator()
|
||||
FadeButton * getActivityIndicator() override
|
||||
{
|
||||
return m_activityIndicator;
|
||||
}
|
||||
@@ -482,6 +487,7 @@ private:
|
||||
PianoView * m_pianoView;
|
||||
|
||||
friend class InstrumentView;
|
||||
friend class InstrumentTrackView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class LMMS_EXPORT Lv2ControlBase : public LinkedModelGroups
|
||||
{
|
||||
public:
|
||||
static Plugin::PluginTypes check(const LilvPlugin* m_plugin,
|
||||
std::vector<PluginIssue> &issues, bool printIssues = false);
|
||||
std::vector<PluginIssue> &issues);
|
||||
|
||||
const LilvPlugin* getPlugin() const { return m_plugin; }
|
||||
|
||||
@@ -134,7 +134,7 @@ protected:
|
||||
QString nodeName() const { return "lv2controls"; }
|
||||
bool hasNoteInput() const;
|
||||
void handleMidiInputEvent(const class MidiEvent &event,
|
||||
const class MidiTime &time, f_cnt_t offset);
|
||||
const class TimePos &time, f_cnt_t offset);
|
||||
|
||||
private:
|
||||
//! Return the DataFile settings type
|
||||
|
||||
@@ -130,6 +130,13 @@ public:
|
||||
return m_supportedFeatureURIs;
|
||||
}
|
||||
bool isFeatureSupported(const char* featName) const;
|
||||
AutoLilvNodes findNodes(const LilvNode *subject,
|
||||
const LilvNode *predicate, const LilvNode *object);
|
||||
|
||||
static const std::set<const char*, Lv2Manager::CmpStr>& getPluginBlacklist()
|
||||
{
|
||||
return pluginBlacklist;
|
||||
}
|
||||
|
||||
private:
|
||||
// general data
|
||||
@@ -144,6 +151,9 @@ private:
|
||||
// URID cache for fast URID access
|
||||
Lv2UridCache m_uridCache;
|
||||
|
||||
// static
|
||||
static const std::set<const char*, Lv2Manager::CmpStr> pluginBlacklist;
|
||||
|
||||
// functions
|
||||
bool isSubclassOf(const LilvPluginClass *clvss, const char *uriStr);
|
||||
};
|
||||
|
||||
104
include/Lv2Options.h
Normal file
104
include/Lv2Options.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Lv2Options.h - Lv2Options class
|
||||
*
|
||||
* Copyright (c) 2020-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* 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 LV2OPTIONS_H
|
||||
#define LV2OPTIONS_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <cstdint>
|
||||
#include <lv2/lv2plug.in/ns/ext/options/options.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "Engine.h"
|
||||
#include "Lv2Manager.h"
|
||||
#include "Lv2UridCache.h"
|
||||
|
||||
/**
|
||||
Option container
|
||||
|
||||
References all available options for a plugin and maps them to their URIDs.
|
||||
This class is used per Lv2 processor (justification in Lv2Proc::initMOptions())
|
||||
|
||||
The public member functions should be called in descending order:
|
||||
|
||||
1. supportOption: set all supported option URIDs
|
||||
2. initOption: initialize options with values
|
||||
3. createOptionVectors: create the option vectors required for
|
||||
the feature
|
||||
4. access the latter using feature()
|
||||
*/
|
||||
class Lv2Options
|
||||
{
|
||||
public:
|
||||
//! Return if an option is supported by LMMS
|
||||
static bool isOptionSupported(LV2_URID key);
|
||||
//! Mark option as supported
|
||||
static void supportOption(LV2_URID key);
|
||||
|
||||
//! Initialize an option
|
||||
template<typename Opt, typename Arg>
|
||||
void initOption(Lv2UridCache::Id key, Arg&& value,
|
||||
LV2_Options_Context context = LV2_OPTIONS_INSTANCE,
|
||||
std::uint32_t subject = 0)
|
||||
{
|
||||
const Lv2UridCache& cache = Engine::getLv2Manager()->uridCache();
|
||||
initOption(cache[key], sizeof(Opt), cache[Lv2UridCache::IdForType<Opt>::value],
|
||||
std::make_shared<Opt>(std::forward<Arg>(value)), context, subject);
|
||||
}
|
||||
//! Fill m_options and m_optionPointers with all options
|
||||
void createOptionVectors();
|
||||
//! Return the feature
|
||||
const LV2_Options_Option* feature() const
|
||||
{
|
||||
return m_options.data();
|
||||
}
|
||||
|
||||
private:
|
||||
//! Initialize an option internally
|
||||
void initOption(LV2_URID key,
|
||||
uint32_t size,
|
||||
LV2_URID type,
|
||||
std::shared_ptr<void> value,
|
||||
LV2_Options_Context context = LV2_OPTIONS_INSTANCE,
|
||||
uint32_t subject = 0);
|
||||
//! options that are supported by every processor
|
||||
static std::set<LV2_URID> s_supportedOptions;
|
||||
//! options + data, ordered by URID
|
||||
std::map<LV2_URID, LV2_Options_Option> m_optionByUrid;
|
||||
//! option storage
|
||||
std::vector<LV2_Options_Option> m_options;
|
||||
//! option value storage
|
||||
std::map<LV2_URID, std::shared_ptr<void>> m_optionValues;
|
||||
};
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
|
||||
#endif // LV2OPTIONS_H
|
||||
@@ -61,10 +61,10 @@ enum class Type {
|
||||
//! Port visualization
|
||||
//! @note All Lv2 audio ports are float, this is only the visualisation
|
||||
enum class Vis {
|
||||
None,
|
||||
Integer,
|
||||
Enumeration,
|
||||
Toggled
|
||||
Generic, //!< nothing specific, a generic knob or slider shall be used
|
||||
Integer, //!< counter
|
||||
Enumeration, //!< selection from enumerated values
|
||||
Toggled //!< boolean widget
|
||||
};
|
||||
|
||||
const char* toStr(Lv2Ports::Flow pf);
|
||||
@@ -106,13 +106,21 @@ struct Meta
|
||||
{
|
||||
Type m_type = Type::Unknown;
|
||||
Flow m_flow = Flow::Unknown;
|
||||
Vis m_vis = Vis::None;
|
||||
Vis m_vis = Vis::Generic;
|
||||
|
||||
bool m_logarithmic = false;
|
||||
|
||||
float m_def = .0f, m_min = .0f, m_max = .0f;
|
||||
bool m_optional = false;
|
||||
bool m_used = true;
|
||||
|
||||
std::vector<PluginIssue> get(const LilvPlugin* plugin, std::size_t portNum);
|
||||
|
||||
float def() const { return m_def; }
|
||||
float min(sample_rate_t sr) const { return m_sampleRate ? sr * m_min : m_min; }
|
||||
float max(sample_rate_t sr) const { return m_sampleRate ? sr * m_max : m_max; }
|
||||
private:
|
||||
float m_def = .0f, m_min = .0f, m_max = .0f;
|
||||
bool m_sampleRate = false;
|
||||
};
|
||||
|
||||
struct PortBase : public Meta
|
||||
|
||||
@@ -35,12 +35,13 @@
|
||||
|
||||
#include "Lv2Basics.h"
|
||||
#include "Lv2Features.h"
|
||||
#include "Lv2Options.h"
|
||||
#include "LinkedModelGroups.h"
|
||||
#include "MidiEvent.h"
|
||||
#include "MidiTime.h"
|
||||
#include "Plugin.h"
|
||||
#include "PluginIssue.h"
|
||||
#include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
// forward declare port structs/enums
|
||||
namespace Lv2Ports
|
||||
@@ -61,7 +62,7 @@ class Lv2Proc : public LinkedModelGroup
|
||||
{
|
||||
public:
|
||||
static Plugin::PluginTypes check(const LilvPlugin* plugin,
|
||||
std::vector<PluginIssue> &issues, bool printIssues = false);
|
||||
std::vector<PluginIssue> &issues);
|
||||
|
||||
/*
|
||||
ctor/dtor
|
||||
@@ -144,7 +145,7 @@ public:
|
||||
void run(fpp_t frames);
|
||||
|
||||
void handleMidiInputEvent(const class MidiEvent &event,
|
||||
const MidiTime &time, f_cnt_t offset);
|
||||
const TimePos &time, f_cnt_t offset);
|
||||
|
||||
/*
|
||||
misc
|
||||
@@ -168,6 +169,7 @@ private:
|
||||
const LilvPlugin* m_plugin;
|
||||
LilvInstance* m_instance;
|
||||
Lv2Features m_features;
|
||||
Lv2Options m_options;
|
||||
|
||||
// full list of ports
|
||||
std::vector<std::unique_ptr<Lv2Ports::PortBase>> m_ports;
|
||||
@@ -187,11 +189,12 @@ private:
|
||||
ringbuffer_reader_t<struct MidiInputEvent> m_midiInputReader;
|
||||
|
||||
// other
|
||||
static std::size_t minimumEvbufSize() { return 1 << 15; /* ardour uses this*/ }
|
||||
static int32_t defaultEvbufSize() { return 1 << 15; /* ardour uses this*/ }
|
||||
|
||||
//! models for the controls, sorted by port symbols
|
||||
std::map<std::string, AutomatableModel *> m_connectedModels;
|
||||
|
||||
void initMOptions(); //!< initialize m_options
|
||||
void initPluginSpecificFeatures();
|
||||
|
||||
//! load a file in the plugin, but don't do anything in LMMS
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <cstdint>
|
||||
|
||||
//! Cached URIDs for fast access (for use in real-time code)
|
||||
@@ -37,16 +38,33 @@ class Lv2UridCache
|
||||
public:
|
||||
enum class Id //!< ID for m_uridCache array
|
||||
{
|
||||
// keep it alphabetically (except "size" at the end)
|
||||
atom_Float,
|
||||
atom_Int,
|
||||
bufsz_minBlockLength,
|
||||
bufsz_maxBlockLength,
|
||||
bufsz_nominalBlockLength,
|
||||
bufsz_sequenceSize,
|
||||
midi_MidiEvent,
|
||||
param_sampleRate,
|
||||
// exception to alphabetic ordering - keep at the end:
|
||||
size
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IdForType;
|
||||
|
||||
//! Return URID for a cache ID
|
||||
uint32_t operator[](Id id) const;
|
||||
|
||||
Lv2UridCache(class UridMap& mapper);
|
||||
|
||||
private:
|
||||
uint32_t m_cache[static_cast<int>(Id::size)];
|
||||
};
|
||||
|
||||
template<> struct Lv2UridCache::IdForType<float> { static constexpr auto value = Id::atom_Float; };
|
||||
template<> struct Lv2UridCache::IdForType<std::int32_t> { static constexpr auto value = Id::atom_Int; };
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
#endif // LV2URIDCACHE_H
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
|
||||
|
||||
virtual void processOutEvent( const MidiEvent & _me,
|
||||
const MidiTime & _time,
|
||||
const TimePos & _time,
|
||||
const MidiPort * _port ) override;
|
||||
|
||||
void applyPortMode( MidiPort * _port ) override;
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void processOutEvent( const MidiEvent & _me,
|
||||
const MidiTime & _time,
|
||||
const TimePos & _time,
|
||||
const MidiPort * _port );
|
||||
|
||||
virtual void applyPortMode( MidiPort * _port );
|
||||
|
||||
40
include/MidiCCRackView.h
Normal file
40
include/MidiCCRackView.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef MIDI_CC_RACK_VIEW_H
|
||||
#define MIDI_CC_RACK_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "GroupBox.h"
|
||||
#include "Knob.h"
|
||||
#include "Midi.h"
|
||||
#include "SerializingObject.h"
|
||||
|
||||
class InstrumentTrack;
|
||||
|
||||
class MidiCCRackView : public QWidget, public SerializingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MidiCCRackView(InstrumentTrack * track);
|
||||
~MidiCCRackView() override;
|
||||
|
||||
void saveSettings(QDomDocument & doc, QDomElement & parent) override;
|
||||
void loadSettings(const QDomElement &) override;
|
||||
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return "MidiCCRackView";
|
||||
}
|
||||
|
||||
private slots:
|
||||
void renameWindow();
|
||||
|
||||
private:
|
||||
InstrumentTrack *m_track;
|
||||
|
||||
GroupBox *m_midiCCGroupBox; // MIDI CC GroupBox (used to enable disable MIDI CC)
|
||||
|
||||
Knob *m_controllerKnob[MidiControllerCount]; // Holds the knob widgets for each controller
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
// to be implemented by sub-classes
|
||||
virtual void processOutEvent( const MidiEvent & _me,
|
||||
const MidiTime & _time,
|
||||
const TimePos & _time,
|
||||
const MidiPort * _port ) = 0;
|
||||
|
||||
// inheriting classes can re-implement this for being able to update
|
||||
@@ -141,7 +141,7 @@ protected:
|
||||
private:
|
||||
// this does MIDI-event-process
|
||||
void processParsedEvent();
|
||||
void processOutEvent( const MidiEvent& event, const MidiTime& time, const MidiPort* port ) override;
|
||||
void processOutEvent( const MidiEvent& event, const TimePos& time, const MidiPort* port ) override;
|
||||
|
||||
// small helper function returning length of a certain event - this
|
||||
// is necessary for parsing raw-MIDI-data
|
||||
|
||||
@@ -44,10 +44,10 @@ public:
|
||||
virtual ~MidiController();
|
||||
|
||||
virtual void processInEvent( const MidiEvent & _me,
|
||||
const MidiTime & _time, f_cnt_t offset = 0 ) override;
|
||||
const TimePos & _time, f_cnt_t offset = 0 ) override;
|
||||
|
||||
virtual void processOutEvent( const MidiEvent& _me,
|
||||
const MidiTime & _time, f_cnt_t offset = 0 ) override
|
||||
const TimePos & _time, f_cnt_t offset = 0 ) override
|
||||
{
|
||||
// No output yet
|
||||
}
|
||||
|
||||
@@ -33,27 +33,32 @@
|
||||
class MidiEvent
|
||||
{
|
||||
public:
|
||||
MidiEvent( MidiEventTypes type = MidiActiveSensing,
|
||||
enum class Source { Internal, External };
|
||||
|
||||
MidiEvent(MidiEventTypes type = MidiActiveSensing,
|
||||
int8_t channel = 0,
|
||||
int16_t param1 = 0,
|
||||
int16_t param2 = 0,
|
||||
const void* sourcePort = NULL ) :
|
||||
const void* sourcePort = nullptr,
|
||||
Source source = Source::External) :
|
||||
m_type( type ),
|
||||
m_metaEvent( MidiMetaInvalid ),
|
||||
m_channel( channel ),
|
||||
m_sysExData( NULL ),
|
||||
m_sourcePort( sourcePort )
|
||||
m_sourcePort(sourcePort),
|
||||
m_source(source)
|
||||
{
|
||||
m_data.m_param[0] = param1;
|
||||
m_data.m_param[1] = param2;
|
||||
}
|
||||
|
||||
MidiEvent( MidiEventTypes type, const char* sysExData, int dataLen ) :
|
||||
MidiEvent(MidiEventTypes type, const char* sysExData, std::size_t dataLen, Source source = Source::External) :
|
||||
m_type( type ),
|
||||
m_metaEvent( MidiMetaInvalid ),
|
||||
m_channel( 0 ),
|
||||
m_sysExData( sysExData ),
|
||||
m_sourcePort( NULL )
|
||||
m_sourcePort(nullptr),
|
||||
m_source(source)
|
||||
{
|
||||
m_data.m_sysExDataLen = dataLen;
|
||||
}
|
||||
@@ -64,7 +69,8 @@ public:
|
||||
m_channel( other.m_channel ),
|
||||
m_data( other.m_data ),
|
||||
m_sysExData( other.m_sysExData ),
|
||||
m_sourcePort( other.m_sourcePort )
|
||||
m_sourcePort(other.m_sourcePort),
|
||||
m_source(other.m_source)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -190,6 +196,16 @@ public:
|
||||
setParam( 0, pitchBend );
|
||||
}
|
||||
|
||||
Source source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
void setSource(Source value)
|
||||
{
|
||||
m_source = value;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
MidiEventTypes m_type; // MIDI event type
|
||||
@@ -198,13 +214,15 @@ private:
|
||||
union
|
||||
{
|
||||
int16_t m_param[2]; // first/second parameter (key/velocity)
|
||||
uint8_t m_bytes[4]; // raw bytes
|
||||
uint8_t m_bytes[4]; // raw bytes
|
||||
int32_t m_sysExDataLen; // len of m_sysExData
|
||||
} m_data;
|
||||
|
||||
const char* m_sysExData;
|
||||
const void* m_sourcePort;
|
||||
|
||||
// Stores the source of the MidiEvent: Internal or External (hardware controllers).
|
||||
Source m_source;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
#define MIDI_EVENT_PROCESSOR_H
|
||||
|
||||
#include "MidiEvent.h"
|
||||
#include "MidiTime.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
// all classes being able to process MIDI-events should inherit from this
|
||||
class MidiEventProcessor
|
||||
@@ -43,8 +43,8 @@ public:
|
||||
}
|
||||
|
||||
// to be implemented by inheriting classes
|
||||
virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) = 0;
|
||||
virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) = 0;
|
||||
virtual void processInEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 ) = 0;
|
||||
virtual void processOutEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 ) = 0;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <QtCore/QMap>
|
||||
|
||||
#include "Midi.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
|
||||
@@ -102,8 +102,8 @@ public:
|
||||
return outputChannel() ? outputChannel() - 1 : 0;
|
||||
}
|
||||
|
||||
void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() );
|
||||
void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() );
|
||||
void processInEvent( const MidiEvent& event, const TimePos& time = TimePos() );
|
||||
void processOutEvent( const MidiEvent& event, const TimePos& time = TimePos() );
|
||||
|
||||
|
||||
void saveSettings( QDomDocument& doc, QDomElement& thisElement ) override;
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
|
||||
virtual void processOutEvent( const MidiEvent & _me,
|
||||
const MidiTime & _time,
|
||||
const TimePos & _time,
|
||||
const MidiPort * _port );
|
||||
|
||||
virtual void applyPortMode( MidiPort * _port );
|
||||
|
||||
@@ -173,8 +173,6 @@ public:
|
||||
|
||||
//! Set new audio device. Old device will be deleted,
|
||||
//! unless it's stored using storeAudioDevice
|
||||
void setAudioDevice( AudioDevice * _dev , bool startNow );
|
||||
//! See overloaded function
|
||||
void setAudioDevice( AudioDevice * _dev,
|
||||
const struct qualitySettings & _qs,
|
||||
bool _needs_fifo,
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
virtual ~ModelView();
|
||||
|
||||
virtual void setModel( Model* model, bool isOldModelValid = true );
|
||||
virtual void unsetModel();
|
||||
|
||||
Model* model()
|
||||
{
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "volume.h"
|
||||
#include "panning.h"
|
||||
#include "MidiTime.h"
|
||||
#include "SerializingObject.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
class DetuningHelper;
|
||||
|
||||
@@ -81,8 +81,8 @@ const float MaxDetuning = 4 * 12.0f;
|
||||
class LMMS_EXPORT Note : public SerializingObject
|
||||
{
|
||||
public:
|
||||
Note( const MidiTime & length = MidiTime( 0 ),
|
||||
const MidiTime & pos = MidiTime( 0 ),
|
||||
Note( const TimePos & length = TimePos( 0 ),
|
||||
const TimePos & pos = TimePos( 0 ),
|
||||
int key = DefaultKey,
|
||||
volume_t volume = DefaultVolume,
|
||||
panning_t panning = DefaultPanning,
|
||||
@@ -93,9 +93,9 @@ public:
|
||||
// used by GUI
|
||||
inline void setSelected( const bool selected ) { m_selected = selected; }
|
||||
inline void setOldKey( const int oldKey ) { m_oldKey = oldKey; }
|
||||
inline void setOldPos( const MidiTime & oldPos ) { m_oldPos = oldPos; }
|
||||
inline void setOldPos( const TimePos & oldPos ) { m_oldPos = oldPos; }
|
||||
|
||||
inline void setOldLength( const MidiTime & oldLength )
|
||||
inline void setOldLength( const TimePos & oldLength )
|
||||
{
|
||||
m_oldLength = oldLength;
|
||||
}
|
||||
@@ -105,8 +105,8 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void setLength( const MidiTime & length );
|
||||
void setPos( const MidiTime & pos );
|
||||
void setLength( const TimePos & length );
|
||||
void setPos( const TimePos & pos );
|
||||
void setKey( const int key );
|
||||
virtual void setVolume( volume_t volume );
|
||||
virtual void setPanning( panning_t panning );
|
||||
@@ -138,12 +138,12 @@ public:
|
||||
return m_oldKey;
|
||||
}
|
||||
|
||||
inline MidiTime oldPos() const
|
||||
inline TimePos oldPos() const
|
||||
{
|
||||
return m_oldPos;
|
||||
}
|
||||
|
||||
inline MidiTime oldLength() const
|
||||
inline TimePos oldLength() const
|
||||
{
|
||||
return m_oldLength;
|
||||
}
|
||||
@@ -153,23 +153,23 @@ public:
|
||||
return m_isPlaying;
|
||||
}
|
||||
|
||||
inline MidiTime endPos() const
|
||||
inline TimePos endPos() const
|
||||
{
|
||||
const int l = length();
|
||||
return pos() + l;
|
||||
}
|
||||
|
||||
inline const MidiTime & length() const
|
||||
inline const TimePos & length() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline const MidiTime & pos() const
|
||||
inline const TimePos & pos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
inline MidiTime pos( MidiTime basePos ) const
|
||||
inline TimePos pos( TimePos basePos ) const
|
||||
{
|
||||
const int bp = basePos;
|
||||
return m_pos - bp;
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
return classNodeName();
|
||||
}
|
||||
|
||||
static MidiTime quantized( const MidiTime & m, const int qGrid );
|
||||
static TimePos quantized( const TimePos & m, const int qGrid );
|
||||
|
||||
DetuningHelper * detuning() const
|
||||
{
|
||||
@@ -226,15 +226,15 @@ private:
|
||||
// for piano roll editing
|
||||
bool m_selected;
|
||||
int m_oldKey;
|
||||
MidiTime m_oldPos;
|
||||
MidiTime m_oldLength;
|
||||
TimePos m_oldPos;
|
||||
TimePos m_oldLength;
|
||||
bool m_isPlaying;
|
||||
|
||||
int m_key;
|
||||
volume_t m_volume;
|
||||
panning_t m_panning;
|
||||
MidiTime m_length;
|
||||
MidiTime m_pos;
|
||||
TimePos m_length;
|
||||
TimePos m_pos;
|
||||
DetuningHelper * m_detuning;
|
||||
};
|
||||
|
||||
|
||||
@@ -244,19 +244,19 @@ public:
|
||||
}
|
||||
|
||||
/*! Process note detuning automation */
|
||||
void processMidiTime( const MidiTime& time );
|
||||
void processTimePos( const TimePos& time );
|
||||
|
||||
/*! Updates total length (m_frames) depending on a new tempo */
|
||||
void resize( const bpm_t newTempo );
|
||||
|
||||
/*! Set song-global offset (relative to containing pattern) in order to properly perform the note detuning */
|
||||
void setSongGlobalParentOffset( const MidiTime& offset )
|
||||
void setSongGlobalParentOffset( const TimePos& offset )
|
||||
{
|
||||
m_songGlobalParentOffset = offset;
|
||||
}
|
||||
|
||||
/*! Returns song-global offset */
|
||||
const MidiTime& songGlobalParentOffset() const
|
||||
const TimePos& songGlobalParentOffset() const
|
||||
{
|
||||
return m_songGlobalParentOffset;
|
||||
}
|
||||
@@ -323,7 +323,7 @@ private:
|
||||
float m_unpitchedFrequency;
|
||||
|
||||
BaseDetuning* m_baseDetuning;
|
||||
MidiTime m_songGlobalParentOffset;
|
||||
TimePos m_songGlobalParentOffset;
|
||||
|
||||
int m_midiChannel;
|
||||
Origin m_origin;
|
||||
@@ -349,6 +349,7 @@ public:
|
||||
NotePlayHandle::Origin origin = NotePlayHandle::OriginPattern );
|
||||
static void release( NotePlayHandle * nph );
|
||||
static void extend( int i );
|
||||
static void free();
|
||||
|
||||
private:
|
||||
static NotePlayHandle ** s_available;
|
||||
|
||||
@@ -34,16 +34,10 @@
|
||||
|
||||
|
||||
#include "Note.h"
|
||||
#include "Track.h"
|
||||
#include "TrackContentObjectView.h"
|
||||
|
||||
|
||||
class QAction;
|
||||
class QProgressBar;
|
||||
class QPushButton;
|
||||
|
||||
class InstrumentTrack;
|
||||
class SampleBuffer;
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT Pattern : public TrackContentObject
|
||||
@@ -128,7 +122,7 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
MidiTime beatPatternLength() const;
|
||||
TimePos beatPatternLength() const;
|
||||
|
||||
void setType( PatternTypes _new_pattern_type );
|
||||
void checkType();
|
||||
|
||||
@@ -187,9 +187,9 @@ protected slots:
|
||||
void pasteNotes();
|
||||
bool deleteSelectedNotes();
|
||||
|
||||
void updatePosition(const MidiTime & t );
|
||||
void updatePositionAccompany(const MidiTime & t );
|
||||
void updatePositionStepRecording(const MidiTime & t );
|
||||
void updatePosition(const TimePos & t );
|
||||
void updatePositionAccompany(const TimePos & t );
|
||||
void updatePositionStepRecording(const TimePos & t );
|
||||
|
||||
void zoomingChanged();
|
||||
void zoomingYChanged();
|
||||
@@ -266,9 +266,9 @@ private:
|
||||
PianoRoll( const PianoRoll & );
|
||||
virtual ~PianoRoll();
|
||||
|
||||
void autoScroll(const MidiTime & t );
|
||||
void autoScroll(const TimePos & t );
|
||||
|
||||
MidiTime newNoteLen() const;
|
||||
TimePos newNoteLen() const;
|
||||
|
||||
void shiftPos(int amount);
|
||||
void shiftPos(NoteVector notes, int amount);
|
||||
@@ -331,7 +331,7 @@ private:
|
||||
QScrollBar * m_leftRightScroll;
|
||||
QScrollBar * m_topBottomScroll;
|
||||
|
||||
MidiTime m_currentPosition;
|
||||
TimePos m_currentPosition;
|
||||
bool m_recording;
|
||||
QList<Note> m_recordingNotes;
|
||||
|
||||
@@ -377,12 +377,12 @@ private:
|
||||
|
||||
// remember these values to use them
|
||||
// for the next note that is set
|
||||
MidiTime m_lenOfNewNotes;
|
||||
TimePos m_lenOfNewNotes;
|
||||
volume_t m_lastNoteVolume;
|
||||
panning_t m_lastNotePanning;
|
||||
|
||||
//When resizing several notes, we want to calculate a common minimum length
|
||||
MidiTime m_minResizeLen;
|
||||
TimePos m_minResizeLen;
|
||||
|
||||
int m_startKey; // first key when drawing
|
||||
int m_lastKey;
|
||||
@@ -447,7 +447,7 @@ private:
|
||||
QBrush m_blackKeyInactiveBackground;
|
||||
|
||||
signals:
|
||||
void positionChanged( const MidiTime & );
|
||||
void positionChanged( const TimePos & );
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
class QLineEdit;
|
||||
class QTreeWidget;
|
||||
class QTreeWidgetItem;
|
||||
|
||||
|
||||
class PluginBrowser : public SideBarWidget
|
||||
@@ -53,8 +52,6 @@ private:
|
||||
|
||||
QWidget * m_view;
|
||||
QTreeWidget * m_descTree;
|
||||
QTreeWidgetItem * m_lmmsRoot;
|
||||
QTreeWidgetItem * m_lv2Root;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -32,18 +32,29 @@
|
||||
//! LMMS Plugins should use this to indicate errors
|
||||
enum PluginIssueType
|
||||
{
|
||||
// port flow & type
|
||||
unknownPortFlow,
|
||||
unknownPortType,
|
||||
// channel count
|
||||
tooManyInputChannels,
|
||||
tooManyOutputChannels,
|
||||
tooManyMidiInputChannels,
|
||||
tooManyMidiOutputChannels,
|
||||
noOutputChannel,
|
||||
// port metadata
|
||||
portHasNoDef,
|
||||
portHasNoMin,
|
||||
portHasNoMax,
|
||||
minGreaterMax,
|
||||
defaultValueNotInRange,
|
||||
logScaleMinMissing,
|
||||
logScaleMaxMissing,
|
||||
logScaleMinMaxDifferentSigns,
|
||||
// features
|
||||
featureNotSupported, //!< plugin requires functionality LMMS can't offer
|
||||
// misc
|
||||
badPortType, //!< port type not supported
|
||||
blacklisted,
|
||||
noIssue
|
||||
};
|
||||
|
||||
@@ -60,6 +71,9 @@ public:
|
||||
: m_issueType(it), m_info(msg)
|
||||
{
|
||||
}
|
||||
PluginIssueType type() const { return m_issueType; }
|
||||
bool operator==(const PluginIssue& other) const;
|
||||
bool operator<(const PluginIssue& other) const;
|
||||
friend QDebug operator<<(QDebug stream, const PluginIssue& iss);
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "NotePlayHandle.h"
|
||||
|
||||
|
||||
class DataFile;
|
||||
class InstrumentTrack;
|
||||
class PreviewTrackContainer;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
handleState( bool _varying_pitch = false, int interpolation_mode = SRC_LINEAR );
|
||||
handleState(bool varyingPitch = false, int interpolationMode = SRC_LINEAR);
|
||||
virtual ~handleState();
|
||||
|
||||
const f_cnt_t frameIndex() const
|
||||
@@ -70,9 +70,9 @@ public:
|
||||
return m_frameIndex;
|
||||
}
|
||||
|
||||
void setFrameIndex( f_cnt_t _index )
|
||||
void setFrameIndex(f_cnt_t index)
|
||||
{
|
||||
m_frameIndex = _index;
|
||||
m_frameIndex = index;
|
||||
}
|
||||
|
||||
bool isBackwards() const
|
||||
@@ -80,9 +80,9 @@ public:
|
||||
return m_isBackwards;
|
||||
}
|
||||
|
||||
void setBackwards( bool _backwards )
|
||||
void setBackwards(bool backwards)
|
||||
{
|
||||
m_isBackwards = _backwards;
|
||||
m_isBackwards = backwards;
|
||||
}
|
||||
|
||||
int interpolationMode() const
|
||||
@@ -106,21 +106,35 @@ public:
|
||||
SampleBuffer();
|
||||
// constructor which either loads sample _audio_file or decodes
|
||||
// base64-data out of string
|
||||
SampleBuffer( const QString & _audio_file, bool _is_base64_data = false );
|
||||
SampleBuffer( const sampleFrame * _data, const f_cnt_t _frames );
|
||||
explicit SampleBuffer( const f_cnt_t _frames );
|
||||
SampleBuffer(const QString & audioFile, bool isBase64Data = false);
|
||||
SampleBuffer(const sampleFrame * data, const f_cnt_t frames);
|
||||
explicit SampleBuffer(const f_cnt_t frames);
|
||||
|
||||
virtual ~SampleBuffer();
|
||||
|
||||
bool play( sampleFrame * _ab, handleState * _state,
|
||||
const fpp_t _frames,
|
||||
const float _freq,
|
||||
const LoopMode _loopmode = LoopOff );
|
||||
bool play(
|
||||
sampleFrame * ab,
|
||||
handleState * state,
|
||||
const fpp_t frames,
|
||||
const float freq,
|
||||
const LoopMode loopMode = LoopOff
|
||||
);
|
||||
|
||||
void visualize( QPainter & _p, const QRect & _dr, const QRect & _clip, f_cnt_t _from_frame = 0, f_cnt_t _to_frame = 0 );
|
||||
inline void visualize( QPainter & _p, const QRect & _dr, f_cnt_t _from_frame = 0, f_cnt_t _to_frame = 0 )
|
||||
void visualize(
|
||||
QPainter & p,
|
||||
const QRect & dr,
|
||||
const QRect & clip,
|
||||
f_cnt_t fromFrame = 0,
|
||||
f_cnt_t toFrame = 0
|
||||
);
|
||||
inline void visualize(
|
||||
QPainter & p,
|
||||
const QRect & dr,
|
||||
f_cnt_t fromFrame = 0,
|
||||
f_cnt_t toFrame = 0
|
||||
)
|
||||
{
|
||||
visualize( _p, _dr, _dr, _from_frame, _to_frame );
|
||||
visualize(p, dr, dr, fromFrame, toFrame);
|
||||
}
|
||||
|
||||
inline const QString & audioFile() const
|
||||
@@ -148,22 +162,27 @@ public:
|
||||
return m_loopEndFrame;
|
||||
}
|
||||
|
||||
void setLoopStartFrame( f_cnt_t _start )
|
||||
void setLoopStartFrame(f_cnt_t start)
|
||||
{
|
||||
m_loopStartFrame = _start;
|
||||
m_loopStartFrame = start;
|
||||
}
|
||||
|
||||
void setLoopEndFrame( f_cnt_t _end )
|
||||
void setLoopEndFrame(f_cnt_t end)
|
||||
{
|
||||
m_loopEndFrame = _end;
|
||||
m_loopEndFrame = end;
|
||||
}
|
||||
|
||||
void setAllPointFrames( f_cnt_t _start, f_cnt_t _end, f_cnt_t _loopstart, f_cnt_t _loopend )
|
||||
void setAllPointFrames(
|
||||
f_cnt_t start,
|
||||
f_cnt_t end,
|
||||
f_cnt_t loopStart,
|
||||
f_cnt_t loopEnd
|
||||
)
|
||||
{
|
||||
m_startFrame = _start;
|
||||
m_endFrame = _end;
|
||||
m_loopStartFrame = _loopstart;
|
||||
m_loopEndFrame = _loopend;
|
||||
m_startFrame = start;
|
||||
m_endFrame = end;
|
||||
m_loopStartFrame = loopStart;
|
||||
m_loopEndFrame = loopEnd;
|
||||
}
|
||||
|
||||
inline f_cnt_t frames() const
|
||||
@@ -193,17 +212,17 @@ public:
|
||||
|
||||
int sampleLength() const
|
||||
{
|
||||
return double( m_endFrame - m_startFrame ) / m_sampleRate * 1000;
|
||||
return double(m_endFrame - m_startFrame) / m_sampleRate * 1000;
|
||||
}
|
||||
|
||||
inline void setFrequency( float _freq )
|
||||
inline void setFrequency(float freq)
|
||||
{
|
||||
m_frequency = _freq;
|
||||
m_frequency = freq;
|
||||
}
|
||||
|
||||
inline void setSampleRate( sample_rate_t _rate )
|
||||
inline void setSampleRate(sample_rate_t rate)
|
||||
{
|
||||
m_sampleRate = _rate;
|
||||
m_sampleRate = rate;
|
||||
}
|
||||
|
||||
inline const sampleFrame * data() const
|
||||
@@ -215,30 +234,28 @@ public:
|
||||
QString openAndSetAudioFile();
|
||||
QString openAndSetWaveformFile();
|
||||
|
||||
QString & toBase64( QString & _dst ) const;
|
||||
QString & toBase64(QString & dst) const;
|
||||
|
||||
|
||||
// protect calls from the GUI to this function with dataReadLock() and
|
||||
// dataUnlock()
|
||||
SampleBuffer * resample( const sample_rate_t _src_sr,
|
||||
const sample_rate_t _dst_sr );
|
||||
SampleBuffer * resample(const sample_rate_t srcSR, const sample_rate_t dstSR);
|
||||
|
||||
void normalizeSampleRate( const sample_rate_t _src_sr,
|
||||
bool _keep_settings = false );
|
||||
void normalizeSampleRate(const sample_rate_t srcSR, bool keepSettings = false);
|
||||
|
||||
// protect calls from the GUI to this function with dataReadLock() and
|
||||
// dataUnlock(), out of loops for efficiency
|
||||
inline sample_t userWaveSample( const float _sample ) const
|
||||
inline sample_t userWaveSample(const float sample) const
|
||||
{
|
||||
f_cnt_t frames = m_frames;
|
||||
sampleFrame * data = m_data;
|
||||
const float frame = _sample * frames;
|
||||
f_cnt_t f1 = static_cast<f_cnt_t>( frame ) % frames;
|
||||
if( f1 < 0 )
|
||||
const float frame = sample * frames;
|
||||
f_cnt_t f1 = static_cast<f_cnt_t>(frame) % frames;
|
||||
if (f1 < 0)
|
||||
{
|
||||
f1 += frames;
|
||||
}
|
||||
return linearInterpolate( data[f1][0], data[ (f1 + 1) % frames ][0], fraction( frame ) );
|
||||
return linearInterpolate(data[f1][0], data[(f1 + 1) % frames][0], fraction(frame));
|
||||
}
|
||||
|
||||
void dataReadLock()
|
||||
@@ -253,33 +270,42 @@ public:
|
||||
|
||||
|
||||
public slots:
|
||||
void setAudioFile( const QString & _audio_file );
|
||||
void loadFromBase64( const QString & _data );
|
||||
void setStartFrame( const f_cnt_t _s );
|
||||
void setEndFrame( const f_cnt_t _e );
|
||||
void setAmplification( float _a );
|
||||
void setReversed( bool _on );
|
||||
void setAudioFile(const QString & audioFile);
|
||||
void loadFromBase64(const QString & data);
|
||||
void setStartFrame(const f_cnt_t s);
|
||||
void setEndFrame(const f_cnt_t e);
|
||||
void setAmplification(float a);
|
||||
void setReversed(bool on);
|
||||
void sampleRateChanged();
|
||||
|
||||
private:
|
||||
static sample_rate_t mixerSampleRate();
|
||||
|
||||
void update( bool _keep_settings = false );
|
||||
void update(bool keepSettings = false);
|
||||
|
||||
void convertIntToFloat ( int_sample_t * & _ibuf, f_cnt_t _frames, int _channels);
|
||||
void directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _channels);
|
||||
void convertIntToFloat(int_sample_t * & ibuf, f_cnt_t frames, int channels);
|
||||
void directFloatWrite(sample_t * & fbuf, f_cnt_t frames, int channels);
|
||||
|
||||
f_cnt_t decodeSampleSF( QString _f, sample_t * & _buf,
|
||||
ch_cnt_t & _channels,
|
||||
sample_rate_t & _sample_rate );
|
||||
f_cnt_t decodeSampleSF(
|
||||
QString fileName,
|
||||
sample_t * & buf,
|
||||
ch_cnt_t & channels,
|
||||
sample_rate_t & samplerate
|
||||
);
|
||||
#ifdef LMMS_HAVE_OGGVORBIS
|
||||
f_cnt_t decodeSampleOGGVorbis( QString _f, int_sample_t * & _buf,
|
||||
ch_cnt_t & _channels,
|
||||
sample_rate_t & _sample_rate );
|
||||
f_cnt_t decodeSampleOGGVorbis(
|
||||
QString fileName,
|
||||
int_sample_t * & buf,
|
||||
ch_cnt_t & channels,
|
||||
sample_rate_t & samplerate
|
||||
);
|
||||
#endif
|
||||
f_cnt_t decodeSampleDS( QString _f, int_sample_t * & _buf,
|
||||
ch_cnt_t & _channels,
|
||||
sample_rate_t & _sample_rate );
|
||||
f_cnt_t decodeSampleDS(
|
||||
QString fileName,
|
||||
int_sample_t * & buf,
|
||||
ch_cnt_t & channels,
|
||||
sample_rate_t & samplerate
|
||||
);
|
||||
|
||||
QString m_audioFile;
|
||||
sampleFrame * m_origData;
|
||||
@@ -296,13 +322,19 @@ private:
|
||||
float m_frequency;
|
||||
sample_rate_t m_sampleRate;
|
||||
|
||||
sampleFrame * getSampleFragment( f_cnt_t _index, f_cnt_t _frames,
|
||||
LoopMode _loopmode,
|
||||
sampleFrame * * _tmp,
|
||||
bool * _backwards, f_cnt_t _loopstart, f_cnt_t _loopend,
|
||||
f_cnt_t _end ) const;
|
||||
f_cnt_t getLoopedIndex( f_cnt_t _index, f_cnt_t _startf, f_cnt_t _endf ) const;
|
||||
f_cnt_t getPingPongIndex( f_cnt_t _index, f_cnt_t _startf, f_cnt_t _endf ) const;
|
||||
sampleFrame * getSampleFragment(
|
||||
f_cnt_t index,
|
||||
f_cnt_t frames,
|
||||
LoopMode loopMode,
|
||||
sampleFrame * * tmp,
|
||||
bool * backwards,
|
||||
f_cnt_t loopStart,
|
||||
f_cnt_t loopEnd,
|
||||
f_cnt_t end
|
||||
) const;
|
||||
|
||||
f_cnt_t getLoopedIndex(f_cnt_t index, f_cnt_t startf, f_cnt_t endf) const;
|
||||
f_cnt_t getPingPongIndex(f_cnt_t index, f_cnt_t startf, f_cnt_t endf) const;
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPair>
|
||||
|
||||
#include "MidiTime.h"
|
||||
#include "PlayHandle.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
class BBTrack;
|
||||
class SampleBuffer;
|
||||
@@ -60,7 +60,7 @@ private:
|
||||
typedef QList<QPair<sampleFrame *, f_cnt_t> > bufferList;
|
||||
bufferList m_buffers;
|
||||
f_cnt_t m_framesRecorded;
|
||||
MidiTime m_minLength;
|
||||
TimePos m_minLength;
|
||||
|
||||
Track * m_track;
|
||||
BBTrack * m_bbTrack;
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "FxMixer.h"
|
||||
#include "FxLineLcdSpinBox.h"
|
||||
#include "Track.h"
|
||||
#include "TrackContentObjectView.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
class EffectRackView;
|
||||
class Knob;
|
||||
@@ -50,7 +52,7 @@ public:
|
||||
SampleTCO( Track * _track );
|
||||
virtual ~SampleTCO();
|
||||
|
||||
void changeLength( const MidiTime & _length ) override;
|
||||
void changeLength( const TimePos & _length ) override;
|
||||
const QString & sampleFile() const;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
@@ -65,7 +67,7 @@ public:
|
||||
return m_sampleBuffer;
|
||||
}
|
||||
|
||||
MidiTime sampleLength() const;
|
||||
TimePos sampleLength() const;
|
||||
void setSampleStartFrame( f_cnt_t startFrame );
|
||||
void setSamplePlayLength( f_cnt_t length );
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
@@ -94,6 +96,7 @@ private:
|
||||
|
||||
signals:
|
||||
void sampleChanged();
|
||||
void wasReversed();
|
||||
|
||||
} ;
|
||||
|
||||
@@ -109,6 +112,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void updateSample();
|
||||
void reverseSample();
|
||||
|
||||
|
||||
|
||||
@@ -137,10 +141,10 @@ public:
|
||||
SampleTrack( TrackContainer* tc );
|
||||
virtual ~SampleTrack();
|
||||
|
||||
virtual bool play( const MidiTime & _start, const fpp_t _frames,
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
TrackView * createView( TrackContainerView* tcv ) override;
|
||||
TrackContentObject* createTCO(const MidiTime & pos) override;
|
||||
TrackContentObject* createTCO(const TimePos & pos) override;
|
||||
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
@@ -251,7 +255,7 @@ private:
|
||||
|
||||
TrackLabelButton * m_tlb;
|
||||
|
||||
FadeButton * getActivityIndicator()
|
||||
FadeButton * getActivityIndicator() override
|
||||
{
|
||||
return m_activityIndicator;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ private slots:
|
||||
void toggleCompactTrackButtons(bool enabled);
|
||||
void toggleOneInstrumentTrackWindow(bool enabled);
|
||||
void toggleSideBarOnRight(bool enabled);
|
||||
void toggleLetPreviewsFinish(bool enabled);
|
||||
void toggleSoloLegacyBehavior(bool enabled);
|
||||
void toggleMMPZ(bool enabled);
|
||||
void toggleDisableBackup(bool enabled);
|
||||
@@ -133,6 +134,7 @@ private:
|
||||
bool m_compactTrackButtons;
|
||||
bool m_oneInstrumentTrackWindow;
|
||||
bool m_sideBarOnRight;
|
||||
bool m_letPreviewsFinish;
|
||||
bool m_soloLegacyBehavior;
|
||||
bool m_MMPZ;
|
||||
bool m_disableBackup;
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
#include <QtCore/QSharedMemory>
|
||||
#include <QtCore/QVector>
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
#include "TrackContainer.h"
|
||||
#include "Controller.h"
|
||||
@@ -81,11 +83,11 @@ public:
|
||||
bool hasErrors();
|
||||
QString errorSummary();
|
||||
|
||||
class PlayPos : public MidiTime
|
||||
class PlayPos : public TimePos
|
||||
{
|
||||
public:
|
||||
PlayPos( const int abs = 0 ) :
|
||||
MidiTime( abs ),
|
||||
TimePos( abs ),
|
||||
m_timeLine( NULL ),
|
||||
m_currentFrame( 0.0f )
|
||||
{
|
||||
@@ -131,27 +133,27 @@ public:
|
||||
return m_elapsedMilliSeconds[playMode];
|
||||
}
|
||||
|
||||
inline void setToTime(MidiTime const & midiTime)
|
||||
inline void setToTime(TimePos const & pos)
|
||||
{
|
||||
m_elapsedMilliSeconds[m_playMode] = midiTime.getTimeInMilliseconds(getTempo());
|
||||
m_playPos[m_playMode].setTicks(midiTime.getTicks());
|
||||
m_elapsedMilliSeconds[m_playMode] = pos.getTimeInMilliseconds(getTempo());
|
||||
m_playPos[m_playMode].setTicks(pos.getTicks());
|
||||
}
|
||||
|
||||
inline void setToTime(MidiTime const & midiTime, PlayModes playMode)
|
||||
inline void setToTime(TimePos const & pos, PlayModes playMode)
|
||||
{
|
||||
m_elapsedMilliSeconds[playMode] = midiTime.getTimeInMilliseconds(getTempo());
|
||||
m_playPos[playMode].setTicks(midiTime.getTicks());
|
||||
m_elapsedMilliSeconds[playMode] = pos.getTimeInMilliseconds(getTempo());
|
||||
m_playPos[playMode].setTicks(pos.getTicks());
|
||||
}
|
||||
|
||||
inline void setToTimeByTicks(tick_t ticks)
|
||||
{
|
||||
m_elapsedMilliSeconds[m_playMode] = MidiTime::ticksToMilliseconds(ticks, getTempo());
|
||||
m_elapsedMilliSeconds[m_playMode] = TimePos::ticksToMilliseconds(ticks, getTempo());
|
||||
m_playPos[m_playMode].setTicks(ticks);
|
||||
}
|
||||
|
||||
inline void setToTimeByTicks(tick_t ticks, PlayModes playMode)
|
||||
{
|
||||
m_elapsedMilliSeconds[playMode] = MidiTime::ticksToMilliseconds(ticks, getTempo());
|
||||
m_elapsedMilliSeconds[playMode] = TimePos::ticksToMilliseconds(ticks, getTempo());
|
||||
m_playPos[playMode].setTicks(ticks);
|
||||
}
|
||||
|
||||
@@ -162,7 +164,7 @@ public:
|
||||
|
||||
inline int ticksPerBar() const
|
||||
{
|
||||
return MidiTime::ticksPerBar(m_timeSigModel);
|
||||
return TimePos::ticksPerBar(m_timeSigModel);
|
||||
}
|
||||
|
||||
// Returns the beat position inside the bar, 0-based
|
||||
@@ -248,6 +250,10 @@ public:
|
||||
{
|
||||
return m_playPos[pm];
|
||||
}
|
||||
inline PlayPos & getPlayPos()
|
||||
{
|
||||
return getPlayPos(m_playMode);
|
||||
}
|
||||
inline const PlayPos & getPlayPos() const
|
||||
{
|
||||
return getPlayPos(m_playMode);
|
||||
@@ -269,7 +275,7 @@ public:
|
||||
}
|
||||
|
||||
//TODO: Add Q_DECL_OVERRIDE when Qt4 is dropped
|
||||
AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const override;
|
||||
AutomatedValueMap automatedValuesAt(TimePos time, int tcoNum = -1) const override;
|
||||
|
||||
// file management
|
||||
void createNewProject();
|
||||
@@ -405,7 +411,7 @@ private:
|
||||
|
||||
void removeAllControllers();
|
||||
|
||||
void processAutomations(const TrackList& tracks, MidiTime timeStart, fpp_t frames);
|
||||
void processAutomations(const TrackList& tracks, TimePos timeStart, fpp_t frames);
|
||||
|
||||
void setModified(bool value);
|
||||
|
||||
@@ -458,11 +464,11 @@ private:
|
||||
|
||||
int m_loopRenderCount;
|
||||
int m_loopRenderRemaining;
|
||||
MidiTime m_exportSongBegin;
|
||||
MidiTime m_exportLoopBegin;
|
||||
MidiTime m_exportLoopEnd;
|
||||
MidiTime m_exportSongEnd;
|
||||
MidiTime m_exportEffectiveLength;
|
||||
TimePos m_exportSongBegin;
|
||||
TimePos m_exportLoopBegin;
|
||||
TimePos m_exportLoopEnd;
|
||||
TimePos m_exportSongEnd;
|
||||
TimePos m_exportEffectiveLength;
|
||||
|
||||
friend class LmmsCore;
|
||||
friend class SongEditor;
|
||||
|
||||
@@ -80,7 +80,7 @@ public slots:
|
||||
void setEditModeSelect();
|
||||
void toggleProportionalSnap();
|
||||
|
||||
void updatePosition( const MidiTime & t );
|
||||
void updatePosition( const TimePos & t );
|
||||
void updatePositionLine();
|
||||
void selectAllTcos( bool select );
|
||||
|
||||
@@ -150,7 +150,7 @@ private:
|
||||
QPoint m_scrollPos;
|
||||
QPoint m_mousePos;
|
||||
int m_rubberBandStartTrackview;
|
||||
MidiTime m_rubberbandStartMidipos;
|
||||
TimePos m_rubberbandStartTimePos;
|
||||
int m_currentZoomingValue;
|
||||
int m_trackHeadWidth;
|
||||
bool m_selectRegion;
|
||||
|
||||
@@ -41,14 +41,14 @@ class StepRecorder : public QObject
|
||||
StepRecorder(PianoRoll& pianoRoll, StepRecorderWidget& stepRecorderWidget);
|
||||
|
||||
void initialize();
|
||||
void start(const MidiTime& currentPosition,const MidiTime& stepLength);
|
||||
void start(const TimePos& currentPosition,const TimePos& 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);
|
||||
void setStepsLength(const TimePos& newLength);
|
||||
|
||||
QVector<Note*> getCurStepNotes();
|
||||
|
||||
@@ -73,7 +73,7 @@ class StepRecorder : public QObject
|
||||
void dismissStep();
|
||||
void prepareNewStep();
|
||||
|
||||
MidiTime getCurStepEndPos();
|
||||
TimePos getCurStepEndPos();
|
||||
|
||||
void updateCurStepNotes();
|
||||
void updateWidget();
|
||||
@@ -84,11 +84,11 @@ class StepRecorder : public QObject
|
||||
StepRecorderWidget& m_stepRecorderWidget;
|
||||
|
||||
bool m_isRecording = false;
|
||||
MidiTime m_curStepStartPos = 0;
|
||||
MidiTime m_curStepEndPos = 0;
|
||||
TimePos m_curStepStartPos = 0;
|
||||
TimePos m_curStepEndPos = 0;
|
||||
|
||||
MidiTime m_stepsLength;
|
||||
MidiTime m_curStepLength; // current step length refers to the step currently recorded. it may defer from m_stepsLength
|
||||
TimePos m_stepsLength;
|
||||
TimePos 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;
|
||||
|
||||
@@ -44,15 +44,15 @@ public:
|
||||
|
||||
//API used by PianoRoll
|
||||
void setPixelsPerBar(int ppb);
|
||||
void setCurrentPosition(MidiTime currentPosition);
|
||||
void setCurrentPosition(TimePos currentPosition);
|
||||
void setMargins(const QMargins &qm);
|
||||
void setBottomMargin(const int marginBottom);
|
||||
QMargins margins();
|
||||
|
||||
//API used by StepRecorder
|
||||
void setStepsLength(MidiTime stepsLength);
|
||||
void setStartPosition(MidiTime pos);
|
||||
void setEndPosition(MidiTime pos);
|
||||
void setStepsLength(TimePos stepsLength);
|
||||
void setStartPosition(TimePos pos);
|
||||
void setEndPosition(TimePos pos);
|
||||
|
||||
void showHint();
|
||||
|
||||
@@ -62,16 +62,16 @@ private:
|
||||
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 drawVerLine(QPainter* painter, const TimePos& pos, const QColor& color, int top, int bottom);
|
||||
|
||||
void updateBoundaries();
|
||||
|
||||
MidiTime m_stepsLength;
|
||||
MidiTime m_curStepStartPos;
|
||||
MidiTime m_curStepEndPos;
|
||||
TimePos m_stepsLength;
|
||||
TimePos m_curStepStartPos;
|
||||
TimePos m_curStepEndPos;
|
||||
|
||||
int m_ppb; // pixels per bar
|
||||
MidiTime m_currentPosition; // current position showed by on PianoRoll
|
||||
TimePos m_currentPosition; // current position showed by on PianoRoll
|
||||
|
||||
QColor m_colorLineStart;
|
||||
QColor m_colorLineEnd;
|
||||
@@ -88,7 +88,7 @@ private:
|
||||
const int m_marginRight;
|
||||
|
||||
signals:
|
||||
void positionChanged(const MidiTime & t);
|
||||
void positionChanged(const TimePos & t);
|
||||
} ;
|
||||
|
||||
#endif //STEP_RECOREDER_WIDGET_H
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
|
||||
|
||||
TimeLineWidget(int xoff, int yoff, float ppb, Song::PlayPos & pos,
|
||||
const MidiTime & begin, Song::PlayModes mode, QWidget * parent);
|
||||
const TimePos & begin, Song::PlayModes mode, QWidget * parent);
|
||||
virtual ~TimeLineWidget();
|
||||
|
||||
inline QColor const & getBarLineColor() const { return m_barLineColor; }
|
||||
@@ -123,23 +123,23 @@ public:
|
||||
return m_loopPoints == LoopPointsEnabled;
|
||||
}
|
||||
|
||||
inline const MidiTime & loopBegin() const
|
||||
inline const TimePos & loopBegin() const
|
||||
{
|
||||
return ( m_loopPos[0] < m_loopPos[1] ) ?
|
||||
m_loopPos[0] : m_loopPos[1];
|
||||
}
|
||||
|
||||
inline const MidiTime & loopEnd() const
|
||||
inline const TimePos & loopEnd() const
|
||||
{
|
||||
return ( m_loopPos[0] > m_loopPos[1] ) ?
|
||||
m_loopPos[0] : m_loopPos[1];
|
||||
}
|
||||
|
||||
inline void savePos( const MidiTime & pos )
|
||||
inline void savePos( const TimePos & pos )
|
||||
{
|
||||
m_savedPos = pos;
|
||||
}
|
||||
inline const MidiTime & savedPos() const
|
||||
inline const TimePos & savedPos() const
|
||||
{
|
||||
return m_savedPos;
|
||||
}
|
||||
@@ -162,10 +162,10 @@ public:
|
||||
return "timeline";
|
||||
}
|
||||
|
||||
inline int markerX( const MidiTime & _t ) const
|
||||
inline int markerX( const TimePos & _t ) const
|
||||
{
|
||||
return m_xOffset + static_cast<int>( ( _t - m_begin ) *
|
||||
m_ppb / MidiTime::ticksPerBar() );
|
||||
m_ppb / TimePos::ticksPerBar() );
|
||||
}
|
||||
|
||||
signals:
|
||||
@@ -175,10 +175,10 @@ signals:
|
||||
|
||||
|
||||
public slots:
|
||||
void updatePosition( const MidiTime & );
|
||||
void updatePosition( const TimePos & );
|
||||
void updatePosition()
|
||||
{
|
||||
updatePosition( MidiTime() );
|
||||
updatePosition( TimePos() );
|
||||
}
|
||||
void toggleAutoScroll( int _n );
|
||||
void toggleLoopPoints( int _n );
|
||||
@@ -218,11 +218,11 @@ private:
|
||||
int m_posMarkerX;
|
||||
float m_ppb;
|
||||
Song::PlayPos & m_pos;
|
||||
const MidiTime & m_begin;
|
||||
const TimePos & m_begin;
|
||||
const Song::PlayModes m_mode;
|
||||
MidiTime m_loopPos[2];
|
||||
TimePos m_loopPos[2];
|
||||
|
||||
MidiTime m_savedPos;
|
||||
TimePos m_savedPos;
|
||||
|
||||
|
||||
TextFloat * m_hint;
|
||||
@@ -242,7 +242,7 @@ private:
|
||||
|
||||
|
||||
signals:
|
||||
void positionChanged( const MidiTime & _t );
|
||||
void positionChanged( const TimePos & _t );
|
||||
void loopPointStateLoaded( int _n );
|
||||
void positionMarkerMoved();
|
||||
void loadBehaviourAtStop( int _n );
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* MidiTime.h - declaration of class MidiTime which provides data type for
|
||||
* position- and length-variables
|
||||
* TimePos.h - declaration of class TimePos which provides data type for
|
||||
* position- and length-variables
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net
|
||||
*
|
||||
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MIDI_TIME_H
|
||||
#define MIDI_TIME_H
|
||||
#ifndef TIME_POS_H
|
||||
#define TIME_POS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
@@ -40,13 +40,15 @@ const int DefaultBeatsPerBar = DefaultTicksPerBar / DefaultStepsPerBar;
|
||||
|
||||
class MeterModel;
|
||||
|
||||
/**
|
||||
Represents a time signature, in which the numerator is the number of beats
|
||||
in a bar, while the denominator is the type of note representing a beat.
|
||||
|
||||
Example: 6/8 means 6 beats in a bar with each beat having a duration of one 8th-note.
|
||||
*/
|
||||
class LMMS_EXPORT TimeSig
|
||||
{
|
||||
public:
|
||||
// in a time signature,
|
||||
// the numerator represents the number of beats in a measure.
|
||||
// the denominator indicates which type of note represents a beat.
|
||||
// example: 6/8 means 6 beats in a measure, where each beat has duration equal to one 8th-note.
|
||||
TimeSig( int num, int denom );
|
||||
TimeSig( const MeterModel &model );
|
||||
int numerator() const;
|
||||
@@ -57,17 +59,20 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class LMMS_EXPORT MidiTime
|
||||
/**
|
||||
Represents a position in time or length of a note or event, in ticks, beats, and bars
|
||||
*/
|
||||
class LMMS_EXPORT TimePos
|
||||
{
|
||||
public:
|
||||
MidiTime( const bar_t bar, const tick_t ticks );
|
||||
MidiTime( const tick_t ticks = 0 );
|
||||
TimePos( const bar_t bar, const tick_t ticks );
|
||||
TimePos( const tick_t ticks = 0 );
|
||||
|
||||
MidiTime quantize(float) const;
|
||||
MidiTime toAbsoluteBar() const;
|
||||
TimePos quantize(float) const;
|
||||
TimePos toAbsoluteBar() const;
|
||||
|
||||
MidiTime& operator+=( const MidiTime& time );
|
||||
MidiTime& operator-=( const MidiTime& time );
|
||||
TimePos& operator+=( const TimePos& time );
|
||||
TimePos& operator-=( const TimePos& time );
|
||||
|
||||
// return the bar, rounded down and 0-based
|
||||
bar_t getBar() const;
|
||||
@@ -92,12 +97,12 @@ public:
|
||||
|
||||
double getTimeInMilliseconds( bpm_t beatsPerMinute ) const;
|
||||
|
||||
static MidiTime fromFrames( const f_cnt_t frames, const float framesPerTick );
|
||||
static TimePos fromFrames( const f_cnt_t frames, const float framesPerTick );
|
||||
static tick_t ticksPerBar();
|
||||
static tick_t ticksPerBar( const TimeSig &sig );
|
||||
static int stepsPerBar();
|
||||
static void setTicksPerBar( tick_t tpt );
|
||||
static MidiTime stepPosition( int step );
|
||||
static TimePos stepPosition( int step );
|
||||
static double ticksToMilliseconds( tick_t ticks, bpm_t beatsPerMinute );
|
||||
static double ticksToMilliseconds( double ticks, bpm_t beatsPerMinute );
|
||||
|
||||
639
include/Track.h
639
include/Track.h
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Track.h - declaration of classes concerning tracks -> necessary for all
|
||||
* track-like objects (beat/bassline, sample-track...)
|
||||
* Track.h - declaration of Track class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -26,43 +25,22 @@
|
||||
#ifndef TRACK_H
|
||||
#define TRACK_H
|
||||
|
||||
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QList>
|
||||
#include <QWidget>
|
||||
#include <QSize>
|
||||
#include <QColor>
|
||||
#include <QMimeData>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "MidiTime.h"
|
||||
#include "Rubberband.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "AutomatableModel.h"
|
||||
#include "ModelView.h"
|
||||
#include "DataFile.h"
|
||||
#include "FadeButton.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
class QMenu;
|
||||
class QPushButton;
|
||||
|
||||
class PixmapButton;
|
||||
class TextFloat;
|
||||
class Track;
|
||||
class TrackContentObjectView;
|
||||
class TimePos;
|
||||
class TrackContainer;
|
||||
class TrackContainerView;
|
||||
class TrackContentWidget;
|
||||
class TrackContentObject;
|
||||
class TrackView;
|
||||
|
||||
|
||||
const int DEFAULT_SETTINGS_WIDGET_WIDTH = 224;
|
||||
const int TRACK_OP_WIDTH = 78;
|
||||
// This shaves 150-ish pixels off track buttons,
|
||||
// ruled from config: ui.compacttrackbuttons
|
||||
const int DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT = 96;
|
||||
const int TRACK_OP_WIDTH_COMPACT = 62;
|
||||
|
||||
/*! The minimum track height in pixels
|
||||
*
|
||||
* Tracks can be resized by shift-dragging anywhere inside the track
|
||||
@@ -71,483 +49,10 @@ const int TRACK_OP_WIDTH_COMPACT = 62;
|
||||
const int MINIMAL_TRACK_HEIGHT = 32;
|
||||
const int DEFAULT_TRACK_HEIGHT = 32;
|
||||
|
||||
const int TCO_BORDER_WIDTH = 2;
|
||||
|
||||
char const *const FILENAME_FILTER = "[\\0000-\x1f\"*/:<>?\\\\|\x7f]";
|
||||
|
||||
|
||||
class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
|
||||
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
|
||||
public:
|
||||
TrackContentObject( Track * track );
|
||||
virtual ~TrackContentObject();
|
||||
|
||||
inline Track * getTrack() const
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline const QString & name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
inline void setName( const QString & name )
|
||||
{
|
||||
m_name = name;
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return name();
|
||||
}
|
||||
|
||||
|
||||
inline const MidiTime & startPosition() const
|
||||
{
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
inline MidiTime endPosition() const
|
||||
{
|
||||
const int sp = m_startPosition;
|
||||
return sp + m_length;
|
||||
}
|
||||
|
||||
inline const MidiTime & length() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline void setAutoResize( const bool r )
|
||||
{
|
||||
m_autoResize = r;
|
||||
}
|
||||
|
||||
inline const bool getAutoResize() const
|
||||
{
|
||||
return m_autoResize;
|
||||
}
|
||||
|
||||
QColor color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void setColor( const QColor & c )
|
||||
{
|
||||
m_color = c;
|
||||
}
|
||||
|
||||
bool hasColor();
|
||||
|
||||
void useCustomClipColor( bool b );
|
||||
|
||||
bool usesCustomClipColor()
|
||||
{
|
||||
return m_useCustomClipColor;
|
||||
}
|
||||
|
||||
virtual void movePosition( const MidiTime & pos );
|
||||
virtual void changeLength( const MidiTime & length );
|
||||
|
||||
virtual TrackContentObjectView * createView( TrackView * tv ) = 0;
|
||||
|
||||
inline void selectViewOnCreate( bool select )
|
||||
{
|
||||
m_selectViewOnCreate = select;
|
||||
}
|
||||
|
||||
inline bool getSelectViewOnCreate()
|
||||
{
|
||||
return m_selectViewOnCreate;
|
||||
}
|
||||
|
||||
/// Returns true if and only if a->startPosition() < b->startPosition()
|
||||
static bool comparePosition(const TrackContentObject* a, const TrackContentObject* b);
|
||||
|
||||
MidiTime startTimeOffset() const;
|
||||
void setStartTimeOffset( const MidiTime &startTimeOffset );
|
||||
|
||||
void updateColor();
|
||||
|
||||
// Will copy the state of a TCO to another TCO
|
||||
static void copyStateTo( TrackContentObject *src, TrackContentObject *dst );
|
||||
|
||||
public slots:
|
||||
void toggleMute();
|
||||
|
||||
|
||||
signals:
|
||||
void lengthChanged();
|
||||
void positionChanged();
|
||||
void destroyedTCO();
|
||||
void trackColorChanged();
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
Move,
|
||||
Resize
|
||||
} ;
|
||||
|
||||
Track * m_track;
|
||||
QString m_name;
|
||||
|
||||
MidiTime m_startPosition;
|
||||
MidiTime m_length;
|
||||
MidiTime m_startTimeOffset;
|
||||
|
||||
BoolModel m_mutedModel;
|
||||
BoolModel m_soloModel;
|
||||
bool m_autoResize;
|
||||
|
||||
bool m_selectViewOnCreate;
|
||||
|
||||
QColor m_color;
|
||||
bool m_useCustomClipColor;
|
||||
|
||||
friend class TrackContentObjectView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class TrackContentObjectView : public selectableObject, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// theming qproperties
|
||||
Q_PROPERTY( QColor mutedColor READ mutedColor WRITE setMutedColor )
|
||||
Q_PROPERTY( QColor mutedBackgroundColor READ mutedBackgroundColor WRITE setMutedBackgroundColor )
|
||||
Q_PROPERTY( QColor selectedColor READ selectedColor WRITE setSelectedColor )
|
||||
Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor )
|
||||
Q_PROPERTY( QColor textBackgroundColor READ textBackgroundColor WRITE setTextBackgroundColor )
|
||||
Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor )
|
||||
Q_PROPERTY( QColor BBPatternBackground READ BBPatternBackground WRITE setBBPatternBackground )
|
||||
Q_PROPERTY( bool gradient READ gradient WRITE setGradient )
|
||||
// We have to use a QSize here because using QPoint isn't supported.
|
||||
// width -> x, height -> y
|
||||
Q_PROPERTY( QSize mouseHotspotHand WRITE setMouseHotspotHand )
|
||||
|
||||
public:
|
||||
TrackContentObjectView( TrackContentObject * tco, TrackView * tv );
|
||||
virtual ~TrackContentObjectView();
|
||||
|
||||
bool fixedTCOs();
|
||||
|
||||
inline TrackContentObject * getTrackContentObject()
|
||||
{
|
||||
return m_tco;
|
||||
}
|
||||
|
||||
inline TrackView * getTrackView()
|
||||
{
|
||||
return m_trackView;
|
||||
}
|
||||
|
||||
// qproperty access func
|
||||
QColor mutedColor() const;
|
||||
QColor mutedBackgroundColor() const;
|
||||
QColor selectedColor() const;
|
||||
QColor textColor() const;
|
||||
QColor textBackgroundColor() const;
|
||||
QColor textShadowColor() const;
|
||||
QColor BBPatternBackground() const;
|
||||
bool gradient() const;
|
||||
void setMutedColor( const QColor & c );
|
||||
void setMutedBackgroundColor( const QColor & c );
|
||||
void setSelectedColor( const QColor & c );
|
||||
void setTextColor( const QColor & c );
|
||||
void setTextBackgroundColor( const QColor & c );
|
||||
void setTextShadowColor( const QColor & c );
|
||||
void setBBPatternBackground( const QColor & c );
|
||||
void setGradient( const bool & b );
|
||||
void setMouseHotspotHand(const QSize & s);
|
||||
|
||||
// access needsUpdate member variable
|
||||
bool needsUpdate();
|
||||
void setNeedsUpdate( bool b );
|
||||
|
||||
// Method to get a QVector of TCOs to be affected by a context menu action
|
||||
QVector<TrackContentObjectView *> getClickedTCOs();
|
||||
|
||||
// Methods to remove, copy, cut, paste and mute a QVector of TCO views
|
||||
void copy( QVector<TrackContentObjectView *> tcovs );
|
||||
void cut( QVector<TrackContentObjectView *> tcovs );
|
||||
void paste();
|
||||
// remove and toggleMute are static because they don't depend
|
||||
// being called from a particular TCO view, but can be called anywhere as long
|
||||
// as a valid TCO view list is given, while copy/cut require an instance for
|
||||
// some metadata to be written to the clipboard.
|
||||
static void remove( QVector<TrackContentObjectView *> tcovs );
|
||||
static void toggleMute( QVector<TrackContentObjectView *> tcovs );
|
||||
|
||||
QColor getColorForDisplay( QColor );
|
||||
|
||||
public slots:
|
||||
virtual bool close();
|
||||
void remove();
|
||||
void update() override;
|
||||
|
||||
void changeClipColor();
|
||||
void useTrackColor();
|
||||
|
||||
protected:
|
||||
enum ContextMenuAction
|
||||
{
|
||||
Remove,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Mute
|
||||
};
|
||||
|
||||
virtual void constructContextMenu( QMenu * )
|
||||
{
|
||||
}
|
||||
|
||||
void contextMenuEvent( QContextMenuEvent * cme ) override;
|
||||
void contextMenuAction( ContextMenuAction action );
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void leaveEvent( QEvent * e ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * me ) override;
|
||||
void resizeEvent( QResizeEvent * re ) override
|
||||
{
|
||||
m_needsUpdate = true;
|
||||
selectableObject::resizeEvent( re );
|
||||
}
|
||||
|
||||
float pixelsPerBar();
|
||||
|
||||
|
||||
DataFile createTCODataFiles(const QVector<TrackContentObjectView *> & tcos) const;
|
||||
|
||||
virtual void paintTextLabel(QString const & text, QPainter & painter);
|
||||
|
||||
|
||||
protected slots:
|
||||
void updateLength();
|
||||
void updatePosition();
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
Move,
|
||||
MoveSelection,
|
||||
Resize,
|
||||
ResizeLeft,
|
||||
CopySelection,
|
||||
ToggleSelected
|
||||
} ;
|
||||
|
||||
static TextFloat * s_textFloat;
|
||||
|
||||
TrackContentObject * m_tco;
|
||||
TrackView * m_trackView;
|
||||
Actions m_action;
|
||||
QPoint m_initialMousePos;
|
||||
QPoint m_initialMouseGlobalPos;
|
||||
MidiTime m_initialTCOPos;
|
||||
MidiTime m_initialTCOEnd;
|
||||
QVector<MidiTime> m_initialOffsets;
|
||||
|
||||
TextFloat * m_hint;
|
||||
|
||||
// qproperty fields
|
||||
QColor m_mutedColor;
|
||||
QColor m_mutedBackgroundColor;
|
||||
QColor m_selectedColor;
|
||||
QColor m_textColor;
|
||||
QColor m_textBackgroundColor;
|
||||
QColor m_textShadowColor;
|
||||
QColor m_BBPatternBackground;
|
||||
bool m_gradient;
|
||||
QSize m_mouseHotspotHand; // QSize must be used because QPoint isn't supported by property system
|
||||
bool m_cursorSetYet;
|
||||
|
||||
bool m_needsUpdate;
|
||||
inline void setInitialPos( QPoint pos )
|
||||
{
|
||||
m_initialMousePos = pos;
|
||||
m_initialMouseGlobalPos = mapToGlobal( pos );
|
||||
m_initialTCOPos = m_tco->startPosition();
|
||||
m_initialTCOEnd = m_initialTCOPos + m_tco->length();
|
||||
}
|
||||
void setInitialOffsets();
|
||||
|
||||
bool mouseMovedDistance( QMouseEvent * me, int distance );
|
||||
MidiTime draggedTCOPos( QMouseEvent * me );
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TrackContentWidget : public QWidget, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// qproperties for track background gradients
|
||||
Q_PROPERTY( QBrush darkerColor READ darkerColor WRITE setDarkerColor )
|
||||
Q_PROPERTY( QBrush lighterColor READ lighterColor WRITE setLighterColor )
|
||||
Q_PROPERTY( QBrush gridColor READ gridColor WRITE setGridColor )
|
||||
Q_PROPERTY( QBrush embossColor READ embossColor WRITE setEmbossColor )
|
||||
|
||||
public:
|
||||
TrackContentWidget( TrackView * parent );
|
||||
virtual ~TrackContentWidget();
|
||||
|
||||
/*! \brief Updates the background tile pixmap. */
|
||||
void updateBackground();
|
||||
|
||||
void addTCOView( TrackContentObjectView * tcov );
|
||||
void removeTCOView( TrackContentObjectView * tcov );
|
||||
void removeTCOView( int tcoNum )
|
||||
{
|
||||
if( tcoNum >= 0 && tcoNum < m_tcoViews.size() )
|
||||
{
|
||||
removeTCOView( m_tcoViews[tcoNum] );
|
||||
}
|
||||
}
|
||||
|
||||
bool canPasteSelection( MidiTime tcoPos, const QDropEvent *de );
|
||||
bool canPasteSelection( MidiTime tcoPos, const QMimeData *md, bool allowSameBar = false );
|
||||
bool pasteSelection( MidiTime tcoPos, QDropEvent * de );
|
||||
bool pasteSelection( MidiTime tcoPos, const QMimeData * md, bool skipSafetyCheck = false );
|
||||
|
||||
MidiTime endPosition( const MidiTime & posStart );
|
||||
|
||||
// qproperty access methods
|
||||
|
||||
QBrush darkerColor() const;
|
||||
QBrush lighterColor() const;
|
||||
QBrush gridColor() const;
|
||||
QBrush embossColor() const;
|
||||
|
||||
void setDarkerColor( const QBrush & c );
|
||||
void setLighterColor( const QBrush & c );
|
||||
void setGridColor( const QBrush & c );
|
||||
void setEmbossColor( const QBrush & c);
|
||||
|
||||
public slots:
|
||||
void update();
|
||||
void changePosition( const MidiTime & newPos = MidiTime( -1 ) );
|
||||
|
||||
protected:
|
||||
enum ContextMenuAction
|
||||
{
|
||||
Paste
|
||||
};
|
||||
|
||||
void contextMenuEvent( QContextMenuEvent * cme ) override;
|
||||
void contextMenuAction( QContextMenuEvent * cme, ContextMenuAction action );
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void resizeEvent( QResizeEvent * re ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "trackcontentwidget";
|
||||
}
|
||||
|
||||
void saveSettings( QDomDocument& doc, QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(doc)
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
void loadSettings( const QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Track * getTrack();
|
||||
MidiTime getPosition( int mouseX );
|
||||
|
||||
TrackView * m_trackView;
|
||||
|
||||
typedef QVector<TrackContentObjectView *> tcoViewVector;
|
||||
tcoViewVector m_tcoViews;
|
||||
|
||||
QPixmap m_background;
|
||||
|
||||
// qproperty fields
|
||||
QBrush m_darkerColor;
|
||||
QBrush m_lighterColor;
|
||||
QBrush m_gridColor;
|
||||
QBrush m_embossColor;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TrackOperationsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackOperationsWidget( TrackView * parent );
|
||||
~TrackOperationsWidget();
|
||||
|
||||
|
||||
protected:
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
|
||||
|
||||
private slots:
|
||||
void cloneTrack();
|
||||
void removeTrack();
|
||||
void updateMenu();
|
||||
void changeTrackColor();
|
||||
void randomTrackColor();
|
||||
void resetTrackColor();
|
||||
void useTrackColor();
|
||||
void toggleRecording(bool on);
|
||||
void recordingOn();
|
||||
void recordingOff();
|
||||
void clearTrack();
|
||||
|
||||
private:
|
||||
TrackView * m_trackView;
|
||||
|
||||
QPushButton * m_trackOps;
|
||||
PixmapButton * m_muteBtn;
|
||||
PixmapButton * m_soloBtn;
|
||||
|
||||
|
||||
friend class TrackView;
|
||||
|
||||
signals:
|
||||
void trackRemovalScheduled( TrackView * t );
|
||||
void colorChanged( QColor & c );
|
||||
void colorParented();
|
||||
void colorReset();
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// base-class for all tracks
|
||||
//! Base-class for all tracks
|
||||
class LMMS_EXPORT Track : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -584,12 +89,12 @@ public:
|
||||
return m_type;
|
||||
}
|
||||
|
||||
virtual bool play( const MidiTime & start, const fpp_t frames,
|
||||
virtual bool play( const TimePos & start, const fpp_t frames,
|
||||
const f_cnt_t frameBase, int tcoNum = -1 ) = 0;
|
||||
|
||||
|
||||
virtual TrackView * createView( TrackContainerView * view ) = 0;
|
||||
virtual TrackContentObject * createTCO( const MidiTime & pos ) = 0;
|
||||
virtual TrackContentObject * createTCO( const TimePos & pos ) = 0;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & doc,
|
||||
QDomElement & parent ) = 0;
|
||||
@@ -618,15 +123,15 @@ public:
|
||||
{
|
||||
return m_trackContentObjects;
|
||||
}
|
||||
void getTCOsInRange( tcoVector & tcoV, const MidiTime & start,
|
||||
const MidiTime & end );
|
||||
void getTCOsInRange( tcoVector & tcoV, const TimePos & start,
|
||||
const TimePos & end );
|
||||
void swapPositionOfTCOs( int tcoNum1, int tcoNum2 );
|
||||
|
||||
void createTCOsForBB( int bb );
|
||||
|
||||
|
||||
void insertBar( const MidiTime & pos );
|
||||
void removeBar( const MidiTime & pos );
|
||||
void insertBar( const TimePos & pos );
|
||||
void removeBar( const TimePos & pos );
|
||||
|
||||
bar_t length() const;
|
||||
|
||||
@@ -729,122 +234,4 @@ signals:
|
||||
|
||||
|
||||
|
||||
|
||||
class TrackView : public QWidget, public ModelView, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackView( Track * _track, TrackContainerView* tcv );
|
||||
virtual ~TrackView();
|
||||
|
||||
inline const Track * getTrack() const
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline Track * getTrack()
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline TrackContainerView* trackContainerView()
|
||||
{
|
||||
return m_trackContainerView;
|
||||
}
|
||||
|
||||
inline TrackOperationsWidget * getTrackOperationsWidget()
|
||||
{
|
||||
return &m_trackOperationsWidget;
|
||||
}
|
||||
|
||||
inline QWidget * getTrackSettingsWidget()
|
||||
{
|
||||
return &m_trackSettingsWidget;
|
||||
}
|
||||
|
||||
inline TrackContentWidget * getTrackContentWidget()
|
||||
{
|
||||
return &m_trackContentWidget;
|
||||
}
|
||||
|
||||
bool isMovingTrack() const
|
||||
{
|
||||
return m_action == MoveTrack;
|
||||
}
|
||||
|
||||
virtual void update();
|
||||
|
||||
// Create a menu for assigning/creating channels for this track
|
||||
// Currently instrument track and sample track supports it
|
||||
virtual QMenu * createFxMenu(QString title, QString newFxLabel);
|
||||
|
||||
|
||||
public slots:
|
||||
virtual bool close();
|
||||
|
||||
|
||||
protected:
|
||||
void modelChanged() override;
|
||||
|
||||
void saveSettings( QDomDocument& doc, QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(doc)
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
void loadSettings( const QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "trackview";
|
||||
}
|
||||
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * me ) override;
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void resizeEvent( QResizeEvent * re ) override;
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
MoveTrack,
|
||||
ResizeTrack
|
||||
} ;
|
||||
|
||||
Track * m_track;
|
||||
TrackContainerView * m_trackContainerView;
|
||||
|
||||
TrackOperationsWidget m_trackOperationsWidget;
|
||||
QWidget m_trackSettingsWidget;
|
||||
TrackContentWidget m_trackContentWidget;
|
||||
|
||||
Actions m_action;
|
||||
|
||||
virtual FadeButton * getActivityIndicator()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setIndicatorMute(FadeButton* indicator, bool muted);
|
||||
|
||||
friend class TrackLabelButton;
|
||||
|
||||
|
||||
private slots:
|
||||
void createTCOView( TrackContentObject * tco );
|
||||
void muteChanged();
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -93,13 +93,13 @@ public:
|
||||
return m_TrackContainerType;
|
||||
}
|
||||
|
||||
virtual AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum = -1) const;
|
||||
virtual AutomatedValueMap automatedValuesAt(TimePos time, int tcoNum = -1) const;
|
||||
|
||||
signals:
|
||||
void trackAdded( Track * _track );
|
||||
|
||||
protected:
|
||||
static AutomatedValueMap automatedValuesFromTracks(const TrackList &tracks, MidiTime timeStart, int tcoNum = -1);
|
||||
static AutomatedValueMap automatedValuesFromTracks(const TrackList &tracks, TimePos timeStart, int tcoNum = -1);
|
||||
|
||||
mutable QReadWriteLock m_tracksMutex;
|
||||
|
||||
@@ -115,30 +115,4 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
class DummyTrackContainer : public TrackContainer
|
||||
{
|
||||
public:
|
||||
DummyTrackContainer();
|
||||
|
||||
virtual ~DummyTrackContainer()
|
||||
{
|
||||
}
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "DummyTrackContainer";
|
||||
}
|
||||
|
||||
InstrumentTrack * dummyInstrumentTrack()
|
||||
{
|
||||
return m_dummyInstrumentTrack;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
InstrumentTrack * m_dummyInstrumentTrack;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,12 +31,15 @@
|
||||
#include <QWidget>
|
||||
#include <QThread>
|
||||
|
||||
#include "Track.h"
|
||||
#include "JournallingObject.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "ModelView.h"
|
||||
#include "Rubberband.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
|
||||
class QVBoxLayout;
|
||||
|
||||
class InstrumentTrack;
|
||||
class TrackContainer;
|
||||
|
||||
|
||||
@@ -57,7 +60,7 @@ public:
|
||||
return m_scrollArea;
|
||||
}
|
||||
|
||||
inline const MidiTime & currentPosition() const
|
||||
inline const TimePos & currentPosition() const
|
||||
{
|
||||
return m_currentPosition;
|
||||
}
|
||||
@@ -143,7 +146,7 @@ protected:
|
||||
|
||||
void resizeEvent( QResizeEvent * ) override;
|
||||
|
||||
MidiTime m_currentPosition;
|
||||
TimePos m_currentPosition;
|
||||
|
||||
|
||||
private:
|
||||
@@ -182,7 +185,7 @@ private:
|
||||
|
||||
|
||||
signals:
|
||||
void positionChanged( const MidiTime & _pos );
|
||||
void positionChanged( const TimePos & _pos );
|
||||
|
||||
|
||||
} ;
|
||||
|
||||
183
include/TrackContentObject.h
Normal file
183
include/TrackContentObject.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* TrackConteintObject.h - declaration of TrackContentObject class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 TRACK_CONTENT_OBJECT_H
|
||||
#define TRACK_CONTENT_OBJECT_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
#include "AutomatableModel.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
class Track;
|
||||
class TrackContentObjectView;
|
||||
class TrackContainer;
|
||||
class TrackView;
|
||||
|
||||
|
||||
class LMMS_EXPORT TrackContentObject : public Model, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
MM_OPERATORS
|
||||
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
|
||||
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
|
||||
public:
|
||||
TrackContentObject( Track * track );
|
||||
virtual ~TrackContentObject();
|
||||
|
||||
inline Track * getTrack() const
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline const QString & name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
inline void setName( const QString & name )
|
||||
{
|
||||
m_name = name;
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return name();
|
||||
}
|
||||
|
||||
|
||||
inline const TimePos & startPosition() const
|
||||
{
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
inline TimePos endPosition() const
|
||||
{
|
||||
const int sp = m_startPosition;
|
||||
return sp + m_length;
|
||||
}
|
||||
|
||||
inline const TimePos & length() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline void setAutoResize( const bool r )
|
||||
{
|
||||
m_autoResize = r;
|
||||
}
|
||||
|
||||
inline const bool getAutoResize() const
|
||||
{
|
||||
return m_autoResize;
|
||||
}
|
||||
|
||||
QColor color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void setColor( const QColor & c )
|
||||
{
|
||||
m_color = c;
|
||||
}
|
||||
|
||||
bool hasColor();
|
||||
|
||||
void useCustomClipColor( bool b );
|
||||
|
||||
bool usesCustomClipColor()
|
||||
{
|
||||
return m_useCustomClipColor;
|
||||
}
|
||||
|
||||
virtual void movePosition( const TimePos & pos );
|
||||
virtual void changeLength( const TimePos & length );
|
||||
|
||||
virtual TrackContentObjectView * createView( TrackView * tv ) = 0;
|
||||
|
||||
inline void selectViewOnCreate( bool select )
|
||||
{
|
||||
m_selectViewOnCreate = select;
|
||||
}
|
||||
|
||||
inline bool getSelectViewOnCreate()
|
||||
{
|
||||
return m_selectViewOnCreate;
|
||||
}
|
||||
|
||||
/// Returns true if and only if a->startPosition() < b->startPosition()
|
||||
static bool comparePosition(const TrackContentObject* a, const TrackContentObject* b);
|
||||
|
||||
TimePos startTimeOffset() const;
|
||||
void setStartTimeOffset( const TimePos &startTimeOffset );
|
||||
|
||||
void updateColor();
|
||||
|
||||
// Will copy the state of a TCO to another TCO
|
||||
static void copyStateTo( TrackContentObject *src, TrackContentObject *dst );
|
||||
|
||||
public slots:
|
||||
void toggleMute();
|
||||
|
||||
|
||||
signals:
|
||||
void lengthChanged();
|
||||
void positionChanged();
|
||||
void destroyedTCO();
|
||||
void trackColorChanged();
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
Move,
|
||||
Resize
|
||||
} ;
|
||||
|
||||
Track * m_track;
|
||||
QString m_name;
|
||||
|
||||
TimePos m_startPosition;
|
||||
TimePos m_length;
|
||||
TimePos m_startTimeOffset;
|
||||
|
||||
BoolModel m_mutedModel;
|
||||
BoolModel m_soloModel;
|
||||
bool m_autoResize;
|
||||
|
||||
bool m_selectViewOnCreate;
|
||||
|
||||
QColor m_color;
|
||||
bool m_useCustomClipColor;
|
||||
|
||||
friend class TrackContentObjectView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
218
include/TrackContentObjectView.h
Normal file
218
include/TrackContentObjectView.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* TrackContentObjectView.h - declaration of TrackContentObjectView class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 TRACK_CONTENT_OBJECT_VIEW_H
|
||||
#define TRACK_CONTENT_OBJECT_VIEW_H
|
||||
|
||||
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "ModelView.h"
|
||||
#include "Rubberband.h"
|
||||
#include "TrackContentObject.h"
|
||||
|
||||
|
||||
class QMenu;
|
||||
class QContextMenuEvent;
|
||||
|
||||
class DataFile;
|
||||
class TextFloat;
|
||||
class TrackContentObject;
|
||||
class TrackView;
|
||||
|
||||
|
||||
class TrackContentObjectView : public selectableObject, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// theming qproperties
|
||||
Q_PROPERTY( QColor mutedColor READ mutedColor WRITE setMutedColor )
|
||||
Q_PROPERTY( QColor mutedBackgroundColor READ mutedBackgroundColor WRITE setMutedBackgroundColor )
|
||||
Q_PROPERTY( QColor selectedColor READ selectedColor WRITE setSelectedColor )
|
||||
Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor )
|
||||
Q_PROPERTY( QColor textBackgroundColor READ textBackgroundColor WRITE setTextBackgroundColor )
|
||||
Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor )
|
||||
Q_PROPERTY( QColor BBPatternBackground READ BBPatternBackground WRITE setBBPatternBackground )
|
||||
Q_PROPERTY( bool gradient READ gradient WRITE setGradient )
|
||||
// We have to use a QSize here because using QPoint isn't supported.
|
||||
// width -> x, height -> y
|
||||
Q_PROPERTY( QSize mouseHotspotHand WRITE setMouseHotspotHand )
|
||||
|
||||
public:
|
||||
TrackContentObjectView( TrackContentObject * tco, TrackView * tv );
|
||||
virtual ~TrackContentObjectView();
|
||||
|
||||
bool fixedTCOs();
|
||||
|
||||
inline TrackContentObject * getTrackContentObject()
|
||||
{
|
||||
return m_tco;
|
||||
}
|
||||
|
||||
inline TrackView * getTrackView()
|
||||
{
|
||||
return m_trackView;
|
||||
}
|
||||
|
||||
// qproperty access func
|
||||
QColor mutedColor() const;
|
||||
QColor mutedBackgroundColor() const;
|
||||
QColor selectedColor() const;
|
||||
QColor textColor() const;
|
||||
QColor textBackgroundColor() const;
|
||||
QColor textShadowColor() const;
|
||||
QColor BBPatternBackground() const;
|
||||
bool gradient() const;
|
||||
void setMutedColor( const QColor & c );
|
||||
void setMutedBackgroundColor( const QColor & c );
|
||||
void setSelectedColor( const QColor & c );
|
||||
void setTextColor( const QColor & c );
|
||||
void setTextBackgroundColor( const QColor & c );
|
||||
void setTextShadowColor( const QColor & c );
|
||||
void setBBPatternBackground( const QColor & c );
|
||||
void setGradient( const bool & b );
|
||||
void setMouseHotspotHand(const QSize & s);
|
||||
|
||||
// access needsUpdate member variable
|
||||
bool needsUpdate();
|
||||
void setNeedsUpdate( bool b );
|
||||
|
||||
// Method to get a QVector of TCOs to be affected by a context menu action
|
||||
QVector<TrackContentObjectView *> getClickedTCOs();
|
||||
|
||||
// Methods to remove, copy, cut, paste and mute a QVector of TCO views
|
||||
void copy( QVector<TrackContentObjectView *> tcovs );
|
||||
void cut( QVector<TrackContentObjectView *> tcovs );
|
||||
void paste();
|
||||
// remove and toggleMute are static because they don't depend
|
||||
// being called from a particular TCO view, but can be called anywhere as long
|
||||
// as a valid TCO view list is given, while copy/cut require an instance for
|
||||
// some metadata to be written to the clipboard.
|
||||
static void remove( QVector<TrackContentObjectView *> tcovs );
|
||||
static void toggleMute( QVector<TrackContentObjectView *> tcovs );
|
||||
|
||||
QColor getColorForDisplay( QColor );
|
||||
|
||||
public slots:
|
||||
virtual bool close();
|
||||
void remove();
|
||||
void update() override;
|
||||
|
||||
void changeClipColor();
|
||||
void useTrackColor();
|
||||
|
||||
protected:
|
||||
enum ContextMenuAction
|
||||
{
|
||||
Remove,
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
Mute
|
||||
};
|
||||
|
||||
virtual void constructContextMenu( QMenu * )
|
||||
{
|
||||
}
|
||||
|
||||
void contextMenuEvent( QContextMenuEvent * cme ) override;
|
||||
void contextMenuAction( ContextMenuAction action );
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void leaveEvent( QEvent * e ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * me ) override;
|
||||
void resizeEvent( QResizeEvent * re ) override
|
||||
{
|
||||
m_needsUpdate = true;
|
||||
selectableObject::resizeEvent( re );
|
||||
}
|
||||
|
||||
float pixelsPerBar();
|
||||
|
||||
|
||||
DataFile createTCODataFiles(const QVector<TrackContentObjectView *> & tcos) const;
|
||||
|
||||
virtual void paintTextLabel(QString const & text, QPainter & painter);
|
||||
|
||||
|
||||
protected slots:
|
||||
void updateLength();
|
||||
void updatePosition();
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
Move,
|
||||
MoveSelection,
|
||||
Resize,
|
||||
ResizeLeft,
|
||||
CopySelection,
|
||||
ToggleSelected
|
||||
} ;
|
||||
|
||||
static TextFloat * s_textFloat;
|
||||
|
||||
TrackContentObject * m_tco;
|
||||
TrackView * m_trackView;
|
||||
Actions m_action;
|
||||
QPoint m_initialMousePos;
|
||||
QPoint m_initialMouseGlobalPos;
|
||||
TimePos m_initialTCOPos;
|
||||
TimePos m_initialTCOEnd;
|
||||
QVector<TimePos> m_initialOffsets;
|
||||
|
||||
TextFloat * m_hint;
|
||||
|
||||
// qproperty fields
|
||||
QColor m_mutedColor;
|
||||
QColor m_mutedBackgroundColor;
|
||||
QColor m_selectedColor;
|
||||
QColor m_textColor;
|
||||
QColor m_textBackgroundColor;
|
||||
QColor m_textShadowColor;
|
||||
QColor m_BBPatternBackground;
|
||||
bool m_gradient;
|
||||
QSize m_mouseHotspotHand; // QSize must be used because QPoint isn't supported by property system
|
||||
bool m_cursorSetYet;
|
||||
|
||||
bool m_needsUpdate;
|
||||
inline void setInitialPos( QPoint pos )
|
||||
{
|
||||
m_initialMousePos = pos;
|
||||
m_initialMouseGlobalPos = mapToGlobal( pos );
|
||||
m_initialTCOPos = m_tco->startPosition();
|
||||
m_initialTCOEnd = m_initialTCOPos + m_tco->length();
|
||||
}
|
||||
void setInitialOffsets();
|
||||
|
||||
bool mouseMovedDistance( QMouseEvent * me, int distance );
|
||||
TimePos draggedTCOPos( QMouseEvent * me );
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
142
include/TrackContentWidget.h
Normal file
142
include/TrackContentWidget.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* TrackContentWidget.h - declaration of TrackContentWidget class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 TRACK_CONTENT_WIDGET_H
|
||||
#define TRACK_CONTENT_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
|
||||
class QMimeData;
|
||||
|
||||
class Track;
|
||||
class TrackContentObjectView;
|
||||
class TrackView;
|
||||
|
||||
|
||||
class TrackContentWidget : public QWidget, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// qproperties for track background gradients
|
||||
Q_PROPERTY( QBrush darkerColor READ darkerColor WRITE setDarkerColor )
|
||||
Q_PROPERTY( QBrush lighterColor READ lighterColor WRITE setLighterColor )
|
||||
Q_PROPERTY( QBrush gridColor READ gridColor WRITE setGridColor )
|
||||
Q_PROPERTY( QBrush embossColor READ embossColor WRITE setEmbossColor )
|
||||
|
||||
public:
|
||||
TrackContentWidget( TrackView * parent );
|
||||
virtual ~TrackContentWidget();
|
||||
|
||||
/*! \brief Updates the background tile pixmap. */
|
||||
void updateBackground();
|
||||
|
||||
void addTCOView( TrackContentObjectView * tcov );
|
||||
void removeTCOView( TrackContentObjectView * tcov );
|
||||
void removeTCOView( int tcoNum )
|
||||
{
|
||||
if( tcoNum >= 0 && tcoNum < m_tcoViews.size() )
|
||||
{
|
||||
removeTCOView( m_tcoViews[tcoNum] );
|
||||
}
|
||||
}
|
||||
|
||||
bool canPasteSelection( TimePos tcoPos, const QDropEvent *de );
|
||||
bool canPasteSelection( TimePos tcoPos, const QMimeData *md, bool allowSameBar = false );
|
||||
bool pasteSelection( TimePos tcoPos, QDropEvent * de );
|
||||
bool pasteSelection( TimePos tcoPos, const QMimeData * md, bool skipSafetyCheck = false );
|
||||
|
||||
TimePos endPosition( const TimePos & posStart );
|
||||
|
||||
// qproperty access methods
|
||||
|
||||
QBrush darkerColor() const;
|
||||
QBrush lighterColor() const;
|
||||
QBrush gridColor() const;
|
||||
QBrush embossColor() const;
|
||||
|
||||
void setDarkerColor( const QBrush & c );
|
||||
void setLighterColor( const QBrush & c );
|
||||
void setGridColor( const QBrush & c );
|
||||
void setEmbossColor( const QBrush & c);
|
||||
|
||||
public slots:
|
||||
void update();
|
||||
void changePosition( const TimePos & newPos = TimePos( -1 ) );
|
||||
|
||||
protected:
|
||||
enum ContextMenuAction
|
||||
{
|
||||
Paste
|
||||
};
|
||||
|
||||
void contextMenuEvent( QContextMenuEvent * cme ) override;
|
||||
void contextMenuAction( QContextMenuEvent * cme, ContextMenuAction action );
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void resizeEvent( QResizeEvent * re ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "trackcontentwidget";
|
||||
}
|
||||
|
||||
void saveSettings( QDomDocument& doc, QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(doc)
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
void loadSettings( const QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Track * getTrack();
|
||||
TimePos getPosition( int mouseX );
|
||||
|
||||
TrackView * m_trackView;
|
||||
|
||||
typedef QVector<TrackContentObjectView *> tcoViewVector;
|
||||
tcoViewVector m_tcoViews;
|
||||
|
||||
QPixmap m_background;
|
||||
|
||||
// qproperty fields
|
||||
QBrush m_darkerColor;
|
||||
QBrush m_lighterColor;
|
||||
QBrush m_gridColor;
|
||||
QBrush m_embossColor;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
79
include/TrackOperationsWidget.h
Normal file
79
include/TrackOperationsWidget.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* TrackOperationsWidget.h - declaration of TrackOperationsWidget class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 TRACK_OPERATIONS_WIDGET_H
|
||||
#define TRACK_OPERATIONS_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class PixmapButton;
|
||||
class TrackView;
|
||||
|
||||
class TrackOperationsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackOperationsWidget( TrackView * parent );
|
||||
~TrackOperationsWidget();
|
||||
|
||||
|
||||
protected:
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
|
||||
|
||||
private slots:
|
||||
void cloneTrack();
|
||||
void removeTrack();
|
||||
void updateMenu();
|
||||
void changeTrackColor();
|
||||
void randomTrackColor();
|
||||
void resetTrackColor();
|
||||
void useTrackColor();
|
||||
void toggleRecording(bool on);
|
||||
void recordingOn();
|
||||
void recordingOff();
|
||||
void clearTrack();
|
||||
|
||||
private:
|
||||
TrackView * m_trackView;
|
||||
|
||||
QPushButton * m_trackOps;
|
||||
PixmapButton * m_muteBtn;
|
||||
PixmapButton * m_soloBtn;
|
||||
|
||||
|
||||
friend class TrackView;
|
||||
|
||||
signals:
|
||||
void trackRemovalScheduled( TrackView * t );
|
||||
void colorChanged( QColor & c );
|
||||
void colorParented();
|
||||
void colorReset();
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
173
include/TrackView.h
Normal file
173
include/TrackView.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* TrackView.h - declaration of TrackView class
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* 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 TRACK_VIEW_H
|
||||
#define TRACK_VIEW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "ModelView.h"
|
||||
#include "TrackContentWidget.h"
|
||||
#include "TrackOperationsWidget.h"
|
||||
|
||||
|
||||
class QMenu;
|
||||
|
||||
class FadeButton;
|
||||
class Track;
|
||||
class TrackContainerView;
|
||||
class TrackContentObject;
|
||||
|
||||
|
||||
const int DEFAULT_SETTINGS_WIDGET_WIDTH = 224;
|
||||
const int TRACK_OP_WIDTH = 78;
|
||||
// This shaves 150-ish pixels off track buttons,
|
||||
// ruled from config: ui.compacttrackbuttons
|
||||
const int DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT = 96;
|
||||
const int TRACK_OP_WIDTH_COMPACT = 62;
|
||||
|
||||
const int TCO_BORDER_WIDTH = 2;
|
||||
|
||||
|
||||
class TrackView : public QWidget, public ModelView, public JournallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackView( Track * _track, TrackContainerView* tcv );
|
||||
virtual ~TrackView();
|
||||
|
||||
inline const Track * getTrack() const
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline Track * getTrack()
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline TrackContainerView* trackContainerView()
|
||||
{
|
||||
return m_trackContainerView;
|
||||
}
|
||||
|
||||
inline TrackOperationsWidget * getTrackOperationsWidget()
|
||||
{
|
||||
return &m_trackOperationsWidget;
|
||||
}
|
||||
|
||||
inline QWidget * getTrackSettingsWidget()
|
||||
{
|
||||
return &m_trackSettingsWidget;
|
||||
}
|
||||
|
||||
inline TrackContentWidget * getTrackContentWidget()
|
||||
{
|
||||
return &m_trackContentWidget;
|
||||
}
|
||||
|
||||
bool isMovingTrack() const
|
||||
{
|
||||
return m_action == MoveTrack;
|
||||
}
|
||||
|
||||
virtual void update();
|
||||
|
||||
// Create a menu for assigning/creating channels for this track
|
||||
// Currently instrument track and sample track supports it
|
||||
virtual QMenu * createFxMenu(QString title, QString newFxLabel);
|
||||
|
||||
|
||||
public slots:
|
||||
virtual bool close();
|
||||
|
||||
|
||||
protected:
|
||||
void modelChanged() override;
|
||||
|
||||
void saveSettings( QDomDocument& doc, QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(doc)
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
void loadSettings( const QDomElement& element ) override
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "trackview";
|
||||
}
|
||||
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * dee ) override;
|
||||
void dropEvent( QDropEvent * de ) override;
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * me ) override;
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void resizeEvent( QResizeEvent * re ) override;
|
||||
|
||||
|
||||
private:
|
||||
enum Actions
|
||||
{
|
||||
NoAction,
|
||||
MoveTrack,
|
||||
ResizeTrack
|
||||
} ;
|
||||
|
||||
Track * m_track;
|
||||
TrackContainerView * m_trackContainerView;
|
||||
|
||||
TrackOperationsWidget m_trackOperationsWidget;
|
||||
QWidget m_trackSettingsWidget;
|
||||
TrackContentWidget m_trackContentWidget;
|
||||
|
||||
Actions m_action;
|
||||
|
||||
virtual FadeButton * getActivityIndicator()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setIndicatorMute(FadeButton* indicator, bool muted);
|
||||
|
||||
friend class TrackLabelButton;
|
||||
|
||||
|
||||
private slots:
|
||||
void createTCOView( TrackContentObject * tco );
|
||||
void muteChanged();
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -134,7 +134,7 @@ void Lv2Instrument::loadFile(const QString &file)
|
||||
|
||||
#ifdef LV2_INSTRUMENT_USE_MIDI
|
||||
bool Lv2Instrument::handleMidiEvent(
|
||||
const MidiEvent &event, const MidiTime &time, f_cnt_t offset)
|
||||
const MidiEvent &event, const TimePos &time, f_cnt_t offset)
|
||||
{
|
||||
// this function can be called from GUI threads while the plugin is running
|
||||
// handleMidiInputEvent will use a thread-safe ringbuffer
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
bool hasNoteInput() const override { return Lv2ControlBase::hasNoteInput(); }
|
||||
#ifdef LV2_INSTRUMENT_USE_MIDI
|
||||
bool handleMidiEvent(const MidiEvent &event,
|
||||
const MidiTime &time = MidiTime(), f_cnt_t offset = 0) override;
|
||||
const TimePos &time = TimePos(), f_cnt_t offset = 0) override;
|
||||
#else
|
||||
void playNote(NotePlayHandle *nph, sampleFrame *) override;
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "lmms_math.h"
|
||||
#include "TrackContainer.h"
|
||||
#include "BBTrack.h"
|
||||
#include "DataFile.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "LocaleHelper.h"
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "Instrument.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "MainWindow.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "debug.h"
|
||||
#include "Song.h"
|
||||
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
|
||||
AutomationTrack * at;
|
||||
AutomationPattern * ap;
|
||||
MidiTime lastPos;
|
||||
TimePos lastPos;
|
||||
|
||||
smfMidiCC & create( TrackContainer* tc, QString tn )
|
||||
{
|
||||
@@ -187,11 +187,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
smfMidiCC & putValue( MidiTime time, AutomatableModel * objModel, float value )
|
||||
smfMidiCC & putValue( TimePos time, AutomatableModel * objModel, float value )
|
||||
{
|
||||
if( !ap || time > lastPos + DefaultTicksPerBar )
|
||||
{
|
||||
MidiTime pPos = MidiTime( time.getBar(), 0 );
|
||||
TimePos pPos = TimePos( time.getBar(), 0 );
|
||||
ap = dynamic_cast<AutomationPattern*>(
|
||||
at->createTCO(pPos));
|
||||
ap->addObject( objModel );
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
lastPos = time;
|
||||
time = time - ap->startPosition();
|
||||
ap->putValue( time, value, false );
|
||||
ap->changeLength( MidiTime( time.getBar() + 1, 0 ) );
|
||||
ap->changeLength( TimePos( time.getBar() + 1, 0 ) );
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -278,14 +278,14 @@ public:
|
||||
void splitPatterns()
|
||||
{
|
||||
Pattern * newPattern = nullptr;
|
||||
MidiTime lastEnd(0);
|
||||
TimePos lastEnd(0);
|
||||
|
||||
p->rearrangeAllNotes();
|
||||
for (auto n : p->notes())
|
||||
{
|
||||
if (!newPattern || n->pos() > lastEnd + DefaultTicksPerBar)
|
||||
{
|
||||
MidiTime pPos = MidiTime(n->pos().getBar(), 0);
|
||||
TimePos pPos = TimePos(n->pos().getBar(), 0);
|
||||
newPattern = dynamic_cast<Pattern*>(it->createTCO(pPos));
|
||||
}
|
||||
lastEnd = n->pos() + n->length();
|
||||
|
||||
@@ -293,7 +293,7 @@ int OpulenzInstrument::pushVoice(int v) {
|
||||
return i;
|
||||
}
|
||||
|
||||
bool OpulenzInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset )
|
||||
bool OpulenzInstrument::handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset )
|
||||
{
|
||||
emulatorMutex.lock();
|
||||
int key, vel, voice, tmp_pb;
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
return IsSingleStreamed | IsMidiBased;
|
||||
}
|
||||
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 );
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0 );
|
||||
virtual void play( sampleFrame * _working_buffer );
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _this );
|
||||
|
||||
@@ -168,7 +168,7 @@ void VectorView::paintEvent(QPaintEvent *event)
|
||||
// To better preserve shapes, the log scale is applied to the distance from origin,
|
||||
// not the individual channels.
|
||||
const float distance = sqrt(inLeft * inLeft + inRight * inRight);
|
||||
const float distanceLog = log10(1 + 9 * abs(distance));
|
||||
const float distanceLog = log10(1 + 9 * std::abs(distance));
|
||||
const float angleCos = inLeft / distance;
|
||||
const float angleSin = inRight / distance;
|
||||
left = distanceLog * angleCos * (activeSize - 1) / 4;
|
||||
@@ -222,7 +222,7 @@ void VectorView::paintEvent(QPaintEvent *event)
|
||||
float inRight = inBuffer[frame][1] * m_zoom;
|
||||
if (logScale) {
|
||||
const float distance = sqrt(inLeft * inLeft + inRight * inRight);
|
||||
const float distanceLog = log10(1 + 9 * abs(distance));
|
||||
const float distanceLog = log10(1 + 9 * std::abs(distance));
|
||||
const float angleCos = inLeft / distance;
|
||||
const float angleSin = inRight / distance;
|
||||
left = distanceLog * angleCos * (activeSize - 1) / 4;
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
|
||||
#include "plugin_export.h"
|
||||
|
||||
static const int wavetableSize = 200;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
@@ -72,8 +74,8 @@ bSynth::bSynth( float * _shape, NotePlayHandle * _nph, bool _interpolation,
|
||||
sample_rate( _sample_rate ),
|
||||
interpolation( _interpolation)
|
||||
{
|
||||
sample_shape = new float[200];
|
||||
for (int i=0; i < 200; ++i)
|
||||
sample_shape = new float[wavetableSize];
|
||||
for (int i=0; i < wavetableSize; ++i)
|
||||
{
|
||||
sample_shape[i] = _shape[i] * _factor;
|
||||
}
|
||||
@@ -138,12 +140,12 @@ sample_t bSynth::nextStringSample( float sample_length )
|
||||
|
||||
bitInvader::bitInvader( InstrumentTrack * _instrument_track ) :
|
||||
Instrument( _instrument_track, &bitinvader_plugin_descriptor ),
|
||||
m_sampleLength( 128, 4, 200, 1, this, tr( "Sample length" ) ),
|
||||
m_graph( -1.0f, 1.0f, 200, this ),
|
||||
m_sampleLength(128, 4, wavetableSize, 1, this, tr("Sample length")),
|
||||
m_graph(-1.0f, 1.0f, wavetableSize, this),
|
||||
m_interpolation( false, this ),
|
||||
m_normalize( false, this )
|
||||
{
|
||||
|
||||
|
||||
lengthChanged();
|
||||
|
||||
m_graph.setWaveToSine();
|
||||
@@ -177,8 +179,8 @@ void bitInvader::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
|
||||
// Save sample shape base64-encoded
|
||||
QString sampleString;
|
||||
base64::encode( (const char *)m_graph.samples(),
|
||||
m_graph.length() * sizeof(float), sampleString );
|
||||
base64::encode((const char *)m_graph.samples(),
|
||||
wavetableSize * sizeof(float), sampleString);
|
||||
_this.setAttribute( "sampleShape", sampleString );
|
||||
|
||||
|
||||
@@ -194,6 +196,9 @@ void bitInvader::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
|
||||
void bitInvader::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
// Clear wavetable before loading a new
|
||||
m_graph.clear();
|
||||
|
||||
// Load sample length
|
||||
m_sampleLength.loadSettings( _this, "sampleLength" );
|
||||
|
||||
@@ -204,8 +209,9 @@ void bitInvader::loadSettings( const QDomElement & _this )
|
||||
char * dst = 0;
|
||||
base64::decode( _this.attribute( "sampleShape"), &dst, &size );
|
||||
|
||||
m_graph.setLength( sampleLength );
|
||||
m_graph.setSamples( (float*) dst );
|
||||
m_graph.setLength(size / sizeof(float));
|
||||
m_graph.setSamples(reinterpret_cast<float*>(dst));
|
||||
m_graph.setLength(sampleLength);
|
||||
delete[] dst;
|
||||
|
||||
// Load LED normalize
|
||||
@@ -240,7 +246,7 @@ void bitInvader::samplesChanged( int _begin, int _end )
|
||||
void bitInvader::normalize()
|
||||
{
|
||||
// analyze
|
||||
float max = 0;
|
||||
float max = std::numeric_limits<float>::epsilon();
|
||||
const float* samples = m_graph.samples();
|
||||
for(int i=0; i < m_graph.length(); i++)
|
||||
{
|
||||
|
||||
@@ -355,7 +355,7 @@ void CarlaInstrument::play(sampleFrame* workingBuffer)
|
||||
instrumentTrack()->processAudioBuffer(workingBuffer, bufsize, NULL);
|
||||
}
|
||||
|
||||
bool CarlaInstrument::handleMidiEvent(const MidiEvent& event, const MidiTime&, f_cnt_t offset)
|
||||
bool CarlaInstrument::handleMidiEvent(const MidiEvent& event, const TimePos&, f_cnt_t offset)
|
||||
{
|
||||
const QMutexLocker ml(&fMutex);
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
virtual void saveSettings(QDomDocument& doc, QDomElement& parent);
|
||||
virtual void loadSettings(const QDomElement& elem);
|
||||
virtual void play(sampleFrame* workingBuffer);
|
||||
virtual bool handleMidiEvent(const MidiEvent& event, const MidiTime& time, f_cnt_t offset);
|
||||
virtual bool handleMidiEvent(const MidiEvent& event, const TimePos& time, f_cnt_t offset);
|
||||
virtual PluginView* instantiateView(QWidget* parent);
|
||||
|
||||
signals:
|
||||
|
||||
@@ -48,7 +48,6 @@ float frnd(float range)
|
||||
#include "ToolTip.h"
|
||||
#include "Song.h"
|
||||
#include "MidiEvent.h"
|
||||
#include "MidiTime.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
#include "embed.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
BUILD_PLUGIN(stereomatrix stereo_matrix.cpp stereomatrix_controls.cpp stereomatrix_control_dialog.cpp stereo_matrix.h stereomatrix_controls.h stereomatrix_control_dialog.h MOCFILES stereomatrix_controls.h stereomatrix_control_dialog.h EMBEDDED_RESOURCES artwork.png)
|
||||
BUILD_PLUGIN(stereomatrix stereo_matrix.cpp stereomatrix_controls.cpp stereomatrix_control_dialog.cpp stereo_matrix.h stereomatrix_controls.h stereomatrix_control_dialog.h MOCFILES stereomatrix_controls.h stereomatrix_control_dialog.h EMBEDDED_RESOURCES artwork.png logo.png)
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@ void vestigeInstrument::play( sampleFrame * _buf )
|
||||
|
||||
|
||||
|
||||
bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset )
|
||||
bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset )
|
||||
{
|
||||
m_pluginMutex.lock();
|
||||
if( m_plugin != NULL )
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
return IsSingleStreamed | IsMidiBased;
|
||||
}
|
||||
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 );
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0 );
|
||||
|
||||
virtual PluginView * instantiateView( QWidget * _parent );
|
||||
|
||||
|
||||
@@ -351,7 +351,7 @@ void ZynAddSubFxInstrument::play( sampleFrame * _buf )
|
||||
|
||||
|
||||
|
||||
bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset )
|
||||
bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset )
|
||||
{
|
||||
// do not forward external MIDI Control Change events if the according
|
||||
// LED is not checked
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
|
||||
virtual void play( sampleFrame * _working_buffer );
|
||||
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 );
|
||||
virtual bool handleMidiEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 );
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
|
||||
@@ -708,7 +708,7 @@ void AutomatableModel::reset()
|
||||
|
||||
|
||||
|
||||
float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
float AutomatableModel::globalAutomationValueAt( const TimePos& time )
|
||||
{
|
||||
// get patterns that connect to this model
|
||||
QVector<AutomationPattern *> patterns = AutomationPattern::patternsForModel( this );
|
||||
@@ -720,7 +720,7 @@ float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
else
|
||||
{
|
||||
// of those patterns:
|
||||
// find the patterns which overlap with the miditime position
|
||||
// find the patterns which overlap with the time position
|
||||
QVector<AutomationPattern *> patternsInRange;
|
||||
for( QVector<AutomationPattern *>::ConstIterator it = patterns.begin(); it != patterns.end(); it++ )
|
||||
{
|
||||
@@ -738,7 +738,7 @@ float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
|
||||
latestPattern = patternsInRange[0];
|
||||
}
|
||||
else
|
||||
// if we find no patterns at the exact miditime, we need to search for the last pattern before time and use that
|
||||
// if we find no patterns at the exact time, we need to search for the last pattern before time and use that
|
||||
{
|
||||
int latestPosition = 0;
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) :
|
||||
m_isRecording( false ),
|
||||
m_lastRecordedValue( 0 )
|
||||
{
|
||||
changeLength( MidiTime( 1, 0 ) );
|
||||
changeLength( TimePos( 1, 0 ) );
|
||||
if( getTrack() )
|
||||
{
|
||||
switch( getTrack()->trackContainer()->type() )
|
||||
@@ -110,7 +110,7 @@ bool AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
|
||||
if( m_objects.isEmpty() && hasAutomation() == false )
|
||||
{
|
||||
// then initialize first value
|
||||
putValue( MidiTime(0), _obj->inverseScaledValue( _obj->value<float>() ), false );
|
||||
putValue( TimePos(0), _obj->inverseScaledValue( _obj->value<float>() ), false );
|
||||
}
|
||||
|
||||
m_objects += _obj;
|
||||
@@ -132,7 +132,8 @@ void AutomationPattern::setProgressionType(
|
||||
{
|
||||
if ( _new_progression_type == DiscreteProgression ||
|
||||
_new_progression_type == LinearProgression ||
|
||||
_new_progression_type == CubicHermiteProgression )
|
||||
_new_progression_type == CubicHermiteProgression ||
|
||||
_new_progression_type == BezierProgression )
|
||||
{
|
||||
m_progressionType = _new_progression_type;
|
||||
emit dataChanged();
|
||||
@@ -176,9 +177,9 @@ const AutomationPattern::objectVector& AutomationPattern::objects() const
|
||||
|
||||
|
||||
|
||||
MidiTime AutomationPattern::timeMapLength() const
|
||||
TimePos AutomationPattern::timeMapLength() const
|
||||
{
|
||||
MidiTime one_bar = MidiTime(1, 0);
|
||||
TimePos one_bar = TimePos(1, 0);
|
||||
if (m_timeMap.isEmpty()) { return one_bar; }
|
||||
|
||||
timeMap::const_iterator it = m_timeMap.end();
|
||||
@@ -187,7 +188,7 @@ MidiTime AutomationPattern::timeMapLength() const
|
||||
// return length as a whole bar to prevent disappearing TCO
|
||||
if (last_tick == 0) { return one_bar; }
|
||||
|
||||
return MidiTime(last_tick);
|
||||
return TimePos(last_tick);
|
||||
}
|
||||
|
||||
|
||||
@@ -202,14 +203,55 @@ void AutomationPattern::updateLength()
|
||||
|
||||
|
||||
|
||||
MidiTime AutomationPattern::putValue( const MidiTime & time,
|
||||
TimePos AutomationPattern::putControlPoint( timeMap::const_iterator it,
|
||||
const int time, const float _value, const bool flip )
|
||||
{
|
||||
if (flip)
|
||||
{
|
||||
putControlPoint( it, 2 * it.key() - time, 2 * it.value() - _value );
|
||||
}
|
||||
else
|
||||
{
|
||||
putControlPoint( it, time, _value );
|
||||
}
|
||||
return it.key();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* If we are only given the value and automation point
|
||||
then figure out where to put the control point */
|
||||
TimePos AutomationPattern::putControlPoint(timeMap::const_iterator it,
|
||||
const float _value)
|
||||
{
|
||||
// Insert control point at the automation point
|
||||
return putControlPoint( it, (float)it.key() + 50, _value );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TimePos AutomationPattern::putControlPoint(timeMap::const_iterator it,
|
||||
const int time, const float _value)
|
||||
{
|
||||
m_controlPoints.remove( it.key() );
|
||||
m_controlPoints[it.key()] = {time, _value};
|
||||
clampControlPoints();
|
||||
return it.key();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TimePos AutomationPattern::putValue( const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos,
|
||||
const bool ignoreSurroundingPoints )
|
||||
{
|
||||
cleanObjects();
|
||||
|
||||
MidiTime newTime = quantPos ?
|
||||
TimePos newTime = quantPos ?
|
||||
Note::quantized( time, quantization() ) :
|
||||
time;
|
||||
|
||||
@@ -225,6 +267,9 @@ MidiTime AutomationPattern::putValue( const MidiTime & time,
|
||||
AutomationPattern::removeValue( i );
|
||||
}
|
||||
}
|
||||
putControlPoint(it, value);
|
||||
clampControlPoints();
|
||||
|
||||
if( it != m_timeMap.begin() )
|
||||
{
|
||||
--it;
|
||||
@@ -241,12 +286,13 @@ MidiTime AutomationPattern::putValue( const MidiTime & time,
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::removeValue( const MidiTime & time )
|
||||
void AutomationPattern::removeValue( const TimePos & time )
|
||||
{
|
||||
cleanObjects();
|
||||
|
||||
m_timeMap.remove( time );
|
||||
m_tangents.remove( time );
|
||||
m_controlPoints.remove( time );
|
||||
timeMap::const_iterator it = m_timeMap.lowerBound( time );
|
||||
if( it != m_timeMap.begin() )
|
||||
{
|
||||
@@ -261,7 +307,7 @@ void AutomationPattern::removeValue( const MidiTime & time )
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::recordValue(MidiTime time, float value)
|
||||
void AutomationPattern::recordValue(TimePos time, float value)
|
||||
{
|
||||
if( value != m_lastRecordedValue )
|
||||
{
|
||||
@@ -286,31 +332,87 @@ void AutomationPattern::recordValue(MidiTime time, float value)
|
||||
* @param true to snip x position
|
||||
* @return
|
||||
*/
|
||||
MidiTime AutomationPattern::setDragValue( const MidiTime & time,
|
||||
TimePos AutomationPattern::setDragValue( const TimePos & time,
|
||||
const float value,
|
||||
const bool quantPos,
|
||||
const bool controlKey )
|
||||
{
|
||||
//cleanControlPoints();
|
||||
if( m_dragging == false )
|
||||
{
|
||||
MidiTime newTime = quantPos ?
|
||||
TimePos newTime = quantPos ?
|
||||
Note::quantized( time, quantization() ) :
|
||||
time;
|
||||
|
||||
if ( m_timeMap.contains( newTime ) )
|
||||
{
|
||||
// Set the offset for the control point, so it gets dragged around with the automation point
|
||||
m_controlPointDragOffset[0] = (float)m_controlPoints[newTime].first - (float)newTime;
|
||||
m_controlPointDragOffset[1] = m_controlPoints[newTime].second - m_timeMap[newTime];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_controlPointDragOffset[0] = 50;
|
||||
m_controlPointDragOffset[1] = 0;
|
||||
}
|
||||
|
||||
this->removeValue( newTime );
|
||||
m_oldTimeMap = m_timeMap;
|
||||
m_oldControlPoints = m_controlPoints;
|
||||
m_dragging = true;
|
||||
}
|
||||
|
||||
//Restore to the state before it the point were being dragged
|
||||
m_timeMap = m_oldTimeMap;
|
||||
m_controlPoints = m_oldControlPoints;
|
||||
|
||||
for( timeMap::const_iterator it = m_timeMap.begin(); it != m_timeMap.end(); ++it )
|
||||
{
|
||||
generateTangents( it, 3 );
|
||||
}
|
||||
|
||||
return this->putValue( time, value, quantPos, controlKey );
|
||||
// Put the new automation point down
|
||||
TimePos returnValue = this->putValue( time, value, quantPos, controlKey );
|
||||
// Put a new control point down at an offset
|
||||
m_controlPoints.remove( returnValue );
|
||||
putControlPoint(m_timeMap.find( returnValue ), (float)returnValue + m_controlPointDragOffset[0],
|
||||
value + m_controlPointDragOffset[1]);
|
||||
clampControlPoints();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TimePos AutomationPattern::setControlPointDragValue( const TimePos & _time, const float _value, const int _x,
|
||||
const bool _quant_pos)
|
||||
{
|
||||
if( m_dragging == false )
|
||||
{
|
||||
TimePos newTime = _quant_pos ?
|
||||
Note::quantized( _time, quantization() ) :
|
||||
_time;
|
||||
m_controlPoints.remove( newTime );
|
||||
m_oldControlPointNode = m_timeMap.find( newTime );
|
||||
m_dragging = true;
|
||||
}
|
||||
|
||||
return this->putControlPoint(m_oldControlPointNode, _x, _value, m_controlFlip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @breif If the control point grabbed is on the left of the automation point,
|
||||
* be flipped in order to get the control points actual location.
|
||||
* @param should the value be flipped or not
|
||||
*/
|
||||
void AutomationPattern::flipControlPoint(bool flip)
|
||||
{
|
||||
m_controlFlip = flip;
|
||||
}
|
||||
|
||||
|
||||
@@ -327,7 +429,7 @@ void AutomationPattern::applyDragValue()
|
||||
|
||||
|
||||
|
||||
float AutomationPattern::valueAt( const MidiTime & _time ) const
|
||||
float AutomationPattern::valueAt( const TimePos & _time ) const
|
||||
{
|
||||
if( m_timeMap.isEmpty() )
|
||||
{
|
||||
@@ -370,7 +472,7 @@ float AutomationPattern::valueAt( timeMap::const_iterator v, int offset ) const
|
||||
((v+1).key() - v.key());
|
||||
return v.value() + offset * slope;
|
||||
}
|
||||
else /* CubicHermiteProgression */
|
||||
else if( m_progressionType == CubicHermiteProgression )
|
||||
{
|
||||
// Implements a Cubic Hermite spline as explained at:
|
||||
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Unit_interval_.280.2C_1.29
|
||||
@@ -390,12 +492,61 @@ float AutomationPattern::valueAt( timeMap::const_iterator v, int offset ) const
|
||||
+ ( -2*pow(t,3) + 3*pow(t,2) ) * (v+1).value()
|
||||
+ ( pow(t,3) - pow(t,2) ) * m2;
|
||||
}
|
||||
else /* BezierProgression */
|
||||
{
|
||||
|
||||
/* Formula goes as such:
|
||||
Automation points: (x0, y0), (x3, y3)
|
||||
Relative control points: (x1, y1), (x2, y2)
|
||||
Where the control points are BETWEEN the automation points.
|
||||
(This isn't the case in this program, so the second control point must be "flipped"
|
||||
around its automation point)
|
||||
|
||||
x = ( (1-t)^3 * x0 ) + ( 3 * (1-t)^2 * t * x1 ) + ( 3 * (1-t) * t^2 * x2 ) + ( t^3 * x3 )
|
||||
y = ( (1-t)^3 * y0 ) + ( 3 * (1-t)^2 * t * y1 ) + ( 3 * (1-t) * t^2 * y2 ) + ( t^3 * y3 )
|
||||
|
||||
0 <= t <= 1
|
||||
*/
|
||||
|
||||
int numValues = (v+1).key() - v.key();
|
||||
|
||||
// The x values are essentially twice the distance from their control points
|
||||
// to make up for their range being limited.
|
||||
int targetX1 = ( m_controlPoints[v.key()].first - v.key() ) * 2;
|
||||
int targetX2 = ( 3 * (v+1).key() - 2 * m_controlPoints[(v+1).key()].first - v.key() );
|
||||
// The y values are the actual y values. Maybe this should be doubled,
|
||||
// but it doesn't seem necessary to me.
|
||||
float targetY1 = m_controlPoints[v.key()].second;
|
||||
float targetY2 = 2*(v+1).value() - m_controlPoints[(v+1).key()].second;
|
||||
|
||||
// To find the y value on the curve at a certain x, we first have to find the t (between 0 and 1) that gives the x
|
||||
float t = 0;
|
||||
float x = 3 * pow((1-t), 2) * t * targetX1 + 3 * (1-t) * pow(t, 2) * targetX2 + pow(t, 3) * numValues;
|
||||
while (offset > x)
|
||||
{
|
||||
t += 0.05;
|
||||
x = 3 * pow((1-t), 2) * t * targetX1 + 3 * (1-t) * pow(t, 2) * targetX2 + pow(t, 3) * numValues;
|
||||
}
|
||||
|
||||
float ratio = x;
|
||||
float y1 = pow((1-t),3) * v.value() + 3 * pow((1-t),2) * t * targetY1 +
|
||||
3 * (1-t) * pow(t,2) * targetY2 + pow(t,3) * (v+1).value();
|
||||
t -= 0.05;
|
||||
float y2 = pow((1-t),3) * v.value() + 3 * pow((1-t),2) * t * targetY1 +
|
||||
3 * (1-t) * pow(t,2) * targetY2 + pow(t,3) * (v+1).value();
|
||||
x = 3 * pow((1-t), 2) * t * targetX1 + 3 * (1-t) * pow(t, 2) * targetX2 + pow(t, 3) * numValues;
|
||||
|
||||
// Ratio is how we get the linear extrapolation between points
|
||||
// We have to get the ratio of how close this point is to its left compared to right
|
||||
ratio = (offset - x) / (ratio - x);
|
||||
return (ratio)*y1 + (1-ratio)*y2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float *AutomationPattern::valuesAfter( const MidiTime & _time ) const
|
||||
float *AutomationPattern::valuesAfter( const TimePos & _time ) const
|
||||
{
|
||||
timeMap::ConstIterator v = m_timeMap.lowerBound( _time );
|
||||
if( v == m_timeMap.end() || (v+1) == m_timeMap.end() )
|
||||
@@ -436,12 +587,16 @@ void AutomationPattern::flipY( int min, int max )
|
||||
if ( min < 0 )
|
||||
{
|
||||
tempValue = valueAt( ( iterate + i ).key() ) * -1;
|
||||
putValue( MidiTime( (iterate + i).key() ) , tempValue, false);
|
||||
putValue( TimePos( (iterate + i).key() ) , tempValue, false);
|
||||
tempValue = m_controlPoints[(iterate + i).key()].second * -1;
|
||||
m_controlPoints[(iterate + i).key()].second = tempValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempValue = max - valueAt( ( iterate + i ).key() );
|
||||
putValue( MidiTime( (iterate + i).key() ) , tempValue, false);
|
||||
putValue( TimePos( (iterate + i).key() ) , tempValue, false);
|
||||
tempValue = max - m_controlPoints[(iterate + i).key()].second;
|
||||
m_controlPoints[(iterate + i).key()].second = tempValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,6 +618,7 @@ void AutomationPattern::flipY()
|
||||
void AutomationPattern::flipX( int length )
|
||||
{
|
||||
timeMap tempMap;
|
||||
controlPointTimeMap tempControlPoints;
|
||||
|
||||
timeMap::ConstIterator iterate = m_timeMap.lowerBound(0);
|
||||
float tempValue = 0;
|
||||
@@ -480,12 +636,17 @@ void AutomationPattern::flipX( int length )
|
||||
if ( realLength < length )
|
||||
{
|
||||
tempValue = valueAt( ( iterate + numPoints ).key() );
|
||||
putValue( MidiTime( length ) , tempValue, false);
|
||||
putValue( TimePos( length ) , tempValue, false);
|
||||
numPoints++;
|
||||
for( int i = 0; i <= numPoints; i++ )
|
||||
{
|
||||
tempValue = valueAt( ( iterate + i ).key() );
|
||||
MidiTime newTime = MidiTime( length - ( iterate + i ).key() );
|
||||
TimePos newTime = TimePos( length - ( iterate + i ).key() );
|
||||
|
||||
int newControlPointX = -( iterate + i ).key() + m_controlPoints[( iterate + i ).key()].first + newTime;
|
||||
tempControlPoints[newTime] = {newControlPointX,
|
||||
2*tempValue - m_controlPoints[( iterate + i ).key()].second};
|
||||
|
||||
tempMap[newTime] = tempValue;
|
||||
}
|
||||
}
|
||||
@@ -494,15 +655,19 @@ void AutomationPattern::flipX( int length )
|
||||
for( int i = 0; i <= numPoints; i++ )
|
||||
{
|
||||
tempValue = valueAt( ( iterate + i ).key() );
|
||||
MidiTime newTime;
|
||||
TimePos newTime;
|
||||
|
||||
int newControlPointX = -( iterate + i ).key() + m_controlPoints[( iterate + i ).key()].first + newTime;
|
||||
tempControlPoints[newTime] = {newControlPointX,
|
||||
2*tempValue - m_controlPoints[( iterate + i ).key()].second};
|
||||
|
||||
if ( ( iterate + i ).key() <= length )
|
||||
{
|
||||
newTime = MidiTime( length - ( iterate + i ).key() );
|
||||
newTime = TimePos( length - ( iterate + i ).key() );
|
||||
}
|
||||
else
|
||||
{
|
||||
newTime = MidiTime( ( iterate + i ).key() );
|
||||
newTime = TimePos( ( iterate + i ).key() );
|
||||
}
|
||||
tempMap[newTime] = tempValue;
|
||||
}
|
||||
@@ -514,14 +679,20 @@ void AutomationPattern::flipX( int length )
|
||||
{
|
||||
tempValue = valueAt( ( iterate + i ).key() );
|
||||
cleanObjects();
|
||||
MidiTime newTime = MidiTime( realLength - ( iterate + i ).key() );
|
||||
TimePos newTime = TimePos( realLength - ( iterate + i ).key() );
|
||||
int newControlPointX = -( iterate + i ).key() + m_controlPoints[( iterate + i ).key()].first + newTime;
|
||||
|
||||
tempMap[newTime] = tempValue;
|
||||
tempControlPoints[newTime] = {newControlPointX,
|
||||
2*tempValue - m_controlPoints[( iterate + i ).key()].second};
|
||||
}
|
||||
}
|
||||
|
||||
m_timeMap.clear();
|
||||
m_controlPoints.clear();
|
||||
|
||||
m_timeMap = tempMap;
|
||||
m_controlPoints = tempControlPoints;
|
||||
|
||||
generateTangents();
|
||||
emit dataChanged();
|
||||
@@ -553,6 +724,16 @@ void AutomationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
_this.appendChild( element );
|
||||
}
|
||||
|
||||
for( controlPointTimeMap::const_iterator it = m_controlPoints.begin();
|
||||
it != m_controlPoints.end(); ++it )
|
||||
{
|
||||
QDomElement element = _doc.createElement( "ctrlpnt" );
|
||||
element.setAttribute( "pos", it.key() );
|
||||
element.setAttribute( "value1", it.value().first );
|
||||
element.setAttribute( "value2", it.value().second );
|
||||
_this.appendChild( element );
|
||||
}
|
||||
|
||||
for( objectVector::const_iterator it = m_objects.begin();
|
||||
it != m_objects.end(); ++it )
|
||||
{
|
||||
@@ -593,6 +774,11 @@ void AutomationPattern::loadSettings( const QDomElement & _this )
|
||||
m_timeMap[element.attribute( "pos" ).toInt()]
|
||||
= LocaleHelper::toFloat(element.attribute("value"));
|
||||
}
|
||||
else if( element.tagName() == "ctrlpnt" )
|
||||
{
|
||||
m_controlPoints[element.attribute( "pos" ).toInt()] = {element.attribute( "value1" ).toInt(),
|
||||
element.attribute( "value2" ).toFloat()};
|
||||
}
|
||||
else if( element.tagName() == "object" )
|
||||
{
|
||||
m_idsToResolve << element.attribute( "id" ).toInt();
|
||||
@@ -616,6 +802,9 @@ void AutomationPattern::loadSettings( const QDomElement & _this )
|
||||
changeLength( len );
|
||||
}
|
||||
generateTangents();
|
||||
|
||||
// Very important for reading older files
|
||||
cleanControlPoints();
|
||||
}
|
||||
|
||||
|
||||
@@ -637,6 +826,62 @@ const QString AutomationPattern::name() const
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::clampControlPoints(bool clampVertical)
|
||||
{
|
||||
timeMap::const_iterator it;
|
||||
for (it = m_timeMap.begin(); it != m_timeMap.end(); it++)
|
||||
{
|
||||
int new_x = m_controlPoints[it.key()].first;
|
||||
float new_y = m_controlPoints[it.key()].second;
|
||||
// Clamp X positions
|
||||
// If the control point x is less than its automation point
|
||||
if ( it.key() > new_x )
|
||||
{
|
||||
new_x = it.key();
|
||||
}
|
||||
// The control point x must not pass the midpoints of its automation point and the automation points
|
||||
// its left and right
|
||||
else if ( it != m_timeMap.begin() && it.key() * 2 - new_x < ( (it-1).key() + it.key() ) / 2 )
|
||||
{
|
||||
new_x = it.key() * 2 - ( (it-1).key() + it.key() )/2;
|
||||
}
|
||||
else if ( it+1 != m_timeMap.end() && new_x > ( (it+1).key() + it.key() )/2 )
|
||||
{
|
||||
new_x = ( (it+1).key() + it.key() )/2;
|
||||
}
|
||||
|
||||
if (clampVertical)
|
||||
{
|
||||
// Clamp y positions between the top and bottom of the screen
|
||||
// Clamp the right control point (keep in mind the last control point isn't clamped)
|
||||
if ( it+1 != m_timeMap.end() && new_y > getMax() )
|
||||
{
|
||||
new_y = getMax();
|
||||
}
|
||||
else if ( it+1 != m_timeMap.end() && new_y < getMin() )
|
||||
{
|
||||
new_y = getMin();
|
||||
}
|
||||
// Clamp the left control point (keep in mind the first control point isn't clamped)
|
||||
if ( it != m_timeMap.begin() && 2 * it.value() - new_y > getMax() )
|
||||
{
|
||||
new_y = 2 * it.value() - getMax();
|
||||
}
|
||||
else if ( it != m_timeMap.begin() && 2 * it.value() - new_y < getMin() )
|
||||
{
|
||||
new_y = 2 * it.value() - getMin();
|
||||
}
|
||||
}
|
||||
|
||||
m_controlPoints.remove( it.key() );
|
||||
|
||||
m_controlPoints[it.key()] = {new_x, new_y};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TrackContentObjectView * AutomationPattern::createView( TrackView * _tv )
|
||||
{
|
||||
return new AutomationPatternView( this, _tv );
|
||||
@@ -818,6 +1063,7 @@ void AutomationPattern::resolveAllIDs()
|
||||
void AutomationPattern::clear()
|
||||
{
|
||||
m_timeMap.clear();
|
||||
m_controlPoints.clear();
|
||||
m_tangents.clear();
|
||||
|
||||
emit dataChanged();
|
||||
@@ -870,6 +1116,40 @@ void AutomationPattern::cleanObjects()
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::cleanControlPoints()
|
||||
{
|
||||
// If there's any control points that aren't connected to an automation point then destroy it
|
||||
for( controlPointTimeMap::iterator it = m_controlPoints.begin(); it != m_controlPoints.end(); )
|
||||
{
|
||||
if(m_timeMap.contains( (int)it.key()) )
|
||||
{
|
||||
it++;
|
||||
}
|
||||
else
|
||||
{
|
||||
it = m_controlPoints.erase( it );
|
||||
}
|
||||
}
|
||||
|
||||
// If there's any automation points without a control point then insert control points
|
||||
for( timeMap::iterator it = m_timeMap.begin(); it != m_timeMap.end(); )
|
||||
{
|
||||
if(m_controlPoints.contains( (int)it.key()) )
|
||||
{
|
||||
it++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_controlPoints[it.key()] = {it.key() + 50, it.value()};
|
||||
}
|
||||
}
|
||||
|
||||
clampControlPoints(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::generateTangents()
|
||||
{
|
||||
generateTangents(m_timeMap.begin(), m_timeMap.size());
|
||||
|
||||
@@ -32,15 +32,15 @@
|
||||
|
||||
BBTrackContainer::BBTrackContainer() :
|
||||
TrackContainer(),
|
||||
m_bbComboBoxModel( this )
|
||||
m_bbComboBoxModel(this)
|
||||
{
|
||||
connect( &m_bbComboBoxModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( currentBBChanged() ) );
|
||||
connect(&m_bbComboBoxModel, SIGNAL(dataChanged()),
|
||||
this, SLOT(currentBBChanged()));
|
||||
// we *always* want to receive updates even in case BB actually did
|
||||
// not change upon setCurrentBB()-call
|
||||
connect( &m_bbComboBoxModel, SIGNAL( dataUnchanged() ),
|
||||
this, SLOT( currentBBChanged() ) );
|
||||
setType( BBContainer );
|
||||
connect(&m_bbComboBoxModel, SIGNAL(dataUnchanged()),
|
||||
this, SLOT(currentBBChanged()));
|
||||
setType(BBContainer);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,27 +53,27 @@ BBTrackContainer::~BBTrackContainer()
|
||||
|
||||
|
||||
|
||||
bool BBTrackContainer::play( MidiTime _start, fpp_t _frames,
|
||||
f_cnt_t _offset, int _tco_num )
|
||||
bool BBTrackContainer::play(TimePos start, fpp_t frames, f_cnt_t offset, int tcoNum)
|
||||
{
|
||||
bool played_a_note = false;
|
||||
if( lengthOfBB( _tco_num ) <= 0 )
|
||||
bool notePlayed = false;
|
||||
|
||||
if (lengthOfBB(tcoNum) <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_start = _start % ( lengthOfBB( _tco_num ) * MidiTime::ticksPerBar() );
|
||||
start = start % (lengthOfBB(tcoNum) * TimePos::ticksPerBar());
|
||||
|
||||
TrackList tl = tracks();
|
||||
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
|
||||
for (Track * t : tl)
|
||||
{
|
||||
if( ( *it )->play( _start, _frames, _offset, _tco_num ) )
|
||||
if (t->play(start, frames, offset, tcoNum))
|
||||
{
|
||||
played_a_note = true;
|
||||
notePlayed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return played_a_note;
|
||||
return notePlayed;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ bool BBTrackContainer::play( MidiTime _start, fpp_t _frames,
|
||||
|
||||
void BBTrackContainer::updateAfterTrackAdd()
|
||||
{
|
||||
if( numOfBBs() == 0 && !Engine::getSong()->isLoadingProject() )
|
||||
if (numOfBBs() == 0 && !Engine::getSong()->isLoadingProject())
|
||||
{
|
||||
Engine::getSong()->addBBTrack();
|
||||
}
|
||||
@@ -90,21 +90,21 @@ void BBTrackContainer::updateAfterTrackAdd()
|
||||
|
||||
|
||||
|
||||
bar_t BBTrackContainer::lengthOfBB( int _bb ) const
|
||||
bar_t BBTrackContainer::lengthOfBB(int bb) const
|
||||
{
|
||||
MidiTime max_length = MidiTime::ticksPerBar();
|
||||
TimePos maxLength = TimePos::ticksPerBar();
|
||||
|
||||
const TrackList & tl = tracks();
|
||||
for (Track* t : tl)
|
||||
for (Track * t : tl)
|
||||
{
|
||||
// Don't create TCOs here if not exist
|
||||
if (_bb < t->numOfTCOs())
|
||||
// Don't create TCOs here if they don't exist
|
||||
if (bb < t->numOfTCOs())
|
||||
{
|
||||
max_length = qMax(max_length, t->getTCO( _bb )->length());
|
||||
maxLength = qMax(maxLength, t->getTCO(bb)->length());
|
||||
}
|
||||
}
|
||||
|
||||
return max_length.nextFullBar();
|
||||
return maxLength.nextFullBar();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,35 +112,35 @@ bar_t BBTrackContainer::lengthOfBB( int _bb ) const
|
||||
|
||||
int BBTrackContainer::numOfBBs() const
|
||||
{
|
||||
return Engine::getSong()->countTracks( Track::BBTrack );
|
||||
return Engine::getSong()->countTracks(Track::BBTrack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void BBTrackContainer::removeBB( int _bb )
|
||||
void BBTrackContainer::removeBB(int bb)
|
||||
{
|
||||
TrackList tl = tracks();
|
||||
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
|
||||
for (Track * t : tl)
|
||||
{
|
||||
delete ( *it )->getTCO( _bb );
|
||||
( *it )->removeBar( _bb * DefaultTicksPerBar );
|
||||
delete t->getTCO(bb);
|
||||
t->removeBar(bb * DefaultTicksPerBar);
|
||||
}
|
||||
if( _bb <= currentBB() )
|
||||
if (bb <= currentBB())
|
||||
{
|
||||
setCurrentBB( qMax( currentBB() - 1, 0 ) );
|
||||
setCurrentBB(qMax(currentBB() - 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void BBTrackContainer::swapBB( int _bb1, int _bb2 )
|
||||
void BBTrackContainer::swapBB(int bb1, int bb2)
|
||||
{
|
||||
TrackList tl = tracks();
|
||||
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
|
||||
for (Track * t : tl)
|
||||
{
|
||||
( *it )->swapPositionOfTCOs( _bb1, _bb2 );
|
||||
t->swapPositionOfTCOs(bb1, bb2);
|
||||
}
|
||||
updateComboBox();
|
||||
}
|
||||
@@ -148,11 +148,10 @@ void BBTrackContainer::swapBB( int _bb1, int _bb2 )
|
||||
|
||||
|
||||
|
||||
void BBTrackContainer::updateBBTrack( TrackContentObject * _tco )
|
||||
void BBTrackContainer::updateBBTrack(TrackContentObject * tco)
|
||||
{
|
||||
BBTrack * t = BBTrack::findBBTrack( _tco->startPosition() /
|
||||
DefaultTicksPerBar );
|
||||
if( t != NULL )
|
||||
BBTrack * t = BBTrack::findBBTrack(tco->startPosition() / DefaultTicksPerBar);
|
||||
if (t != NULL)
|
||||
{
|
||||
t->dataChanged();
|
||||
}
|
||||
@@ -164,11 +163,11 @@ void BBTrackContainer::updateBBTrack( TrackContentObject * _tco )
|
||||
void BBTrackContainer::fixIncorrectPositions()
|
||||
{
|
||||
TrackList tl = tracks();
|
||||
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
|
||||
for (Track * t : tl)
|
||||
{
|
||||
for( int i = 0; i < numOfBBs(); ++i )
|
||||
for (int i = 0; i < numOfBBs(); ++i)
|
||||
{
|
||||
( *it )->getTCO( i )->movePosition( MidiTime( i, 0 ) );
|
||||
t->getTCO(i)->movePosition(TimePos(i, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +177,7 @@ void BBTrackContainer::fixIncorrectPositions()
|
||||
|
||||
void BBTrackContainer::play()
|
||||
{
|
||||
if( Engine::getSong()->playMode() != Song::Mode_PlayBB )
|
||||
if (Engine::getSong()->playMode() != Song::Mode_PlayBB)
|
||||
{
|
||||
Engine::getSong()->playBB();
|
||||
}
|
||||
@@ -201,16 +200,16 @@ void BBTrackContainer::stop()
|
||||
|
||||
void BBTrackContainer::updateComboBox()
|
||||
{
|
||||
const int cur_bb = currentBB();
|
||||
const int curBB = currentBB();
|
||||
|
||||
m_bbComboBoxModel.clear();
|
||||
|
||||
for( int i = 0; i < numOfBBs(); ++i )
|
||||
for (int i = 0; i < numOfBBs(); ++i)
|
||||
{
|
||||
BBTrack * bbt = BBTrack::findBBTrack( i );
|
||||
m_bbComboBoxModel.addItem( bbt->name() );
|
||||
BBTrack * bbt = BBTrack::findBBTrack(i);
|
||||
m_bbComboBoxModel.addItem(bbt->name());
|
||||
}
|
||||
setCurrentBB( cur_bb );
|
||||
setCurrentBB(curBB);
|
||||
}
|
||||
|
||||
|
||||
@@ -218,14 +217,13 @@ void BBTrackContainer::updateComboBox()
|
||||
|
||||
void BBTrackContainer::currentBBChanged()
|
||||
{
|
||||
// now update all track-labels (the current one has to become white,
|
||||
// the others gray)
|
||||
// now update all track-labels (the current one has to become white, the others gray)
|
||||
TrackList tl = Engine::getSong()->tracks();
|
||||
for( TrackList::iterator it = tl.begin(); it != tl.end(); ++it )
|
||||
for (Track * t : tl)
|
||||
{
|
||||
if( ( *it )->type() == Track::BBTrack )
|
||||
if (t->type() == Track::BBTrack)
|
||||
{
|
||||
( *it )->dataChanged();
|
||||
t->dataChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,27 +231,27 @@ void BBTrackContainer::currentBBChanged()
|
||||
|
||||
|
||||
|
||||
void BBTrackContainer::createTCOsForBB( int _bb )
|
||||
void BBTrackContainer::createTCOsForBB(int bb)
|
||||
{
|
||||
TrackList tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
for (Track * t : tl)
|
||||
{
|
||||
tl[i]->createTCOsForBB( _bb );
|
||||
t->createTCOsForBB(bb);
|
||||
}
|
||||
}
|
||||
|
||||
AutomatedValueMap BBTrackContainer::automatedValuesAt(MidiTime time, int tcoNum) const
|
||||
AutomatedValueMap BBTrackContainer::automatedValuesAt(TimePos time, int tcoNum) const
|
||||
{
|
||||
Q_ASSERT(tcoNum >= 0);
|
||||
Q_ASSERT(time.getTicks() >= 0);
|
||||
|
||||
auto length_bars = lengthOfBB(tcoNum);
|
||||
auto length_ticks = length_bars * MidiTime::ticksPerBar();
|
||||
if (time > length_ticks)
|
||||
auto lengthBars = lengthOfBB(tcoNum);
|
||||
auto lengthTicks = lengthBars * TimePos::ticksPerBar();
|
||||
if (time > lengthTicks)
|
||||
{
|
||||
time = length_ticks;
|
||||
time = lengthTicks;
|
||||
}
|
||||
|
||||
return TrackContainer::automatedValuesAt(time + (MidiTime::ticksPerBar() * tcoNum), tcoNum);
|
||||
return TrackContainer::automatedValuesAt(time + (TimePos::ticksPerBar() * tcoNum), tcoNum);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,9 +67,11 @@ set(LMMS_SRCS
|
||||
core/SerializingObject.cpp
|
||||
core/Song.cpp
|
||||
core/TempoSyncKnobModel.cpp
|
||||
core/TimePos.cpp
|
||||
core/ToolPlugin.cpp
|
||||
core/Track.cpp
|
||||
core/TrackContainer.cpp
|
||||
core/TrackContentObject.cpp
|
||||
core/ValueBuffer.cpp
|
||||
core/VstSyncController.cpp
|
||||
core/StepRecorder.cpp
|
||||
@@ -98,6 +100,7 @@ set(LMMS_SRCS
|
||||
core/lv2/Lv2Ports.cpp
|
||||
core/lv2/Lv2Proc.cpp
|
||||
core/lv2/Lv2Manager.cpp
|
||||
core/lv2/Lv2Options.cpp
|
||||
core/lv2/Lv2SubPluginFeatures.cpp
|
||||
core/lv2/Lv2UridCache.cpp
|
||||
core/lv2/Lv2UridMap.cpp
|
||||
@@ -112,7 +115,6 @@ set(LMMS_SRCS
|
||||
core/midi/MidiSndio.cpp
|
||||
core/midi/MidiApple.cpp
|
||||
core/midi/MidiPort.cpp
|
||||
core/midi/MidiTime.cpp
|
||||
core/midi/MidiWinMM.cpp
|
||||
|
||||
PARENT_SCOPE
|
||||
|
||||
@@ -528,17 +528,16 @@ void ConfigManager::loadConfigFile(const QString & configFile)
|
||||
{
|
||||
#if defined(LMMS_BUILD_WIN32)
|
||||
m_stkDir = m_dataDir + "stk/rawwaves/";
|
||||
#elif defined(LMMS_BUILD_APPLE)
|
||||
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
|
||||
#else
|
||||
if ( qApp->applicationDirPath().startsWith("/tmp/") )
|
||||
// Look for bundled raw waves first
|
||||
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
|
||||
// Try system installations if not exists
|
||||
if (!QDir(m_stkDir).exists())
|
||||
{
|
||||
// Assume AppImage bundle
|
||||
m_stkDir = qApp->applicationDirPath() + "/../share/stk/rawwaves/";
|
||||
m_stkDir = "/usr/local/share/stk/rawwaves/";
|
||||
}
|
||||
else
|
||||
if (!QDir(m_stkDir).exists())
|
||||
{
|
||||
// Fallback to system provided location
|
||||
m_stkDir = "/usr/share/stk/rawwaves/";
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,6 @@ Lv2Manager * LmmsCore::s_lv2Manager = nullptr;
|
||||
#endif
|
||||
Ladspa2LMMS * LmmsCore::s_ladspaManager = NULL;
|
||||
void* LmmsCore::s_dndPluginKey = nullptr;
|
||||
DummyTrackContainer * LmmsCore::s_dummyTC = NULL;
|
||||
|
||||
|
||||
|
||||
@@ -79,7 +78,6 @@ void LmmsCore::init( bool renderOnly )
|
||||
s_mixer->initDevices();
|
||||
|
||||
PresetPreviewPlayHandle::init();
|
||||
s_dummyTC = new DummyTrackContainer;
|
||||
|
||||
emit engine->initProgress(tr("Launching mixer threads"));
|
||||
s_mixer->startProcessing();
|
||||
@@ -98,7 +96,6 @@ void LmmsCore::destroy()
|
||||
s_song->clearProject();
|
||||
|
||||
deleteHelper( &s_bbTrackContainer );
|
||||
deleteHelper( &s_dummyTC );
|
||||
|
||||
deleteHelper( &s_fxMixer );
|
||||
deleteHelper( &s_mixer );
|
||||
@@ -116,6 +113,18 @@ void LmmsCore::destroy()
|
||||
delete ConfigManager::inst();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool LmmsCore::ignorePluginBlacklist()
|
||||
{
|
||||
const char* envVar = getenv("LMMS_IGNORE_BLACKLIST");
|
||||
return (envVar && *envVar);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float LmmsCore::framesPerTick(sample_rate_t sampleRate)
|
||||
{
|
||||
return sampleRate * 60.0f * 4 /
|
||||
|
||||
@@ -506,7 +506,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
|
||||
NotePlayHandleManager::acquire( _n->instrumentTrack(),
|
||||
frames_processed,
|
||||
gated_frames,
|
||||
Note( MidiTime( 0 ), MidiTime( 0 ), sub_note_key, _n->getVolume(),
|
||||
Note( TimePos( 0 ), TimePos( 0 ), sub_note_key, _n->getVolume(),
|
||||
_n->getPanning(), _n->detuning() ),
|
||||
_n, -1, NotePlayHandle::OriginArpeggio )
|
||||
);
|
||||
|
||||
@@ -361,7 +361,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
|
||||
// Stop crash with metronome if empty project
|
||||
Engine::getSong()->countTracks() )
|
||||
{
|
||||
tick_t ticksPerBar = MidiTime::ticksPerBar();
|
||||
tick_t ticksPerBar = TimePos::ticksPerBar();
|
||||
if ( p.getTicks() % ( ticksPerBar / 1 ) == 0 )
|
||||
{
|
||||
addPlayHandle( new SamplePlayHandle( "misc/metronome02.ogg" ) );
|
||||
@@ -600,21 +600,6 @@ void Mixer::doSetAudioDevice( AudioDevice * _dev )
|
||||
|
||||
|
||||
|
||||
void Mixer::setAudioDevice( AudioDevice * _dev,
|
||||
bool startNow )
|
||||
{
|
||||
stopProcessing();
|
||||
|
||||
doSetAudioDevice( _dev );
|
||||
|
||||
emit sampleRateChanged();
|
||||
|
||||
if (startNow) {startProcessing();}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Mixer::setAudioDevice(AudioDevice * _dev,
|
||||
const struct qualitySettings & _qs,
|
||||
bool _needs_fifo,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "DetuningHelper.h"
|
||||
|
||||
|
||||
Note::Note( const MidiTime & length, const MidiTime & pos,
|
||||
Note::Note( const TimePos & length, const TimePos & pos,
|
||||
int key, volume_t volume, panning_t panning,
|
||||
DetuningHelper * detuning ) :
|
||||
m_selected( false ),
|
||||
@@ -93,7 +93,7 @@ Note::~Note()
|
||||
|
||||
|
||||
|
||||
void Note::setLength( const MidiTime & length )
|
||||
void Note::setLength( const TimePos & length )
|
||||
{
|
||||
m_length = length;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ void Note::setLength( const MidiTime & length )
|
||||
|
||||
|
||||
|
||||
void Note::setPos( const MidiTime & pos )
|
||||
void Note::setPos( const TimePos & pos )
|
||||
{
|
||||
m_pos = pos;
|
||||
}
|
||||
@@ -136,7 +136,7 @@ void Note::setPanning( panning_t panning )
|
||||
|
||||
|
||||
|
||||
MidiTime Note::quantized( const MidiTime & m, const int qGrid )
|
||||
TimePos Note::quantized( const TimePos & m, const int qGrid )
|
||||
{
|
||||
float p = ( (float) m / qGrid );
|
||||
if( p - floorf( p ) < 0.5f )
|
||||
|
||||
@@ -211,7 +211,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer )
|
||||
// send MidiNoteOn event
|
||||
m_instrumentTrack->processOutEvent(
|
||||
MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ),
|
||||
MidiTime::fromFrames( offset(), Engine::framesPerTick() ),
|
||||
TimePos::fromFrames( offset(), Engine::framesPerTick() ),
|
||||
offset() );
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s )
|
||||
// send MidiNoteOff event
|
||||
m_instrumentTrack->processOutEvent(
|
||||
MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ),
|
||||
MidiTime::fromFrames( _s, Engine::framesPerTick() ),
|
||||
TimePos::fromFrames( _s, Engine::framesPerTick() ),
|
||||
_s );
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s )
|
||||
{
|
||||
if( m_origin == OriginMidiInput )
|
||||
{
|
||||
setLength( MidiTime( static_cast<f_cnt_t>( totalFramesPlayed() / Engine::framesPerTick() ) ) );
|
||||
setLength( TimePos( static_cast<f_cnt_t>( totalFramesPlayed() / Engine::framesPerTick() ) ) );
|
||||
m_instrumentTrack->midiNoteOff( *this );
|
||||
}
|
||||
}
|
||||
@@ -519,7 +519,7 @@ void NotePlayHandle::updateFrequency()
|
||||
|
||||
|
||||
|
||||
void NotePlayHandle::processMidiTime( const MidiTime& time )
|
||||
void NotePlayHandle::processTimePos( const TimePos& time )
|
||||
{
|
||||
if( detuning() && time >= songGlobalParentOffset()+pos() )
|
||||
{
|
||||
@@ -623,3 +623,8 @@ void NotePlayHandleManager::extend( int c )
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
void NotePlayHandleManager::free()
|
||||
{
|
||||
MM_FREE(s_available);
|
||||
}
|
||||
|
||||
@@ -50,10 +50,22 @@ const char *PluginIssue::msgFor(const PluginIssueType &it)
|
||||
return "port is missing min value";
|
||||
case portHasNoMax:
|
||||
return "port is missing max value";
|
||||
case minGreaterMax:
|
||||
return "port minimum is greater than maximum";
|
||||
case defaultValueNotInRange:
|
||||
return "default value is not in range [min, max]";
|
||||
case logScaleMinMissing:
|
||||
return "logscale requires minimum value";
|
||||
case logScaleMaxMissing:
|
||||
return "logscale requires maximum value";
|
||||
case logScaleMinMaxDifferentSigns:
|
||||
return "logscale with min < 0 < max";
|
||||
case featureNotSupported:
|
||||
return "required feature not supported";
|
||||
case badPortType:
|
||||
return "unsupported port type";
|
||||
case blacklisted:
|
||||
return "blacklisted plugin";
|
||||
case noIssue:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -63,6 +75,24 @@ const char *PluginIssue::msgFor(const PluginIssueType &it)
|
||||
|
||||
|
||||
|
||||
bool PluginIssue::operator==(const PluginIssue &other) const
|
||||
{
|
||||
return (m_issueType == other.m_issueType) && (m_info == other.m_info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool PluginIssue::operator<(const PluginIssue &other) const
|
||||
{
|
||||
return (m_issueType != other.m_issueType)
|
||||
? m_issueType < other.m_issueType
|
||||
: m_info < other.m_info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QDebug operator<<(QDebug stream, const PluginIssue &iss)
|
||||
{
|
||||
stream << PluginIssue::msgFor(iss.m_issueType);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -73,7 +73,7 @@ void SampleRecordHandle::play( sampleFrame * /*_working_buffer*/ )
|
||||
writeBuffer( recbuf, frames );
|
||||
m_framesRecorded += frames;
|
||||
|
||||
MidiTime len = (tick_t)( m_framesRecorded / Engine::framesPerTick() );
|
||||
TimePos len = (tick_t)( m_framesRecorded / Engine::framesPerTick() );
|
||||
if( len > m_minLength )
|
||||
{
|
||||
// m_tco->changeLength( len );
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
#include "AutomationTrack.h"
|
||||
@@ -46,6 +48,8 @@
|
||||
#include "FxMixerView.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "ExportFilter.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "NotePlayHandle.h"
|
||||
#include "Pattern.h"
|
||||
#include "PianoRoll.h"
|
||||
#include "ProjectJournal.h"
|
||||
@@ -55,7 +59,7 @@
|
||||
#include "PeakController.h"
|
||||
|
||||
|
||||
tick_t MidiTime::s_ticksPerBar = DefaultTicksPerBar;
|
||||
tick_t TimePos::s_ticksPerBar = DefaultTicksPerBar;
|
||||
|
||||
|
||||
|
||||
@@ -164,7 +168,7 @@ void Song::setTempo()
|
||||
|
||||
void Song::setTimeSignature()
|
||||
{
|
||||
MidiTime::setTicksPerBar( ticksPerBar() );
|
||||
TimePos::setTicksPerBar( ticksPerBar() );
|
||||
emit timeSignatureChanged( m_oldTicksPerBar, ticksPerBar() );
|
||||
emit dataChanged();
|
||||
m_oldTicksPerBar = ticksPerBar();
|
||||
@@ -191,231 +195,164 @@ void Song::savePos()
|
||||
|
||||
void Song::processNextBuffer()
|
||||
{
|
||||
m_vstSyncController.setPlaybackJumped( false );
|
||||
m_vstSyncController.setPlaybackJumped(false);
|
||||
|
||||
// if not playing, nothing to do
|
||||
if( m_playing == false )
|
||||
// If nothing is playing, there is nothing to do
|
||||
if (!m_playing) { return; }
|
||||
|
||||
// At the beginning of the song, we have to reset the LFOs
|
||||
if (m_playMode == Mode_PlaySong && getPlayPos() == 0)
|
||||
{
|
||||
return;
|
||||
EnvelopeAndLfoParameters::instances()->reset();
|
||||
}
|
||||
|
||||
TrackList trackList;
|
||||
int tcoNum = -1; // track content object number
|
||||
int clipNum = -1; // The number of the clip that will be played
|
||||
|
||||
// determine the list of tracks to play and the track content object
|
||||
// (TCO) number
|
||||
switch( m_playMode )
|
||||
// Determine the list of tracks to play and the clip number
|
||||
switch (m_playMode)
|
||||
{
|
||||
case Mode_PlaySong:
|
||||
trackList = tracks();
|
||||
// at song-start we have to reset the LFOs
|
||||
if( m_playPos[Mode_PlaySong] == 0 )
|
||||
{
|
||||
EnvelopeAndLfoParameters::instances()->reset();
|
||||
}
|
||||
break;
|
||||
|
||||
case Mode_PlayBB:
|
||||
if( Engine::getBBTrackContainer()->numOfBBs() > 0 )
|
||||
if (Engine::getBBTrackContainer()->numOfBBs() > 0)
|
||||
{
|
||||
tcoNum = Engine::getBBTrackContainer()->
|
||||
currentBB();
|
||||
trackList.push_back( BBTrack::findBBTrack(
|
||||
tcoNum ) );
|
||||
clipNum = Engine::getBBTrackContainer()->currentBB();
|
||||
trackList.push_back(BBTrack::findBBTrack(clipNum));
|
||||
}
|
||||
break;
|
||||
|
||||
case Mode_PlayPattern:
|
||||
if( m_patternToPlay != NULL )
|
||||
if (m_patternToPlay)
|
||||
{
|
||||
tcoNum = m_patternToPlay->getTrack()->
|
||||
getTCONum( m_patternToPlay );
|
||||
trackList.push_back(
|
||||
m_patternToPlay->getTrack() );
|
||||
clipNum = m_patternToPlay->getTrack()->getTCONum(m_patternToPlay);
|
||||
trackList.push_back(m_patternToPlay->getTrack());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// if we have no tracks to play, nothing to do
|
||||
if( trackList.empty() == true )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// If we have no tracks to play, there is nothing to do
|
||||
if (trackList.empty()) { return; }
|
||||
|
||||
// check for looping-mode and act if necessary
|
||||
TimeLineWidget * tl = m_playPos[m_playMode].m_timeLine;
|
||||
bool checkLoop =
|
||||
tl != NULL && m_exporting == false && tl->loopPointsEnabled();
|
||||
|
||||
if( checkLoop )
|
||||
// If the playback position is outside of the range [begin, end), move it to
|
||||
// begin and inform interested parties.
|
||||
// Returns true if the playback position was moved, else false.
|
||||
const auto enforceLoop = [this](const TimePos& begin, const TimePos& end)
|
||||
{
|
||||
// if looping-mode is enabled and we are outside of the looping
|
||||
// range, go to the beginning of the range
|
||||
if( m_playPos[m_playMode] < tl->loopBegin() ||
|
||||
m_playPos[m_playMode] >= tl->loopEnd() )
|
||||
if (getPlayPos() < begin || getPlayPos() >= end)
|
||||
{
|
||||
setToTime(tl->loopBegin());
|
||||
m_playPos[m_playMode].setTicks(
|
||||
tl->loopBegin().getTicks() );
|
||||
|
||||
m_vstSyncController.setPlaybackJumped( true );
|
||||
|
||||
setToTime(begin);
|
||||
m_vstSyncController.setPlaybackJumped(true);
|
||||
emit updateSampleTracks();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto timeline = getPlayPos().m_timeLine;
|
||||
const auto loopEnabled = !m_exporting && timeline && timeline->loopPointsEnabled();
|
||||
|
||||
// Ensure playback begins within the loop if it is enabled
|
||||
if (loopEnabled) { enforceLoop(timeline->loopBegin(), timeline->loopEnd()); }
|
||||
|
||||
// Inform VST plugins if the user moved the play head
|
||||
if (getPlayPos().jumped())
|
||||
{
|
||||
m_vstSyncController.setPlaybackJumped(true);
|
||||
getPlayPos().setJumped(false);
|
||||
}
|
||||
|
||||
if( m_playPos[m_playMode].jumped() )
|
||||
const auto framesPerTick = Engine::framesPerTick();
|
||||
const auto framesPerPeriod = Engine::mixer()->framesPerPeriod();
|
||||
|
||||
f_cnt_t frameOffsetInPeriod = 0;
|
||||
|
||||
while (frameOffsetInPeriod < framesPerPeriod)
|
||||
{
|
||||
m_vstSyncController.setPlaybackJumped( true );
|
||||
m_playPos[m_playMode].setJumped( false );
|
||||
}
|
||||
auto frameOffsetInTick = getPlayPos().currentFrame();
|
||||
|
||||
f_cnt_t framesPlayed = 0;
|
||||
const float framesPerTick = Engine::framesPerTick();
|
||||
|
||||
while( framesPlayed < Engine::mixer()->framesPerPeriod() )
|
||||
{
|
||||
m_vstSyncController.update();
|
||||
|
||||
float currentFrame = m_playPos[m_playMode].currentFrame();
|
||||
// did we play a tick?
|
||||
if( currentFrame >= framesPerTick )
|
||||
// If a whole tick has elapsed, update the frame and tick count, and check any loops
|
||||
if (frameOffsetInTick >= framesPerTick)
|
||||
{
|
||||
int ticks = m_playPos[m_playMode].getTicks() +
|
||||
( int )( currentFrame / framesPerTick );
|
||||
// Transfer any whole ticks from the frame count to the tick count
|
||||
const auto elapsedTicks = static_cast<int>(frameOffsetInTick / framesPerTick);
|
||||
getPlayPos().setTicks(getPlayPos().getTicks() + elapsedTicks);
|
||||
frameOffsetInTick -= elapsedTicks * framesPerTick;
|
||||
getPlayPos().setCurrentFrame(frameOffsetInTick);
|
||||
|
||||
// did we play a whole bar?
|
||||
if( ticks >= MidiTime::ticksPerBar() )
|
||||
// If we are playing a BB track, or a pattern with no loop enabled,
|
||||
// loop back to the beginning when we reach the end
|
||||
if (m_playMode == Mode_PlayBB)
|
||||
{
|
||||
// per default we just continue playing even if
|
||||
// there's no more stuff to play
|
||||
// (song-play-mode)
|
||||
int maxBar = m_playPos[m_playMode].getBar()
|
||||
+ 2;
|
||||
|
||||
// then decide whether to go over to next bar
|
||||
// or to loop back to first bar
|
||||
if( m_playMode == Mode_PlayBB )
|
||||
{
|
||||
maxBar = Engine::getBBTrackContainer()
|
||||
->lengthOfCurrentBB();
|
||||
}
|
||||
else if( m_playMode == Mode_PlayPattern &&
|
||||
m_loopPattern == true &&
|
||||
tl != NULL &&
|
||||
tl->loopPointsEnabled() == false )
|
||||
{
|
||||
maxBar = m_patternToPlay->length()
|
||||
.getBar();
|
||||
}
|
||||
|
||||
// end of played object reached?
|
||||
if( m_playPos[m_playMode].getBar() + 1
|
||||
>= maxBar )
|
||||
{
|
||||
// then start from beginning and keep
|
||||
// offset
|
||||
ticks %= ( maxBar * MidiTime::ticksPerBar() );
|
||||
|
||||
// wrap milli second counter
|
||||
setToTimeByTicks(ticks);
|
||||
|
||||
m_vstSyncController.setPlaybackJumped( true );
|
||||
}
|
||||
enforceLoop(TimePos{0}, TimePos{Engine::getBBTrackContainer()->lengthOfCurrentBB(), 0});
|
||||
}
|
||||
else if (m_playMode == Mode_PlayPattern && m_loopPattern && !loopEnabled)
|
||||
{
|
||||
enforceLoop(TimePos{0}, m_patternToPlay->length());
|
||||
}
|
||||
m_playPos[m_playMode].setTicks( ticks );
|
||||
|
||||
if (checkLoop || m_loopRenderRemaining > 1)
|
||||
// Handle loop points, and inform VST plugins of the loop status
|
||||
if (loopEnabled || (m_loopRenderRemaining > 1 && getPlayPos() >= timeline->loopBegin()))
|
||||
{
|
||||
m_vstSyncController.startCycle(
|
||||
tl->loopBegin().getTicks(), tl->loopEnd().getTicks() );
|
||||
timeline->loopBegin().getTicks(), timeline->loopEnd().getTicks());
|
||||
|
||||
// if looping-mode is enabled and we have got
|
||||
// past the looping range, return to the
|
||||
// beginning of the range
|
||||
if( m_playPos[m_playMode] >= tl->loopEnd() )
|
||||
// Loop if necessary, and decrement the remaining loops if we did
|
||||
if (enforceLoop(timeline->loopBegin(), timeline->loopEnd())
|
||||
&& m_loopRenderRemaining > 1)
|
||||
{
|
||||
if (m_loopRenderRemaining > 1)
|
||||
m_loopRenderRemaining--;
|
||||
ticks = tl->loopBegin().getTicks();
|
||||
m_playPos[m_playMode].setTicks( ticks );
|
||||
setToTime(tl->loopBegin());
|
||||
|
||||
m_vstSyncController.setPlaybackJumped( true );
|
||||
|
||||
emit updateSampleTracks();
|
||||
m_loopRenderRemaining--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vstSyncController.stopCycle();
|
||||
}
|
||||
|
||||
currentFrame = fmodf( currentFrame, framesPerTick );
|
||||
m_playPos[m_playMode].setCurrentFrame( currentFrame );
|
||||
}
|
||||
|
||||
if( framesPlayed == 0 )
|
||||
const f_cnt_t framesUntilNextPeriod = framesPerPeriod - frameOffsetInPeriod;
|
||||
const f_cnt_t framesUntilNextTick = static_cast<f_cnt_t>(std::ceil(framesPerTick - frameOffsetInTick));
|
||||
|
||||
// We want to proceed to the next buffer or tick, whichever is closer
|
||||
const auto framesToPlay = std::min(framesUntilNextPeriod, framesUntilNextTick);
|
||||
|
||||
if (frameOffsetInPeriod == 0)
|
||||
{
|
||||
// update VST sync position after we've corrected frame/
|
||||
// tick count but before actually playing any frames
|
||||
m_vstSyncController.setAbsolutePosition(
|
||||
m_playPos[m_playMode].getTicks()
|
||||
+ m_playPos[m_playMode].currentFrame()
|
||||
/ (double) framesPerTick );
|
||||
// First frame of buffer: update VST sync position.
|
||||
// This must be done after we've corrected the frame/tick count,
|
||||
// but before actually playing any frames.
|
||||
m_vstSyncController.setAbsolutePosition(getPlayPos().getTicks()
|
||||
+ getPlayPos().currentFrame() / static_cast<double>(framesPerTick));
|
||||
m_vstSyncController.update();
|
||||
}
|
||||
|
||||
f_cnt_t framesToPlay =
|
||||
Engine::mixer()->framesPerPeriod() - framesPlayed;
|
||||
|
||||
f_cnt_t framesLeft = ( f_cnt_t )framesPerTick -
|
||||
( f_cnt_t )currentFrame;
|
||||
// skip last frame fraction
|
||||
if( framesLeft == 0 )
|
||||
if (static_cast<f_cnt_t>(frameOffsetInTick) == 0)
|
||||
{
|
||||
++framesPlayed;
|
||||
m_playPos[m_playMode].setCurrentFrame( currentFrame
|
||||
+ 1.0f );
|
||||
continue;
|
||||
}
|
||||
// do we have samples left in this tick but these are less
|
||||
// than samples we have to play?
|
||||
if( framesLeft < framesToPlay )
|
||||
{
|
||||
// then set framesToPlay to remaining samples, the
|
||||
// rest will be played in next loop
|
||||
framesToPlay = framesLeft;
|
||||
}
|
||||
|
||||
if( ( f_cnt_t ) currentFrame == 0 )
|
||||
{
|
||||
processAutomations(trackList, m_playPos[m_playMode], framesToPlay);
|
||||
|
||||
// loop through all tracks and play them
|
||||
for( int i = 0; i < trackList.size(); ++i )
|
||||
// First frame of tick: process automation and play tracks
|
||||
processAutomations(trackList, getPlayPos(), framesToPlay);
|
||||
for (const auto track : trackList)
|
||||
{
|
||||
trackList[i]->play( m_playPos[m_playMode],
|
||||
framesToPlay,
|
||||
framesPlayed, tcoNum );
|
||||
track->play(getPlayPos(), framesToPlay, frameOffsetInPeriod, clipNum);
|
||||
}
|
||||
}
|
||||
|
||||
// update frame-counters
|
||||
framesPlayed += framesToPlay;
|
||||
m_playPos[m_playMode].setCurrentFrame( framesToPlay +
|
||||
currentFrame );
|
||||
m_elapsedMilliSeconds[m_playMode] += MidiTime::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo());
|
||||
// Update frame counters
|
||||
frameOffsetInPeriod += framesToPlay;
|
||||
frameOffsetInTick += framesToPlay;
|
||||
getPlayPos().setCurrentFrame(frameOffsetInTick);
|
||||
m_elapsedMilliSeconds[m_playMode] += TimePos::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo());
|
||||
m_elapsedBars = m_playPos[Mode_PlaySong].getBar();
|
||||
m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerBar() ) / 48;
|
||||
m_elapsedTicks = (m_playPos[Mode_PlaySong].getTicks() % ticksPerBar()) / 48;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Song::processAutomations(const TrackList &tracklist, MidiTime timeStart, fpp_t)
|
||||
void Song::processAutomations(const TrackList &tracklist, TimePos timeStart, fpp_t)
|
||||
{
|
||||
AutomatedValueMap values;
|
||||
|
||||
@@ -457,7 +394,7 @@ void Song::processAutomations(const TrackList &tracklist, MidiTime timeStart, fp
|
||||
for (TrackContentObject* tco : tcos)
|
||||
{
|
||||
auto p = dynamic_cast<AutomationPattern *>(tco);
|
||||
MidiTime relTime = timeStart - p->startPosition();
|
||||
TimePos relTime = timeStart - p->startPosition();
|
||||
if (p->isRecording() && relTime >= 0 && relTime < p->length())
|
||||
{
|
||||
const AutomatableModel* recordedModel = p->firstObject();
|
||||
@@ -493,7 +430,7 @@ bool Song::isExportDone() const
|
||||
|
||||
int Song::getExportProgress() const
|
||||
{
|
||||
MidiTime pos = m_playPos[m_playMode];
|
||||
TimePos pos = m_playPos[m_playMode];
|
||||
|
||||
if (pos >= m_exportSongEnd)
|
||||
{
|
||||
@@ -637,7 +574,7 @@ void Song::setPlayPos( tick_t ticks, PlayModes playMode )
|
||||
{
|
||||
tick_t ticksFromPlayMode = m_playPos[playMode].getTicks();
|
||||
m_elapsedTicks += ticksFromPlayMode - ticks;
|
||||
m_elapsedMilliSeconds[playMode] += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() );
|
||||
m_elapsedMilliSeconds[playMode] += TimePos::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() );
|
||||
m_playPos[playMode].setTicks( ticks );
|
||||
m_playPos[playMode].setCurrentFrame( 0.0f );
|
||||
m_playPos[playMode].setJumped( true );
|
||||
@@ -755,7 +692,7 @@ void Song::startExport()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_exportSongEnd = MidiTime(m_length, 0);
|
||||
m_exportSongEnd = TimePos(m_length, 0);
|
||||
|
||||
// Handle potentially ridiculous loop points gracefully.
|
||||
if (m_loopRenderCount > 1 && m_playPos[Mode_PlaySong].m_timeLine->loopEnd() > m_exportSongEnd)
|
||||
@@ -764,18 +701,18 @@ void Song::startExport()
|
||||
}
|
||||
|
||||
if (!m_exportLoop)
|
||||
m_exportSongEnd += MidiTime(1,0);
|
||||
m_exportSongEnd += TimePos(1,0);
|
||||
|
||||
m_exportSongBegin = MidiTime(0,0);
|
||||
m_exportSongBegin = TimePos(0,0);
|
||||
// FIXME: remove this check once we load timeline in headless mode
|
||||
if (m_playPos[Mode_PlaySong].m_timeLine)
|
||||
{
|
||||
m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd &&
|
||||
m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ?
|
||||
m_playPos[Mode_PlaySong].m_timeLine->loopBegin() : MidiTime(0,0);
|
||||
m_playPos[Mode_PlaySong].m_timeLine->loopBegin() : TimePos(0,0);
|
||||
m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd &&
|
||||
m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ?
|
||||
m_playPos[Mode_PlaySong].m_timeLine->loopEnd() : MidiTime(0,0);
|
||||
m_playPos[Mode_PlaySong].m_timeLine->loopEnd() : TimePos(0,0);
|
||||
}
|
||||
|
||||
m_playPos[Mode_PlaySong].setTicks( 0 );
|
||||
@@ -871,7 +808,7 @@ AutomationPattern * Song::tempoAutomationPattern()
|
||||
}
|
||||
|
||||
|
||||
AutomatedValueMap Song::automatedValuesAt(MidiTime time, int tcoNum) const
|
||||
AutomatedValueMap Song::automatedValuesAt(TimePos time, int tcoNum) const
|
||||
{
|
||||
return TrackContainer::automatedValuesFromTracks(TrackList{m_globalAutomationTrack} << tracks(), time, tcoNum);
|
||||
}
|
||||
@@ -949,8 +886,6 @@ void Song::clearProject()
|
||||
Engine::projectJournal()->clearJournal();
|
||||
|
||||
Engine::projectJournal()->setJournalling( true );
|
||||
|
||||
InstrumentTrackView::cleanupWindowCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void StepRecorder::initialize()
|
||||
connect(&m_updateReleasedTimer, SIGNAL(timeout()), this, SLOT(removeNotesReleasedForTooLong()));
|
||||
}
|
||||
|
||||
void StepRecorder::start(const MidiTime& currentPosition, const MidiTime& stepLength)
|
||||
void StepRecorder::start(const TimePos& currentPosition, const TimePos& stepLength)
|
||||
{
|
||||
m_isRecording = true;
|
||||
|
||||
@@ -53,7 +53,7 @@ void StepRecorder::start(const MidiTime& currentPosition, const MidiTime& stepLe
|
||||
const int q = m_pianoRoll.quantization();
|
||||
const int curPosTicks = currentPosition.getTicks();
|
||||
const int QuantizedPosTicks = (curPosTicks / q) * q;
|
||||
const MidiTime& QuantizedPos = MidiTime(QuantizedPosTicks);
|
||||
const TimePos& QuantizedPos = TimePos(QuantizedPosTicks);
|
||||
|
||||
m_curStepStartPos = QuantizedPos;
|
||||
m_curStepLength = 0;
|
||||
@@ -154,7 +154,7 @@ bool StepRecorder::keyPressEvent(QKeyEvent* ke)
|
||||
return event_handled;
|
||||
}
|
||||
|
||||
void StepRecorder::setStepsLength(const MidiTime& newLength)
|
||||
void StepRecorder::setStepsLength(const TimePos& newLength)
|
||||
{
|
||||
if(m_isStepInProgress)
|
||||
{
|
||||
@@ -319,7 +319,7 @@ void StepRecorder::removeNotesReleasedForTooLong()
|
||||
}
|
||||
}
|
||||
|
||||
MidiTime StepRecorder::getCurStepEndPos()
|
||||
TimePos StepRecorder::getCurStepEndPos()
|
||||
{
|
||||
return m_curStepStartPos + m_curStepLength;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* MidiTime.cpp - Class that encapsulates the position of a note/event in terms of
|
||||
* TimePos.cpp - Class that encapsulates the position of a note/event in terms of
|
||||
* its bar, beat and tick.
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net
|
||||
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
#include "MeterModel.h"
|
||||
|
||||
@@ -53,17 +53,17 @@ int TimeSig::denominator() const
|
||||
|
||||
|
||||
|
||||
MidiTime::MidiTime( const bar_t bar, const tick_t ticks ) :
|
||||
TimePos::TimePos( const bar_t bar, const tick_t ticks ) :
|
||||
m_ticks( bar * s_ticksPerBar + ticks )
|
||||
{
|
||||
}
|
||||
|
||||
MidiTime::MidiTime( const tick_t ticks ) :
|
||||
TimePos::TimePos( const tick_t ticks ) :
|
||||
m_ticks( ticks )
|
||||
{
|
||||
}
|
||||
|
||||
MidiTime MidiTime::quantize(float bars) const
|
||||
TimePos TimePos::quantize(float bars) const
|
||||
{
|
||||
//The intervals we should snap to, our new position should be a factor of this
|
||||
int interval = s_ticksPerBar * bars;
|
||||
@@ -78,80 +78,80 @@ MidiTime MidiTime::quantize(float bars) const
|
||||
}
|
||||
|
||||
|
||||
MidiTime MidiTime::toAbsoluteBar() const
|
||||
TimePos TimePos::toAbsoluteBar() const
|
||||
{
|
||||
return getBar() * s_ticksPerBar;
|
||||
}
|
||||
|
||||
|
||||
MidiTime& MidiTime::operator+=( const MidiTime& time )
|
||||
TimePos& TimePos::operator+=( const TimePos& time )
|
||||
{
|
||||
m_ticks += time.m_ticks;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
MidiTime& MidiTime::operator-=( const MidiTime& time )
|
||||
TimePos& TimePos::operator-=( const TimePos& time )
|
||||
{
|
||||
m_ticks -= time.m_ticks;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bar_t MidiTime::getBar() const
|
||||
bar_t TimePos::getBar() const
|
||||
{
|
||||
return m_ticks / s_ticksPerBar;
|
||||
}
|
||||
|
||||
|
||||
bar_t MidiTime::nextFullBar() const
|
||||
bar_t TimePos::nextFullBar() const
|
||||
{
|
||||
return ( m_ticks + ( s_ticksPerBar - 1 ) ) / s_ticksPerBar;
|
||||
}
|
||||
|
||||
|
||||
void MidiTime::setTicks( tick_t ticks )
|
||||
void TimePos::setTicks( tick_t ticks )
|
||||
{
|
||||
m_ticks = ticks;
|
||||
}
|
||||
|
||||
|
||||
tick_t MidiTime::getTicks() const
|
||||
tick_t TimePos::getTicks() const
|
||||
{
|
||||
return m_ticks;
|
||||
}
|
||||
|
||||
|
||||
MidiTime::operator int() const
|
||||
TimePos::operator int() const
|
||||
{
|
||||
return m_ticks;
|
||||
}
|
||||
|
||||
|
||||
tick_t MidiTime::ticksPerBeat( const TimeSig &sig ) const
|
||||
tick_t TimePos::ticksPerBeat( const TimeSig &sig ) const
|
||||
{
|
||||
// (number of ticks per bar) divided by (number of beats per bar)
|
||||
return ticksPerBar(sig) / sig.numerator();
|
||||
}
|
||||
|
||||
|
||||
tick_t MidiTime::getTickWithinBar( const TimeSig &sig ) const
|
||||
tick_t TimePos::getTickWithinBar( const TimeSig &sig ) const
|
||||
{
|
||||
return m_ticks % ticksPerBar( sig );
|
||||
}
|
||||
|
||||
tick_t MidiTime::getBeatWithinBar( const TimeSig &sig ) const
|
||||
tick_t TimePos::getBeatWithinBar( const TimeSig &sig ) const
|
||||
{
|
||||
return getTickWithinBar( sig ) / ticksPerBeat( sig );
|
||||
}
|
||||
|
||||
tick_t MidiTime::getTickWithinBeat( const TimeSig &sig ) const
|
||||
tick_t TimePos::getTickWithinBeat( const TimeSig &sig ) const
|
||||
{
|
||||
return getTickWithinBar( sig ) % ticksPerBeat( sig );
|
||||
}
|
||||
|
||||
|
||||
f_cnt_t MidiTime::frames( const float framesPerTick ) const
|
||||
f_cnt_t TimePos::frames( const float framesPerTick ) const
|
||||
{
|
||||
if( m_ticks >= 0 )
|
||||
{
|
||||
@@ -160,53 +160,53 @@ f_cnt_t MidiTime::frames( const float framesPerTick ) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
double MidiTime::getTimeInMilliseconds( bpm_t beatsPerMinute ) const
|
||||
double TimePos::getTimeInMilliseconds( bpm_t beatsPerMinute ) const
|
||||
{
|
||||
return ticksToMilliseconds( getTicks(), beatsPerMinute );
|
||||
}
|
||||
|
||||
MidiTime MidiTime::fromFrames( const f_cnt_t frames, const float framesPerTick )
|
||||
TimePos TimePos::fromFrames( const f_cnt_t frames, const float framesPerTick )
|
||||
{
|
||||
return MidiTime( static_cast<int>( frames / framesPerTick ) );
|
||||
return TimePos( static_cast<int>( frames / framesPerTick ) );
|
||||
}
|
||||
|
||||
|
||||
tick_t MidiTime::ticksPerBar()
|
||||
tick_t TimePos::ticksPerBar()
|
||||
{
|
||||
return s_ticksPerBar;
|
||||
}
|
||||
|
||||
|
||||
tick_t MidiTime::ticksPerBar( const TimeSig &sig )
|
||||
tick_t TimePos::ticksPerBar( const TimeSig &sig )
|
||||
{
|
||||
return DefaultTicksPerBar * sig.numerator() / sig.denominator();
|
||||
}
|
||||
|
||||
|
||||
int MidiTime::stepsPerBar()
|
||||
int TimePos::stepsPerBar()
|
||||
{
|
||||
int steps = ticksPerBar() / DefaultBeatsPerBar;
|
||||
return qMax( 1, steps );
|
||||
}
|
||||
|
||||
|
||||
void MidiTime::setTicksPerBar( tick_t tpb )
|
||||
void TimePos::setTicksPerBar( tick_t tpb )
|
||||
{
|
||||
s_ticksPerBar = tpb;
|
||||
}
|
||||
|
||||
|
||||
MidiTime MidiTime::stepPosition( int step )
|
||||
TimePos TimePos::stepPosition( int step )
|
||||
{
|
||||
return step * ticksPerBar() / stepsPerBar();
|
||||
}
|
||||
|
||||
double MidiTime::ticksToMilliseconds( tick_t ticks, bpm_t beatsPerMinute )
|
||||
double TimePos::ticksToMilliseconds( tick_t ticks, bpm_t beatsPerMinute )
|
||||
{
|
||||
return MidiTime::ticksToMilliseconds( static_cast<double>(ticks), beatsPerMinute );
|
||||
return TimePos::ticksToMilliseconds( static_cast<double>(ticks), beatsPerMinute );
|
||||
}
|
||||
|
||||
double MidiTime::ticksToMilliseconds(double ticks, bpm_t beatsPerMinute)
|
||||
double TimePos::ticksToMilliseconds(double ticks, bpm_t beatsPerMinute)
|
||||
{
|
||||
// 60 * 1000 / 48 = 1250
|
||||
return ( ticks * 1250 ) / beatsPerMinute;
|
||||
2860
src/core/Track.cpp
2860
src/core/Track.cpp
File diff suppressed because it is too large
Load Diff
@@ -248,13 +248,13 @@ bool TrackContainer::isEmpty() const
|
||||
|
||||
|
||||
|
||||
AutomatedValueMap TrackContainer::automatedValuesAt(MidiTime time, int tcoNum) const
|
||||
AutomatedValueMap TrackContainer::automatedValuesAt(TimePos time, int tcoNum) const
|
||||
{
|
||||
return automatedValuesFromTracks(tracks(), time, tcoNum);
|
||||
}
|
||||
|
||||
|
||||
AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tracks, MidiTime time, int tcoNum)
|
||||
AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tracks, TimePos time, int tcoNum)
|
||||
{
|
||||
Track::tcoVector tcos;
|
||||
|
||||
@@ -295,7 +295,7 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra
|
||||
if (! p->hasAutomation()) {
|
||||
continue;
|
||||
}
|
||||
MidiTime relTime = time - p->startPosition();
|
||||
TimePos relTime = time - p->startPosition();
|
||||
if (! p->getAutoResize()) {
|
||||
relTime = qMin(relTime, p->length());
|
||||
}
|
||||
@@ -311,9 +311,9 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra
|
||||
auto bbIndex = dynamic_cast<class BBTrack*>(bb->getTrack())->index();
|
||||
auto bbContainer = Engine::getBBTrackContainer();
|
||||
|
||||
MidiTime bbTime = time - tco->startPosition();
|
||||
TimePos bbTime = time - tco->startPosition();
|
||||
bbTime = std::min(bbTime, tco->length());
|
||||
bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * MidiTime::ticksPerBar());
|
||||
bbTime = bbTime % (bbContainer->lengthOfBB(bbIndex) * TimePos::ticksPerBar());
|
||||
|
||||
auto bbValues = bbContainer->automatedValuesAt(bbTime, bbIndex);
|
||||
for (auto it=bbValues.begin(); it != bbValues.end(); it++)
|
||||
@@ -331,16 +331,3 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra
|
||||
return valueMap;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DummyTrackContainer::DummyTrackContainer() :
|
||||
TrackContainer(),
|
||||
m_dummyInstrumentTrack( NULL )
|
||||
{
|
||||
setJournalling( false );
|
||||
m_dummyInstrumentTrack = dynamic_cast<InstrumentTrack *>(
|
||||
Track::create( Track::InstrumentTrack,
|
||||
this ) );
|
||||
m_dummyInstrumentTrack->setJournalling( false );
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user