Merge branch 'master' into refac/memory

This commit is contained in:
Lukas W
2020-12-11 09:47:41 +01:00
566 changed files with 18836 additions and 29336 deletions

View File

@@ -71,7 +71,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget",
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
"ALSA (Advanced Linux Sound Architecture)" );
}

View File

@@ -115,7 +115,7 @@ protected:
const fpp_t _frames );
// resample given buffer from samplerate _src_sr to samplerate _dst_sr
void resample( const surroundSampleFrame * _src,
fpp_t resample( const surroundSampleFrame * _src,
const fpp_t _frames,
surroundSampleFrame * _dst,
const sample_rate_t _src_sr,

View File

@@ -48,7 +48,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "Dummy (no sound output)" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "Dummy (no sound output)" );
}

View File

@@ -34,6 +34,7 @@
#include "weak_libjack.h"
#endif
#include <atomic>
#include <QtCore/QVector>
#include <QtCore/QList>
#include <QtCore/QMap>
@@ -57,11 +58,12 @@ public:
// the jack callback is handled here, we call the midi client so that it can read
// it's midi data during the callback
AudioJack * addMidiClient(MidiJack *midiClient);
void removeMidiClient(void) { m_midiClient = nullptr; }
jack_client_t * jackClient() {return m_client;};
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget",
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
"JACK (JACK Audio Connection Kit)" );
}
@@ -106,9 +108,9 @@ private:
jack_client_t * m_client;
bool m_active;
bool m_stopped;
std::atomic<bool> m_stopped;
MidiJack *m_midiClient;
std::atomic<MidiJack *> m_midiClient;
QVector<jack_port_t *> m_outputPorts;
jack_default_audio_sample_t * * m_tempOutBufs;
surroundSampleFrame * m_outBuf;

View File

@@ -48,7 +48,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "OSS (Open Sound System)" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "OSS (Open Sound System)" );
}
static QString probeDevice();

View File

@@ -72,7 +72,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "PortAudio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PortAudio" );
}

View File

@@ -50,7 +50,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "PulseAudio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PulseAudio" );
}
static QString probeDevice();

View File

@@ -51,7 +51,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget",
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
"SDL (Simple DirectMedia Layer)" );
}

View File

@@ -49,7 +49,7 @@ public:
inline static QString name( void )
{
return QT_TRANSLATE_NOOP( "setupWidget", "sndio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "sndio" );
}
class setupWidget : public AudioDeviceSetupWidget

View File

@@ -61,7 +61,7 @@ public:
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "soundio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "soundio" );
}
class setupWidget : public AudioDeviceSetupWidget
@@ -110,6 +110,7 @@ private:
fpp_t m_outBufFrameIndex;
bool m_stopped;
bool m_outstreamStarted;
int m_disconnectErr;
void onBackendDisconnect(int err);

View File

@@ -30,7 +30,7 @@
#include "JournallingObject.h"
#include "Model.h"
#include "MidiTime.h"
#include "TimePos.h"
#include "ValueBuffer.h"
#include "Memory.h"
#include "ModelVisitor.h"
@@ -148,7 +148,7 @@ public:
template<class T>
inline T value( int frameOffset = 0 ) const
{
if( unlikely( hasLinkedModels() || m_controllerConnection != NULL ) )
if( hasLinkedModels() || m_controllerConnection != NULL )
{
return castValue<T>( controllerValue( frameOffset ) );
}
@@ -281,7 +281,7 @@ public:
return false;
}
float globalAutomationValueAt( const MidiTime& time );
float globalAutomationValueAt( const TimePos& time );
void setStrictStepSize( const bool b )
{

View File

@@ -50,6 +50,7 @@ public:
}
void setModel( Model* model, bool isOldModelValid = true ) override;
void unsetModel() override;
template<typename T>
inline T value() const
@@ -69,12 +70,16 @@ public:
void addDefaultActions( QMenu* menu );
void setConversionFactor( float factor );
float getConversionFactor();
protected:
virtual void mousePressEvent( QMouseEvent* event );
QString m_description;
QString m_unit;
float m_conversionFactor; // Factor to be applied when the m_model->value is displayed
} ;

View File

@@ -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"
@@ -70,7 +70,7 @@ public:
inline bool validPattern() const
{
return m_pattern != nullptr;
return m_pattern != nullptr && m_pattern->hasAutomation();
}
void saveSettings(QDomDocument & doc, QDomElement & parent) override;
@@ -153,7 +153,7 @@ protected slots:
void pasteValues();
void deleteSelectedValues();
void updatePosition( const MidiTime & t );
void updatePosition( const TimePos & t );
void zoomingXChanged();
void zoomingYChanged();
@@ -209,12 +209,13 @@ private:
float m_bottomLevel;
float m_topLevel;
void centerTopBottomScroll();
void updateTopBottomLevels();
QScrollBar * m_leftRightScroll;
QScrollBar * m_topBottomScroll;
MidiTime m_currentPosition;
TimePos m_currentPosition;
Actions m_action;
@@ -264,7 +265,7 @@ private:
signals:
void currentPatternChanged();
void positionChanged( const MidiTime & );
void positionChanged( const TimePos & );
} ;

View File

@@ -30,11 +30,11 @@
#include <QtCore/QMap>
#include <QtCore/QPointer>
#include "Track.h"
#include "TrackContentObject.h"
class AutomationTrack;
class MidiTime;
class TimePos;
@@ -74,19 +74,19 @@ 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 );
void removeValue( const TimePos & time );
void recordValue(MidiTime time, float value);
void recordValue(TimePos time, float value);
MidiTime setDragValue( const MidiTime & time,
TimePos setDragValue( const TimePos & time,
const float value,
const bool quantPos = true,
const bool controlKey = false );
@@ -134,8 +134,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;

View File

@@ -27,9 +27,10 @@
#include <QStaticText>
#include "Track.h"
class AutomationPattern;
#include "AutomationPattern.h"
#include "Song.h"
#include "SongEditor.h"
#include "TrackContentObjectView.h"
class AutomationPatternView : public TrackContentObjectView

View File

@@ -28,6 +28,7 @@
#define AUTOMATION_TRACK_H
#include "Track.h"
#include "TrackView.h"
class LMMS_EXPORT 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;

View File

@@ -26,6 +26,7 @@
#ifndef BB_EDITOR_H
#define BB_EDITOR_H
#include "Editor.h"
#include "TrackContainerView.h"
@@ -86,6 +87,7 @@ public slots:
void removeSteps();
void addSampleTrack();
void addAutomationTrack();
void clonePattern();
protected slots:
void dropEvent(QDropEvent * de ) override;

View File

@@ -32,7 +32,9 @@
#include <QStaticText>
#include "lmms_export.h"
#include "TrackContentObjectView.h"
#include "Track.h"
#include "TrackView.h"
class TrackLabelButton;
class TrackContainer;
@@ -51,33 +53,11 @@ public:
return( "bbtco" );
}
unsigned int color() const
{
return( m_color.rgb() );
}
QColor colorObj() const
{
return m_color;
}
void setColor( const QColor & c )
{
m_color = QColor( c );
}
void setUseStyleColor( bool b )
{
m_useStyleColor = b;
}
int bbTrackIndex();
TrackContentObjectView * createView( TrackView * _tv ) override;
private:
QColor m_color;
bool m_useStyleColor;
friend class BBTCOView;
@@ -93,11 +73,6 @@ public:
BBTCOView( TrackContentObject * _tco, TrackView * _tv );
virtual ~BBTCOView() = default;
QColor color() const
{
return( m_bbTCO->m_color );
}
void setColor( QColor _new_color );
public slots:
void update() override;
@@ -106,8 +81,6 @@ protected slots:
void openInBBEditor();
void resetName();
void changeName();
void changeColor();
void resetColor();
protected:
@@ -133,10 +106,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;
@@ -163,27 +136,6 @@ public:
m_disabledTracks.removeAll( _track );
}
static void setLastTCOColor( const QColor & c )
{
if( ! s_lastTCOColor )
{
s_lastTCOColor = new QColor( c );
}
else
{
*s_lastTCOColor = QColor( c );
}
}
static void clearLastTCOColor()
{
if( s_lastTCOColor )
{
delete s_lastTCOColor;
}
s_lastTCOColor = NULL;
}
protected:
inline QString nodeName() const override
{
@@ -197,8 +149,6 @@ private:
typedef QMap<BBTrack *, int> infoMap;
static infoMap s_infoMap;
static QColor * s_lastTCOColor;
friend class BBTrackView;
} ;

View File

@@ -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();

View File

@@ -29,25 +29,40 @@
#include <QDomElement>
class JournallingObject;
class Clipboard
namespace Clipboard
{
public:
typedef QMap<QString, QDomElement> Map;
static void copy( JournallingObject * _object );
static const QDomElement * getContent( const QString & _node_name );
static const char * mimeType()
enum class MimeType
{
return( "application/x-lmms-clipboard" );
StringPair,
Default
};
// Convenience Methods
const QMimeData * getMimeData();
bool hasFormat( MimeType mT );
// Helper methods for String data
void copyString( const QString & str, MimeType mT );
QString getString( MimeType mT );
// Helper methods for String Pair data
void copyStringPair( const QString & key, const QString & value );
QString decodeKey( const QMimeData * mimeData );
QString decodeValue( const QMimeData * mimeData );
inline const char * mimeType( MimeType type )
{
switch( type )
{
case MimeType::StringPair:
return "application/x-lmms-stringpair";
break;
case MimeType::Default:
default:
return "application/x-lmms-clipboard";
break;
}
}
private:
static Map content;
} ;
#endif

View File

@@ -21,21 +21,39 @@
*
*/
#include <QColorDialog>
#include <QApplication>
#include <QColor>
#include <QColorDialog>
#include <QKeyEvent>
#include <QVector>
class ColorChooser: public QColorDialog
{
public:
ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {};
ColorChooser(QWidget *parent): QColorDialog(parent) {};
//! For getting a color without having to initialise a color dialog
ColorChooser() {};
enum class Palette {Default, Track, Mixer};
//! Set global palette via array, checking bounds
void setPalette (QVector<QColor>);
//! Set global paletter via enum
void setPalette (Palette);
//! Set palette via enum, return self pointer for chaining
ColorChooser* withPalette (Palette);
//! Return a certain palette
static QVector<QColor> getPalette (Palette);
protected:
// Forward key events to the parent to prevent stuck notes when the dialog gets focus
//! Forward key events to the parent to prevent stuck notes when the dialog gets focus
void keyReleaseEvent(QKeyEvent *event) override
{
QKeyEvent ke(*event);
QApplication::sendEvent(parentWidget(), &ke);
}
private:
//! Copy the current QColorDialog palette into an array
static QVector<QColor> defaultPalette();
//! Generate a nice palette, with adjustable value
static QVector<QColor> nicePalette (int);
};

View File

@@ -32,8 +32,6 @@
#include "ComboBoxModel.h"
#include "AutomatableModelView.h"
class LMMS_EXPORT ComboBox : public QWidget, public IntModelView
{
Q_OBJECT
@@ -51,6 +49,8 @@ public:
return castModel<ComboBoxModel>();
}
static constexpr int DEFAULT_HEIGHT = 22;
public slots:
void selectNext();
void selectPrevious();

View File

@@ -39,7 +39,6 @@
class LmmsCore;
const QString PROJECTS_PATH = "projects/";
const QString TEMPLATE_PATH = "templates/";
const QString PRESETS_PATH = "presets/";
@@ -50,11 +49,14 @@ const QString LADSPA_PATH ="plugins/ladspa/";
const QString DEFAULT_THEME_PATH = "themes/default/";
const QString TRACK_ICON_PATH = "track_icons/";
const QString LOCALE_PATH = "locale/";
const QString PORTABLE_MODE_FILE = "/portable_mode.txt";
class LMMS_EXPORT ConfigManager : public QObject
{
Q_OBJECT
using UpgradeMethod = void(ConfigManager::*)();
public:
static inline ConfigManager * inst()
{
@@ -71,6 +73,12 @@ public:
return m_workingDir;
}
void initPortableWorkingDir();
void initInstalledWorkingDir();
void initDevelopmentWorkingDir();
const QString & dataDir() const
{
return m_dataDir;
@@ -213,10 +221,14 @@ public:
return m_version;
}
// Used when the configversion attribute is not present in a configuration file.
// Returns the appropriate config file version based on the LMMS version.
unsigned int legacyConfigVersion();
QString defaultVersion() const;
static QStringList availabeVstEmbedMethods();
static QStringList availableVstEmbedMethods();
QString vstEmbedMethod() const;
// Returns true if the working dir (e.g. ~/lmms) exists on disk.
@@ -264,6 +276,9 @@ private:
void upgrade_1_1_91();
void upgrade();
// List of all upgrade methods
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
QString m_workingDir;
QString m_dataDir;
QString m_vstDir;
@@ -280,6 +295,7 @@ private:
QString m_backgroundPicFile;
QString m_lmmsRcFile;
QString m_version;
unsigned int m_configVersion;
QStringList m_recentlyOpenedProjects;
typedef QVector<QPair<QString, QString> > stringPairVector;

View File

@@ -110,6 +110,9 @@ public:
void setGeometry(const QRect &rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
//! remove focus from QLineEdit search bar
//! this may be useful if the mouse is outside the layout
void removeFocusFromSearchBar();
private slots:
void onTextChanged(const QString&);

30
include/CustomTextKnob.h Normal file
View File

@@ -0,0 +1,30 @@
/* Text customizable knob */
#ifndef CUSTOM_TEXT_KNOB_H
#define CUSTOM_TEXT_KNOB_H
#include "Knob.h"
class LMMS_EXPORT CustomTextKnob : public Knob
{
protected:
inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
public:
CustomTextKnob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() );
CustomTextKnob( QWidget * _parent = NULL, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor
CustomTextKnob( const Knob& other ) = delete;
inline void setValueText(const QString & _value_text)
{
m_value_text = _value_text;
}
private:
virtual QString displayValue() const;
protected:
QString m_value_text;
} ;
#endif

View File

@@ -31,12 +31,16 @@
#include "lmms_export.h"
#include "Memory.h"
#include "ProjectVersion.h"
class QTextStream;
class LMMS_EXPORT DataFile : public QDomDocument
{
MM_OPERATORS
using UpgradeMethod = void(DataFile::*)();
public:
enum Types
{
@@ -84,6 +88,8 @@ public:
return m_type;
}
unsigned int legacyFileVersion();
private:
static Type type( const QString& typeName );
static QString typeName( Type type );
@@ -107,8 +113,13 @@ private:
void upgrade_1_1_0();
void upgrade_1_1_91();
void upgrade_1_2_0_rc3();
void upgrade_1_2_0_rc2_42();
void upgrade_1_3_0();
void upgrade_noHiddenClipNames();
// List of all upgrade methods
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
// List of ProjectVersions for the legacyFileVersion method
static const std::vector<ProjectVersion> UPGRADE_VERSIONS;
void upgrade();
@@ -125,14 +136,9 @@ private:
QDomElement m_content;
QDomElement m_head;
Type m_type;
unsigned int m_fileVersion;
} ;
const int LDF_MAJOR_VERSION = 1;
const int LDF_MINOR_VERSION = 0;
const QString LDF_VERSION_STRING = QString::number( LDF_MAJOR_VERSION ) + "." + QString::number( LDF_MINOR_VERSION );
#endif

View File

@@ -0,0 +1,63 @@
/*
* DeprecationHelper.h - This file contains the declarations of helper functions
* which helps centralize the #ifdefs preprocessors regarding deprecation based on Qt versions.
* The functions are defined differently based on the callers' Qt versions.
*
* Copyright (c) 2020 Tien Dat Nguyen <ntd.bk.k56/at/gmail.com>
*
* 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 DEPRECATIONHELPER_H
#define DEPRECATIONHELPER_H
#include <QFontMetrics>
#include <QWheelEvent>
/**
* @brief horizontalAdvance is a backwards-compatible adapter for
* QFontMetrics::horizontalAdvance and width functions.
* @param metrics
* @param text
* @return text's horizontal advance based on metrics.
*/
inline int horizontalAdvance(const QFontMetrics& metrics, const QString& text)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
return metrics.horizontalAdvance(text);
#else
return metrics.width(text);
#endif
}
/**
* @brief position is a backwards-compatible adapter for
* QWheelEvent::position and pos functions.
* @param wheelEvent
* @return the position of wheelEvent
*/
inline QPoint position(QWheelEvent *wheelEvent)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
return wheelEvent->position().toPoint();
#else
return wheelEvent->pos();
#endif
}
#endif // DEPRECATIONHELPER_H

View File

@@ -28,6 +28,12 @@
#include <QMainWindow>
#include <QToolBar>
static const int Quantizations[] = {
1, 2, 4, 8, 16, 32, 64,
3, 6, 12, 24, 48, 96, 192
};
class QAction;
class DropToolBar;
@@ -58,6 +64,11 @@ protected slots:
private slots:
/// Called by pressing the space key. Plays or stops.
void togglePlayStop();
/// Called by pressing shift+space. Toggles pause state.
void togglePause();
void toggleMaximize();
signals:

View File

@@ -46,6 +46,7 @@ public:
EffectRackView( EffectChain* model, QWidget* parent = NULL );
virtual ~EffectRackView();
static constexpr int DEFAULT_WIDTH = 245;
public slots:
void clearViews();

View File

@@ -57,6 +57,7 @@ public:
return castModel<Effect>();
}
static constexpr int DEFAULT_WIDTH = 215;
public slots:
void editControls();

View File

@@ -30,11 +30,11 @@
#include <QtCore/QObject>
#include "lmmsconfig.h"
#include "lmms_export.h"
#include "lmms_basics.h"
class BBTrackContainer;
class DummyTrackContainer;
class FxMixer;
class ProjectJournal;
class Mixer;
@@ -87,16 +87,20 @@ public:
return s_projectJournal;
}
static bool ignorePluginBlacklist();
#ifdef LMMS_HAVE_LV2
static class Lv2Manager * getLv2Manager()
{
return s_lv2Manager;
}
#endif
static Ladspa2LMMS * getLADSPAManager()
{
return s_ladspaManager;
}
static DummyTrackContainer * dummyTrackContainer()
{
return s_dummyTC;
}
static float framesPerTick()
{
return s_framesPerTick;
@@ -141,8 +145,10 @@ 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;
#endif
static Ladspa2LMMS * s_ladspaManager;
static void* s_dndPluginKey;

View File

@@ -26,9 +26,9 @@
#ifndef FADE_BUTTON_H
#define FADE_BUTTON_H
#include <QtCore/QTime>
#include <QAbstractButton>
#include <QColor>
#include <QElapsedTimer>
class FadeButton : public QAbstractButton
@@ -55,8 +55,8 @@ protected:
private:
QTime m_stateTimer;
QTime m_releaseTimer;
QElapsedTimer m_stateTimer;
QElapsedTimer m_releaseTimer;
// the default color of the widget
QColor m_normalColor;
@@ -66,7 +66,7 @@ private:
QColor m_holdColor;
int activeNotes;
QColor fadeToColor(QColor, QColor, QTime, float);
QColor fadeToColor(QColor, QColor, QElapsedTimer, float);
} ;

View File

@@ -48,9 +48,10 @@
#ifndef FADER_H
#define FADER_H
#include <QtCore/QTime>
#include <QWidget>
#include <QElapsedTimer>
#include <QPixmap>
#include <QWidget>
#include "AutomatableModelView.h"
@@ -98,7 +99,7 @@ public:
void setDisplayConversion( bool b )
{
m_displayConversion = b;
m_conversionFactor = b ? 100.0 : 1.0;
}
inline void setHintText( const QString & _txt_before,
@@ -130,7 +131,7 @@ private:
return height() - ( ( height() - m_knob->height() ) * ( realVal / fRange ) );
}
void setPeak( float fPeak, float &targetPeak, float &persistentPeak, QTime &lastPeakTime );
void setPeak( float fPeak, float &targetPeak, float &persistentPeak, QElapsedTimer &lastPeakTimer );
int calculateDisplayPeak( float fPeak );
void updateTextFloat();
@@ -144,8 +145,8 @@ private:
float m_fMinPeak;
float m_fMaxPeak;
QTime m_lastPeakTime_L;
QTime m_lastPeakTime_R;
QElapsedTimer m_lastPeakTimer_L;
QElapsedTimer m_lastPeakTimer_R;
static QPixmap * s_back;
static QPixmap * s_leds;
@@ -154,8 +155,7 @@ private:
QPixmap * m_back;
QPixmap * m_leds;
QPixmap * m_knob;
bool m_displayConversion;
bool m_levelsDisplayedInDBFS;
int m_moveStartPoint;

View File

@@ -26,6 +26,7 @@
#ifndef FILE_BROWSER_H
#define FILE_BROWSER_H
#include <QCheckBox>
#include <QtCore/QDir>
#include <QtCore/QMutex>
#include <QTreeWidget>
@@ -58,14 +59,17 @@ 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:
void reloadTree( void );
void expandItems( QTreeWidgetItem * item=NULL, QList<QString> expandedDirs = QList<QString>() );
void expandItems( QTreeWidgetItem * item=nullptr, QList<QString> expandedDirs = QList<QString>() );
// call with item=NULL to filter the entire tree
bool filterItems( const QString & filter, QTreeWidgetItem * item=NULL );
bool filterItems( const QString & filter, QTreeWidgetItem * item=nullptr );
void giveFocusToFilter();
private:
@@ -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;
} ;
@@ -105,29 +114,39 @@ protected:
void mousePressEvent( QMouseEvent * me ) override;
void mouseMoveEvent( QMouseEvent * me ) override;
void mouseReleaseEvent( QMouseEvent * me ) override;
void keyPressEvent( QKeyEvent * ke ) override;
void keyReleaseEvent( QKeyEvent * ke ) override;
void hideEvent( QHideEvent * he ) override;
void focusOutEvent( QFocusEvent * fe ) override;
private:
//! Start a preview of a file item
void previewFileItem(FileItem* file);
//! If a preview is playing, stop it.
void stopPreview();
void handleFile( FileItem * fi, InstrumentTrack * it );
void openInNewInstrumentTrack( TrackContainer* tc );
void openInNewInstrumentTrack( TrackContainer* tc, FileItem* item );
bool m_mousePressed;
QPoint m_pressPos;
//! This should only be accessed or modified when m_pphMutex is held
PlayHandle* m_previewPlayHandle;
QMutex m_pphMutex;
FileItem * m_contextMenuItem;
QList<QAction*> getContextActions(FileItem* item, bool songEditor);
private slots:
void activateListItem( QTreeWidgetItem * item, int column );
void openInNewInstrumentTrackBBE( void );
void openInNewInstrumentTrackSE( void );
void sendToActiveInstrumentTrack( void );
void openInNewInstrumentTrack( FileItem* item, bool songEditor );
bool openInNewSampleTrack( FileItem* item );
void sendToActiveInstrumentTrack( FileItem* item );
void updateDirectory( QTreeWidgetItem * item );
void openContainingFolder();
void openContainingFolder( FileItem* item );
} ;
@@ -234,6 +253,11 @@ public:
return( m_handling );
}
inline bool isTrack( void ) const
{
return m_handling == LoadAsPreset || m_handling == LoadByPlugin;
}
QString extension( void );
static QString extension( const QString & file );

View File

@@ -46,8 +46,7 @@ public:
const QString &caption = QString(),
const QString &directory = QString(),
const QString &filter = QString(),
QString *selectedFilter = 0,
QFileDialog::Options options = 0);
QString *selectedFilter = 0);
void clearSelection();
};

View File

@@ -26,10 +26,12 @@
#ifndef FX_LINE_H
#define FX_LINE_H
#include <QColorDialog>
#include <QGraphicsView>
#include <QLineEdit>
#include <QWidget>
#include "ColorChooser.h"
#include "Knob.h"
#include "LcdWidget.h"
#include "SendButtonIndicator.h"
@@ -101,6 +103,9 @@ private:
public slots:
void renameChannel();
void resetColor();
void changeColor();
void randomColor();
private slots:
void renameFinished();

View File

@@ -32,6 +32,8 @@
#include <atomic>
#include <QColor>
class FxRoute;
typedef QVector<FxRoute *> FxRouteVector;
@@ -70,6 +72,17 @@ class FxChannel : public ThreadableJob
bool requiresProcessing() const override { return true; }
void unmuteForSolo();
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;
std::atomic_int m_dependenciesMet;
void incrementDeps();

View File

@@ -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; }

View File

@@ -30,8 +30,8 @@
#include "lmms_export.h"
#include "lmms_basics.h"
#include "Memory.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;
}
@@ -132,6 +132,9 @@ public:
protected:
// fade in to prevent clicks
void applyFadeIn(sampleFrame * buf, NotePlayHandle * n);
// instruments may use this to apply a soft fade out at the end of
// notes - method does this only if really less or equal
// desiredReleaseFrames() frames are left

View File

@@ -74,7 +74,7 @@ private:
FloatModel m_filterCutModel;
FloatModel m_filterResModel;
static const QString targetNames[InstrumentSoundShaping::NumTargets][3];
static const char *const targetNames[InstrumentSoundShaping::NumTargets][3];
friend class InstrumentSoundShapingView;

View File

@@ -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
@@ -219,6 +221,8 @@ public:
return m_previewMode;
}
void autoAssignMidiDevice( bool );
signals:
void instrumentChanged();
void midiNoteOn( const Note& );
@@ -227,7 +231,6 @@ signals:
void newNote();
void endNote();
protected:
QString nodeName() const override
{
@@ -246,6 +249,8 @@ protected slots:
private:
void processCCEvent(int controller);
MidiPort m_midiPort;
NotePlayHandle* m_notes[NumKeys];
@@ -260,6 +265,9 @@ private:
bool m_previewMode;
bool m_hasAutoMidiDev;
static InstrumentTrack *s_autoAssignedTrack;
IntModel m_baseNoteModel;
NotePlayHandleList m_processHandles;
@@ -282,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;
} ;
@@ -319,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;
@@ -334,6 +341,7 @@ protected:
private slots:
void toggleInstrumentWindow( bool _on );
void toggleMidiCCRack();
void activityIndicatorPressed();
void activityIndicatorReleased();
@@ -344,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;
@@ -361,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;
}
@@ -477,6 +487,7 @@ private:
PianoView * m_pianoView;
friend class InstrumentView;
friend class InstrumentTrackView;
} ;

View File

@@ -26,6 +26,8 @@
#ifndef KNOB_H
#define KNOB_H
#include <memory>
#include <QPixmap>
#include <QWidget>
#include <QtCore/QPoint>
@@ -41,6 +43,7 @@ enum knobTypes
} ;
void convertPixmapToGrayScale(QPixmap &pixMap);
class LMMS_EXPORT Knob : public QWidget, public FloatModelView
{
@@ -58,8 +61,12 @@ class LMMS_EXPORT Knob : public QWidget, public FloatModelView
// Unfortunately, the gradient syntax doesn't create our gradient
// correctly so we need to do this:
Q_PROPERTY(QColor outerColor READ outerColor WRITE setOuterColor)
Q_PROPERTY(QColor lineColor READ lineColor WRITE setlineColor)
Q_PROPERTY(QColor arcColor READ arcColor WRITE setarcColor)
Q_PROPERTY(QColor lineActiveColor MEMBER m_lineActiveColor)
Q_PROPERTY(QColor lineInactiveColor MEMBER m_lineInactiveColor)
Q_PROPERTY(QColor arcActiveColor MEMBER m_arcActiveColor)
Q_PROPERTY(QColor arcInactiveColor MEMBER m_arcInactiveColor)
mapPropertyFromModel(bool,isVolumeKnob,setVolumeKnob,m_volumeKnob);
mapPropertyFromModel(float,volumeRatio,setVolumeRatio,m_volumeRatio);
@@ -74,7 +81,6 @@ public:
Knob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString() );
Knob( QWidget * _parent = NULL, const QString & _name = QString() ); //!< default ctor
Knob( const Knob& other ) = delete;
virtual ~Knob();
// TODO: remove
inline void setHintText( const QString & _txt_before,
@@ -108,10 +114,6 @@ public:
QColor outerColor() const;
void setOuterColor( const QColor & c );
QColor lineColor() const;
void setlineColor( const QColor & c );
QColor arcColor() const;
void setarcColor( const QColor & c );
QColor textColor() const;
void setTextColor( const QColor & c );
@@ -134,6 +136,7 @@ protected:
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
void paintEvent( QPaintEvent * _me ) override;
void wheelEvent( QWheelEvent * _me ) override;
void changeEvent(QEvent * ev) override;
virtual float getValue( const QPoint & _p );
@@ -143,7 +146,7 @@ private slots:
void toggleScale();
private:
QString displayValue() const;
virtual QString displayValue() const;
void doConnections() override;
@@ -169,12 +172,11 @@ private:
QString m_label;
QPixmap * m_knobPixmap;
std::unique_ptr<QPixmap> m_knobPixmap;
BoolModel m_volumeKnob;
FloatModel m_volumeRatio;
QPoint m_mouseOffset;
QPoint m_origMousePos;
QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent
float m_leftOver;
bool m_buttonPressed;
@@ -188,8 +190,11 @@ private:
float m_outerRadius;
float m_lineWidth;
QColor m_outerColor;
QColor m_lineColor; //!< unused yet
QColor m_arcColor; //!< unused yet
QColor m_lineActiveColor;
QColor m_lineInactiveColor;
QColor m_arcActiveColor;
QColor m_arcInactiveColor;
QColor m_textColor;

View File

@@ -73,8 +73,9 @@ protected:
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
private:
float m_remainder; //!< floating offset of spinbox in [-0.5, 0.5]
bool m_mouseMoving;
QPoint m_origMousePos;
QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent
int m_displayOffset;
void enterValue();

View File

@@ -71,6 +71,8 @@ protected:
void removeControl(const QString &key);
void removeFocusFromSearchBar();
private:
class LinkedModelGroup* m_model;
@@ -96,7 +98,7 @@ protected:
void modelChanged(class LinkedModelGroups* ctrlBase);
private:
//! The base class must return the adressed group view,
//! The base class must return the addressed group view,
//! which has the same value as "this"
virtual LinkedModelGroupView* getGroupView() = 0;
};

View File

@@ -42,7 +42,7 @@
/**
Base class for a group of linked models
See the LinkedModelGroup class for explenations
See the LinkedModelGroup class for explanations
Features:
* Models are stored by their QObject::objectName

View File

@@ -28,27 +28,32 @@
#include <QMutex>
#include <QWaitCondition>
#include "lmms_basics.h"
#include "lmms_export.h"
#include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h"
//! A convenience layer for a realtime-safe and thread-safe multi-reader ring buffer library.
//! A convenience layer for a realtime-safe and thread-safe multi-reader ringbuffer
template <class T>
class LocklessRingBufferBase
class LocklessRingBuffer
{
template<class _T>
friend class LocklessRingBufferReader;
public:
LocklessRingBufferBase(std::size_t sz) : m_buffer(sz)
LocklessRingBuffer(std::size_t sz) : m_buffer(sz)
{
m_buffer.touch(); // reserve storage space before realtime operation starts
}
~LocklessRingBufferBase() {};
~LocklessRingBuffer() {};
std::size_t capacity() const {return m_buffer.maximum_eventual_write_space();}
std::size_t free() const {return m_buffer.write_space();}
void wakeAll() {m_notifier.wakeAll();}
std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false)
{
std::size_t written = LocklessRingBuffer<T>::m_buffer.write(src, cnt);
// Let all waiting readers know new data are available.
if (notify) {LocklessRingBuffer<T>::m_notifier.wakeAll();}
return written;
}
protected:
ringbuffer_t<T> m_buffer;
@@ -56,59 +61,6 @@ protected:
};
// The SampleFrameCopier is required because sampleFrame is just a two-element
// array and therefore does not have a copy constructor needed by std::copy.
class SampleFrameCopier
{
const sampleFrame* m_src;
public:
SampleFrameCopier(const sampleFrame* src) : m_src(src) {}
void operator()(std::size_t src_offset, std::size_t count, sampleFrame* dest)
{
for (std::size_t i = src_offset; i < src_offset + count; i++, dest++)
{
(*dest)[0] = m_src[i][0];
(*dest)[1] = m_src[i][1];
}
}
};
//! Standard ring buffer template for data types with copy constructor.
template <class T>
class LocklessRingBuffer : public LocklessRingBufferBase<T>
{
public:
LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase<T>(sz) {};
std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false)
{
std::size_t written = LocklessRingBufferBase<T>::m_buffer.write(src, cnt);
// Let all waiting readers know new data are available.
if (notify) {LocklessRingBufferBase<T>::m_notifier.wakeAll();}
return written;
}
};
//! Specialized ring buffer template with write function modified to support sampleFrame.
template <>
class LocklessRingBuffer<sampleFrame> : public LocklessRingBufferBase<sampleFrame>
{
public:
LocklessRingBuffer(std::size_t sz) : LocklessRingBufferBase<sampleFrame>(sz) {};
std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false)
{
SampleFrameCopier copier(src);
std::size_t written = LocklessRingBufferBase<sampleFrame>::m_buffer.write_func<SampleFrameCopier>(copier, cnt);
// Let all waiting readers know new data are available.
if (notify) {LocklessRingBufferBase<sampleFrame>::m_notifier.wakeAll();}
return written;
}
};
//! Wrapper for lockless ringbuffer reader
template <class T>
class LocklessRingBufferReader : public ringbuffer_reader_t<T>

67
include/Lv2Basics.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* Lv2Basics.h - basic Lv2 utils
*
* Copyright (c) 2018-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 LV2BASICS_H
#define LV2BASICS_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lilv/lilv.h>
#include <memory>
#include <QString>
#include <string>
struct LilvNodeDeleter
{
void operator()(LilvNode* n) { lilv_node_free(n); }
};
struct LilvNodesDeleter
{
void operator()(LilvNodes* n) { lilv_nodes_free(n); }
};
using AutoLilvNode = std::unique_ptr<LilvNode, LilvNodeDeleter>;
using AutoLilvNodes = std::unique_ptr<LilvNodes, LilvNodesDeleter>;
/**
Return QString from a plugin's node, everything will be freed automatically
@param plug The plugin where the node is
@param getFunc The function to return the node from the plugin
*/
QString qStringFromPluginNode(const LilvPlugin* plug,
LilvNode * (*getFunc)(const LilvPlugin*));
//! Return port name as QString, everything will be freed automatically
QString qStringFromPortName(const LilvPlugin* plug, const LilvPort* port);
//! Return port name as std::string, everything will be freed automatically
std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port);
#endif // LMMS_HAVE_LV2
#endif // LV2BASICS_H

158
include/Lv2ControlBase.h Normal file
View File

@@ -0,0 +1,158 @@
/*
* Lv2ControlBase.h - Lv2 control base class
*
* Copyright (c) 2018-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 LV2_CONTROL_BASE_H
#define LV2_CONTROL_BASE_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lilv/lilv.h>
#include "DataFile.h"
#include "LinkedModelGroups.h"
#include "lmms_export.h"
#include "Plugin.h"
class Lv2Proc;
class PluginIssue;
/**
Common base class for Lv2 plugins
This class contains a vector of Lv2Proc, usually 1 (for stereo plugins) or
2 (for mono plugins). Most of the logic is done there, this class primarily
forwards work to the Lv2Proc and collects the results.
This class provides everything Lv2 plugins have in common. It's not
named Lv2Plugin, because
* it does not inherit Instrument
* the Plugin subclass Effect does not inherit this class
This class would usually be a Model subclass. However, Qt doesn't allow
this:
* inheriting only from Model will cause diamond inheritance for QObject,
which will cause errors with Q_OBJECT
* making this a direct subclass of Instrument resp. EffectControls would
require CRTP, which would make this class a template class, which would
conflict with Q_OBJECT
The consequence is that this class can neither inherit QObject or Model, nor
Instrument or EffectControls, which means in fact:
* this class contains no signals or slots, but it offers stubs for slots
that shall be called by child classes
* this class can not override virtuals of Instrument or EffectControls, so
it will offer functions that must be called by virtuals in its child class
*/
class LMMS_EXPORT Lv2ControlBase : public LinkedModelGroups
{
public:
static Plugin::PluginTypes check(const LilvPlugin* m_plugin,
std::vector<PluginIssue> &issues);
const LilvPlugin* getPlugin() const { return m_plugin; }
Lv2Proc *control(std::size_t idx) { return m_procs[idx].get(); }
const Lv2Proc *control(std::size_t idx) const { return m_procs[idx].get(); }
bool hasGui() const { return m_hasGUI; }
void setHasGui(bool val) { m_hasGUI = val; }
protected:
/*
ctor/dtor
*/
//! @param that the class inheriting this class and inheriting Model;
//! this is the same pointer as this, but a different type
//! @param uri the Lv2 URI telling this class what plugin to construct
Lv2ControlBase(class Model *that, const QString& uri);
Lv2ControlBase(const Lv2ControlBase&) = delete;
~Lv2ControlBase() override;
Lv2ControlBase& operator=(const Lv2ControlBase&) = delete;
//! Must be checked after ctor or reload
bool isValid() const { return m_valid; }
/*
overrides
*/
LinkedModelGroup* getGroup(std::size_t idx) override;
const LinkedModelGroup* getGroup(std::size_t idx) const override;
/*
utils for the run thread
*/
//! Copy values from the LMMS core (connected models, MIDI events, ...) into
//! the respective ports
void copyModelsFromLmms();
//! Bring values from all ports to the LMMS core
void copyModelsToLmms() const;
//! Copy buffer passed by LMMS into our ports
void copyBuffersFromLmms(const sampleFrame *buf, fpp_t frames);
//! Copy our ports into buffers passed by LMMS
void copyBuffersToLmms(sampleFrame *buf, fpp_t frames) const;
//! Run the Lv2 plugin instance for @param frames frames
void run(fpp_t frames);
/*
load/save, must be called from virtuals
*/
void saveSettings(QDomDocument &doc, QDomElement &that);
void loadSettings(const QDomElement &that);
void loadFile(const QString &file);
//! TODO: not implemented
void reloadPlugin();
/*
more functions that must be called from virtuals
*/
std::size_t controlCount() const;
QString nodeName() const { return "lv2controls"; }
bool hasNoteInput() const;
void handleMidiInputEvent(const class MidiEvent &event,
const class TimePos &time, f_cnt_t offset);
private:
//! Return the DataFile settings type
virtual DataFile::Types settingsType() = 0;
//! Inform the plugin about a file name change
virtual void setNameFromFile(const QString &fname) = 0;
//! Independent processors
//! If this is a mono effect, the vector will have size 2 in order to
//! fulfill LMMS' requirement of having stereo input and output
std::vector<std::unique_ptr<Lv2Proc>> m_procs;
bool m_valid = true;
bool m_hasGUI = false;
unsigned m_channelsPerProc;
const LilvPlugin* m_plugin;
};
#endif // LMMS_HAVE_LV2
#endif // LV2_CONTROL_BASE_H

149
include/Lv2Evbuf.h Normal file
View File

@@ -0,0 +1,149 @@
/*
* lv2_evbuf.h - Lv2 event buffer definitions
*
* Copyright (c) 2019-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.
*
*/
/*
* The original code was written by David Robillard <http://drobilla.net>
* Original version: 6f22ee0 from https://github.com/drobilla/jalv.git
* Minor changes have been done, but no functional changes.
* Considering this as an "external library", the identifiers do not need to
* match the LMMS coding conventions.
*/
#ifndef LV2_EVBUF_H
#define LV2_EVBUF_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <cstdint>
/**
An abstract/opaque LV2 event buffer.
*/
typedef struct LV2_Evbuf_Impl LV2_Evbuf;
/**
An iterator over an LV2_Evbuf.
*/
typedef struct {
LV2_Evbuf* evbuf;
uint32_t offset;
} LV2_Evbuf_Iterator;
/**
Allocate a new, empty event buffer.
URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM.
*/
LV2_Evbuf*
lv2_evbuf_new(uint32_t capacity, uint32_t atom_Chunk, uint32_t atom_Sequence);
/**
Free an event buffer allocated with lv2_evbuf_new.
*/
void
lv2_evbuf_free(LV2_Evbuf* evbuf);
/**
Clear and initialize an existing event buffer.
The contents of buf are ignored entirely and overwritten, except capacity
which is unmodified.
If input is false and this is an atom buffer, the buffer will be prepared
for writing by the plugin. This MUST be called before every run cycle.
*/
void
lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input);
/**
Return the total padded size of the events stored in the buffer.
*/
uint32_t
lv2_evbuf_get_size(LV2_Evbuf* evbuf);
/**
Return the actual buffer implementation.
The format of the buffer returned depends on the buffer type.
*/
void*
lv2_evbuf_get_buffer(LV2_Evbuf* evbuf);
/**
Return an iterator to the start of `evbuf`.
*/
LV2_Evbuf_Iterator
lv2_evbuf_begin(LV2_Evbuf* evbuf);
/**
Return an iterator to the end of `evbuf`.
*/
LV2_Evbuf_Iterator
lv2_evbuf_end(LV2_Evbuf* evbuf);
/**
Check if `iter` is valid.
@return True if `iter` is valid, otherwise false (past end of buffer)
*/
bool
lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter);
/**
Advance `iter` forward one event.
`iter` must be valid.
@return True if `iter` is valid, otherwise false (reached end of buffer)
*/
LV2_Evbuf_Iterator
lv2_evbuf_next(LV2_Evbuf_Iterator iter);
/**
Dereference an event iterator (i.e. get the event currently pointed to).
`iter` must be valid.
`type` Set to the type of the event.
`size` Set to the size of the event.
`data` Set to the contents of the event.
@return True on success.
*/
bool
lv2_evbuf_get( LV2_Evbuf_Iterator iter,
uint32_t* frames,
uint32_t* type,
uint32_t* size,
uint8_t** data);
/**
Write an event at `iter`.
The event (if any) pointed to by `iter` will be overwritten, and `iter`
incremented to point to the following event (i.e. several calls to this
function can be done in sequence without twiddling iter in-between).
@return True if event was written, otherwise false (buffer is full).
*/
bool
lv2_evbuf_write( LV2_Evbuf_Iterator* iter,
uint32_t frames,
uint32_t type,
uint32_t size,
const uint8_t* data);
#endif // LMMS_HAVE_LV2
#endif // LV2_EVBUF_H

81
include/Lv2Features.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Lv2Features.h - Lv2Features 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 LV2FEATURES_H
#define LV2FEATURES_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lv2.h>
#include <map>
#include <vector>
#include "Lv2Manager.h"
/**
Feature container
References all available features for a plugin and maps them to their URIs.
The public member functions should be called in descending order:
1. initCommon: map plugin-common features
2. operator[]: map plugin-specific features
3. createFeatureVectors: create the feature vectors required for
lilv_plugin_instantiate
4. access the latter
*/
class Lv2Features
{
public:
//! Return if a feature is supported by LMMS
static bool isFeatureSupported(const char *featName);
Lv2Features();
//! Register only plugin-common features
void initCommon();
//! Return reference to feature data with given URI featName
void*& operator[](const char* featName);
//! Fill m_features and m_featurePointers with all features
void createFeatureVectors();
//! Return LV2_Feature pointer vector, suited for lilv_plugin_instantiate
const LV2_Feature* const* featurePointers() const
{
return m_featurePointers.data();
}
private:
//! feature storage
std::vector<LV2_Feature> m_features;
//! pointers to m_features, required for lilv_plugin_instantiate
std::vector<const LV2_Feature*> m_featurePointers;
//! features + data, ordered by URI
std::map<const char*, void*, Lv2Manager::CmpStr> m_featureByUri;
};
#endif // LMMS_HAVE_LV2
#endif // LV2FEATURES_H

163
include/Lv2Manager.h Normal file
View File

@@ -0,0 +1,163 @@
/*
* Lv2Manager.h - Implementation of Lv2Manager class
*
* Copyright (c) 2018-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 LV2MANAGER_H
#define LV2MANAGER_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <map>
#include <set>
#include <lilv/lilv.h>
#include "Lv2Basics.h"
#include "Lv2UridCache.h"
#include "Lv2UridMap.h"
#include "Plugin.h"
/*
all Lv2 classes in relation (use our "4 spaces per tab rule" to view):
explanation:
"x = {y z}" means class "x" consists of classes "y" and "z"
(and probably other classes not mentioned)
"x = {y*}" means class "x" references/uses class "y"
core:
Lv2Proc = {LilvInstance}
Lv2ControlBase = {Lv2Proc, Lv2Proc... (2 for mono, 1 for stereo)}
Lv2Manager = {LilvPlugin*, LilvPlugin* ...}
(creates Lv2ControlBase, Lv2ControlBase...)
Lv2FxControls = {Lv2ControlBase}
Lv2Effect = {Effect + Lv2FxControls}
(takes Lv2SubPluginFeatures in ctor)
Lv2Instrument = {Instrument + Lv2ControlBase}
(takes Lv2SubPluginFeatures in ctor)
gui:
Lv2ViewProc = {Lv2Proc*}
Lv2ViewBase = {Lv2ViewProc, Lv2ViewProc...
(2 for mono, 1 for stereo)}
Lv2FxControlDialog = {EffectControlDialog + Lv2ViewBase}
Lv2InsView = {InstrumentView + Lv2ViewBase}
Lv2SubPluginFeatures:
Lv2SubPluginFeatures = {Lv2Manager*}
Lv2Effect::Descriptor = {Lv2SubPluginFeatures}
Lv2Instrument::Descriptor = {Lv2SubPluginFeatures}
*/
//! Class to keep track of all LV2 plugins
class Lv2Manager
{
public:
void initPlugins();
Lv2Manager();
~Lv2Manager();
AutoLilvNode uri(const char* uriStr);
//! Class representing info for one plugin
struct Lv2Info
{
public:
//! use only for std::map internals
Lv2Info() : m_plugin(nullptr) {}
//! ctor used inside Lv2Manager
Lv2Info(const LilvPlugin* plug, Plugin::PluginTypes type, bool valid) :
m_plugin(plug), m_type(type), m_valid(valid) {}
Lv2Info(Lv2Info&& other) = default;
Lv2Info& operator=(Lv2Info&& other) = default;
const LilvPlugin* plugin() const { return m_plugin; }
Plugin::PluginTypes type() const { return m_type; }
bool isValid() const { return m_valid; }
private:
const LilvPlugin* m_plugin;
Plugin::PluginTypes m_type;
bool m_valid = false;
};
//! Return descriptor with URI @p uri or nullptr if none exists
const LilvPlugin *getPlugin(const std::string &uri);
//! Return descriptor with URI @p uri or nullptr if none exists
const LilvPlugin *getPlugin(const QString& uri);
using Lv2InfoMap = std::map<std::string, Lv2Info>;
using Iterator = Lv2InfoMap::iterator;
Iterator begin() { return m_lv2InfoMap.begin(); }
Iterator end() { return m_lv2InfoMap.end(); }
//! strcmp based key comparator for std::set and std::map
struct CmpStr
{
bool operator()(char const *a, char const *b) const;
};
UridMap& uridMap() { return m_uridMap; }
const Lv2UridCache& uridCache() const { return m_uridCache; }
const std::set<const char*, CmpStr>& supportedFeatureURIs() const
{
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
bool m_debug; //!< if set, debug output will be printed
LilvWorld* m_world;
Lv2InfoMap m_lv2InfoMap;
std::set<const char*, CmpStr> m_supportedFeatureURIs;
// feature data that are common for all Lv2Proc
UridMap m_uridMap;
// 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);
};
#endif // LMMS_HAVE_LV2
#endif // LV2MANAGER_H

104
include/Lv2Options.h Normal file
View 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

265
include/Lv2Ports.h Normal file
View File

@@ -0,0 +1,265 @@
/*
* Lv2Ports.h - Lv2 port classes definitions
*
* Copyright (c) 2019-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 LV2PORTS_H
#define LV2PORTS_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lilv/lilv.h>
#include <memory>
#include <vector>
#include "lmms_basics.h"
#include "PluginIssue.h"
struct ConnectPortVisitor;
typedef struct LV2_Evbuf_Impl LV2_Evbuf;
namespace Lv2Ports {
/*
port structs
*/
enum class Flow {
Unknown,
Input,
Output
};
enum class Type {
Unknown,
Control,
Audio,
AtomSeq,
Cv //!< TODO: unused, describe
};
//! Port visualization
//! @note All Lv2 audio ports are float, this is only the visualisation
enum class Vis {
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);
const char* toStr(Lv2Ports::Type pt);
const char* toStr(Lv2Ports::Vis pv);
struct ControlPortBase;
struct Control;
struct Audio;
struct Cv;
struct AtomSeq;
struct Unknown;
struct ConstVisitor
{
virtual void visit(const Lv2Ports::ControlPortBase& ) {}
virtual void visit(const Lv2Ports::Control& ) {}
virtual void visit(const Lv2Ports::Audio& ) {}
virtual void visit(const Lv2Ports::Cv& ) {}
virtual void visit(const Lv2Ports::AtomSeq& ) {}
virtual void visit(const Lv2Ports::Unknown& ) {}
virtual ~ConstVisitor();
};
struct Visitor
{
virtual void visit(Lv2Ports::ControlPortBase& ) {}
virtual void visit(Lv2Ports::Control& ) {}
virtual void visit(Lv2Ports::Audio& ) {}
virtual void visit(Lv2Ports::Cv& ) {}
virtual void visit(Lv2Ports::AtomSeq& ) {}
virtual void visit(Lv2Ports::Unknown& ) {}
virtual ~Visitor();
};
struct Meta
{
Type m_type = Type::Unknown;
Flow m_flow = Flow::Unknown;
Vis m_vis = Vis::Generic;
bool m_logarithmic = false;
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
{
const LilvPort* m_port = nullptr;
const LilvPlugin* m_plugin = nullptr;
virtual void accept(Visitor& v) = 0;
virtual void accept(ConstVisitor& v) const = 0;
QString name() const;
QString uri() const;
virtual ~PortBase();
};
template<typename Derived, typename Base>
struct VisitablePort : public Base
{
void accept(Visitor& v) override { v.visit(static_cast<Derived&>(*this)); }
void accept(ConstVisitor& v) const override { v.visit(static_cast<const Derived&>(*this)); }
};
struct ControlPortBase : public VisitablePort<ControlPortBase, PortBase>
{
//! LMMS models
//! Always up-to-date, except during runs
std::unique_ptr<class AutomatableModel> m_connectedModel;
//! Enumerate float values
//! lv2 defines scale points as
//! "single float Points (for control inputs)"
std::vector<float> m_scalePointMap;
};
struct Control : public VisitablePort<Control, ControlPortBase>
{
//! Data location which Lv2 plugins see
//! Model values are being copied here every run
//! Between runs, this data is not up-to-date
float m_val;
};
struct Cv : public VisitablePort<Cv, ControlPortBase>
{
//! Data location which Lv2 plugins see
//! Model values are being copied here every run
//! Between runs, this data is not up-to-date
std::vector<float> m_buffer;
};
struct Audio : public VisitablePort<Audio, PortBase>
{
Audio(std::size_t bufferSize, bool isSidechain);
//! Copy buffer passed by LMMS into our ports
//! @param channel channel index into each sample frame
void copyBuffersFromCore(const sampleFrame *lmmsBuf,
unsigned channel, fpp_t frames);
//! Add buffer passed by LMMS into our ports, and halve the result
//! @param channel channel index into each sample frame
void averageWithBuffersFromCore(const sampleFrame *lmmsBuf,
unsigned channel, fpp_t frames);
//! Copy our ports into buffers passed by LMMS
//! @param channel channel index into each sample frame
void copyBuffersToCore(sampleFrame *lmmsBuf,
unsigned channel, fpp_t frames) const;
bool isSideChain() const { return m_sidechain; }
bool isOptional() const { return m_optional; }
bool mustBeUsed() const { return !isSideChain() && !isOptional(); }
std::size_t bufferSize() const { return m_buffer.size(); }
private:
//! the buffer where Lv2 reads/writes the data from/to
std::vector<float> m_buffer;
bool m_sidechain;
// the only case when data of m_buffer may be referenced:
friend struct ::ConnectPortVisitor;
};
struct AtomSeq : public VisitablePort<AtomSeq, PortBase>
{
enum FlagType
{
None = 0,
Midi = 1
};
unsigned flags = FlagType::None;
struct Lv2EvbufDeleter
{
void operator()(LV2_Evbuf* n);
};
using AutoLv2Evbuf = std::unique_ptr<LV2_Evbuf, Lv2EvbufDeleter>;
AutoLv2Evbuf m_buf;
};
struct Unknown : public VisitablePort<Unknown, PortBase>
{
};
/*
port casts
*/
template<class Target>
struct DCastVisitor : public Visitor
{
Target* m_result = nullptr;
void visit(Target& tar) { m_result = &tar; }
};
template<class Target>
struct ConstDCastVisitor : public ConstVisitor
{
const Target* m_result = nullptr;
void visit(const Target& tar) { m_result = &tar; }
};
//! If you don't want to use a whole visitor, you can use dcast
template<class Target>
Target* dcast(PortBase* base)
{
DCastVisitor<Target> vis;
base->accept(vis);
return vis.m_result;
}
//! const overload
template<class Target>
const Target* dcast(const PortBase* base)
{
ConstDCastVisitor<Target> vis;
base->accept(vis);
return vis.m_result;
}
} // namespace Lv2Ports
#endif // LMMS_HAVE_LV2
#endif // LV2PORTS_H

217
include/Lv2Proc.h Normal file
View File

@@ -0,0 +1,217 @@
/*
* Lv2Proc.h - Lv2 processor class
*
* Copyright (c) 2019-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 LV2PROC_H
#define LV2PROC_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lilv/lilv.h>
#include <memory>
#include <QObject>
#include "Lv2Basics.h"
#include "Lv2Features.h"
#include "Lv2Options.h"
#include "LinkedModelGroups.h"
#include "MidiEvent.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
{
struct Audio;
struct PortBase;
struct AtomSeq;
enum class Type;
enum class Flow;
enum class Vis;
}
//! Class representing one Lv2 processor, i.e. one Lv2 handle
//! For Mono effects, 1 Lv2ControlBase references 2 Lv2Proc
class Lv2Proc : public LinkedModelGroup
{
public:
static Plugin::PluginTypes check(const LilvPlugin* plugin,
std::vector<PluginIssue> &issues);
/*
ctor/dtor
*/
Lv2Proc(const LilvPlugin* plugin, Model *parent);
~Lv2Proc() override;
//! Must be checked after ctor or reload
bool isValid() const { return m_valid; }
/*
port access
*/
struct StereoPortRef
{
//! mono port or left port in case of stereo
Lv2Ports::Audio* m_left = nullptr;
//! unused, or right port in case of stereo
Lv2Ports::Audio* m_right = nullptr;
};
StereoPortRef& inPorts() { return m_inPorts; }
const StereoPortRef& inPorts() const { return m_inPorts; }
StereoPortRef& outPorts() { return m_outPorts; }
const StereoPortRef& outPorts() const { return m_outPorts; }
template<class Functor>
void foreach_port(const Functor& ftor)
{
for (std::unique_ptr<Lv2Ports::PortBase>& port : m_ports)
{
ftor(port.get());
}
}
template<class Functor>
void foreach_port(const Functor& ftor) const
{
for (const std::unique_ptr<Lv2Ports::PortBase>& port : m_ports)
{
ftor(port.get());
}
}
//! Debug function to print ports to stdout
void dumpPorts();
/*
utils for the run thread
*/
//! Copy values from the LMMS core (connected models, MIDI events, ...) into
//! the respective ports
void copyModelsFromCore();
//! Bring values from all ports to the LMMS core
void copyModelsToCore();
/**
* Copy buffer passed by the core into our ports
* @param buf buffer of sample frames, each sample frame is something like
* a `float[<number-of-procs> * <channels per proc>]` array.
* @param firstChan The offset for @p buf where we have to read our
* first channel.
* This marks the first sample in each sample frame where we read from.
* If we are the 2nd of 2 mono procs, this can be greater than 0.
* @param num Number of channels we must read from @param buf (starting at
* @p offset)
*/
void copyBuffersFromCore(const sampleFrame *buf,
unsigned firstChan, unsigned num, fpp_t frames);
/**
* Copy our ports into buffers passed by the core
* @param buf buffer of sample frames, each sample frame is something like
* a `float[<number-of-procs> * <channels per proc>]` array.
* @param firstChan The offset for @p buf where we have to write our
* first channel.
* This marks the first sample in each sample frame where we write to.
* If we are the 2nd of 2 mono procs, this can be greater than 0.
* @param num Number of channels we must write to @param buf (starting at
* @p offset)
*/
void copyBuffersToCore(sampleFrame *buf, unsigned firstChan, unsigned num,
fpp_t frames) const;
//! Run the Lv2 plugin instance for @param frames frames
void run(fpp_t frames);
void handleMidiInputEvent(const class MidiEvent &event,
const TimePos &time, f_cnt_t offset);
/*
misc
*/
class AutomatableModel *modelAtPort(const QString &uri); // unused currently
std::size_t controlCount() const { return LinkedModelGroup::modelNum(); }
bool hasNoteInput() const;
protected:
/*
load and save
*/
//! Create ports and instance, connect ports, activate plugin
void initPlugin();
//! Deactivate instance
void shutdownPlugin();
private:
bool m_valid = true;
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;
// quick reference to specific, unique ports
StereoPortRef m_inPorts, m_outPorts;
Lv2Ports::AtomSeq *m_midiIn = nullptr, *m_midiOut = nullptr;
// MIDI
// many things here may be moved into the `Instrument` class
constexpr const static std::size_t m_maxMidiInputEvents = 1024;
//! spinlock for the MIDI ringbuffer (for MIDI events going to the plugin)
std::atomic_flag m_ringLock = ATOMIC_FLAG_INIT;
//! MIDI ringbuffer (for MIDI events going to the plugin)
ringbuffer_t<struct MidiInputEvent> m_midiInputBuf;
//! MIDI ringbuffer reader
ringbuffer_reader_t<struct MidiInputEvent> m_midiInputReader;
// other
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
void loadFileInternal(const QString &file);
//! allocate m_ports, fill all with metadata, and assign meaning of ports
void createPorts();
//! fill m_ports[portNum] with metadata
void createPort(std::size_t portNum);
//! connect m_ports[portNum] with Lv2
void connectPort(std::size_t num);
void dumpPort(std::size_t num);
static bool portIsSideChain(const LilvPlugin* plugin, const LilvPort *port);
static bool portIsOptional(const LilvPlugin* plugin, const LilvPort *port);
static AutoLilvNode uri(const char* uriStr);
};
#endif // LMMS_HAVE_LV2
#endif // LV2PROC_H

View File

@@ -0,0 +1,62 @@
/*
* Lv2SubPluginFeatures.h - derivation from
* Plugin::Descriptor::SubPluginFeatures for
* hosting LV2 plugins
*
* Copyright (c) 2018-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 LV2_SUBPLUGIN_FEATURES_H
#define LV2_SUBPLUGIN_FEATURES_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lilv/lilv.h>
#include "lmms_export.h"
#include "Plugin.h"
class LMMS_EXPORT Lv2SubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures
{
private:
static const LilvPlugin *getPlugin(const Key &k);
static QString pluginName(const LilvPlugin *plug);
public:
Lv2SubPluginFeatures(Plugin::PluginTypes type);
void fillDescriptionWidget(
QWidget *parent, const Key *k) const override;
QString additionalFileExtensions(const Key &k) const override;
QString displayName(const Key &k) const override;
QString description(const Key &k) const override;
const PixmapLoader *logo(const Key &k) const override;
void listSubPluginKeys(
const Plugin::Descriptor *desc, KeyList &kl) const override;
};
#endif // LMMS_HAVE_LV2
#endif

70
include/Lv2UridCache.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Lv2UridCache.h - Lv2UridCache definition
*
* 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 LV2URIDCACHE_H
#define LV2URIDCACHE_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <QtGlobal>
#include <cstdint>
//! Cached URIDs for fast access (for use in real-time code)
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

70
include/Lv2UridMap.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Lv2UridMap.cpp - Lv2UridMap class
*
* Copyright (c) 2019 Johannes Lorenz <j.git$$$lorenz-ho.me, $$$=@>
*
* 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 LV2URIDMAP_H
#define LV2URIDMAP_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
#include <mutex> // TODO: use semaphore, even though this is not realtime critical
#include <string>
#include <unordered_map>
#include <vector>
/**
* Complete implementation of the Lv2 Urid Map extension
*/
class UridMap
{
std::unordered_map<std::string, LV2_URID> m_map;
std::vector<const char*> m_unMap;
//! mutex for both m_map and m_unMap
//! the URID map is global, which is why a mutex is required here
std::mutex m_MapMutex;
LV2_URID_Map m_mapFeature;
LV2_URID_Unmap m_unmapFeature;
LV2_URID m_lastUrid = 0;
public:
//! constructor; will set up the features
UridMap();
//! map feature function
LV2_URID map(const char* uri);
//! unmap feature function
const char* unmap(LV2_URID urid);
// access the features
LV2_URID_Map* mapFeature() { return &m_mapFeature; }
LV2_URID_Unmap* unmapFeature() { return &m_unmapFeature; }
};
#endif // LMMS_HAVE_LV2
#endif // LV2URIDMAP_H

98
include/Lv2ViewBase.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Lv2ViewBase.h - base class for Lv2 plugin views
*
* Copyright (c) 2018-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 LV2VIEWBASE_H
#define LV2VIEWBASE_H
#include "lmmsconfig.h"
#ifdef LMMS_HAVE_LV2
#include <QString>
#include <QVector>
#include "LinkedModelGroupViews.h"
#include "lmms_export.h"
#include "Lv2Basics.h"
class Lv2Proc;
class Lv2ControlBase;
//! View for one processor, Lv2ViewBase contains 2 of those for mono plugins
class Lv2ViewProc : public LinkedModelGroupView
{
public:
//! @param colNum numbers of columns for the controls
Lv2ViewProc(QWidget *parent, Lv2Proc *ctrlBase, int colNum);
~Lv2ViewProc();
private:
static AutoLilvNode uri(const char *uriStr);
};
//! Base class for view for one Lv2 plugin
class LMMS_EXPORT Lv2ViewBase : public LinkedModelGroupsView
{
protected:
//! @param pluginWidget A child class which inherits QWidget
Lv2ViewBase(class QWidget *pluginWidget, Lv2ControlBase *ctrlBase);
~Lv2ViewBase();
// these widgets must be connected by child widgets
class QPushButton *m_reloadPluginButton = nullptr;
class QPushButton *m_toggleUIButton = nullptr;
class QPushButton *m_helpButton = nullptr;
void toggleUI();
void toggleHelp(bool visible);
// to be called by child virtuals
//! Reconnect models if model changed
void modelChanged(Lv2ControlBase* ctrlBase);
private:
enum Rows
{
ButtonRow,
ProcRow,
LinkChannelsRow
};
static AutoLilvNode uri(const char *uriStr);
LinkedModelGroupView* getGroupView() override { return m_procView; }
Lv2ViewProc* m_procView;
//! Numbers of controls per row; must be multiple of 2 for mono effects
const int m_colNum = 6;
class QMdiSubWindow* m_helpWindow = nullptr;
class LedCheckBox *m_multiChannelLink;
};
#endif // LMMS_HAVE_LV2
#endif // LV2VIEWBASE_H

View File

@@ -63,7 +63,7 @@ public:
void addSpacingToToolBar( int _size );
// wrap the widget with a window decoration and add it to the workspace
SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags=0);
SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags = QFlag(0));
///
@@ -157,6 +157,7 @@ public slots:
void toggleFxMixerWin();
void togglePianoRollWin();
void toggleControllerRack();
void toggleFullscreen();
void updatePlayPauseIcons();
@@ -226,6 +227,8 @@ private:
ToolButton * m_metronomeToggle;
SessionState m_session;
bool maximized;
private slots:
void browseHelp();

View File

@@ -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;

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -26,8 +26,8 @@
#define MIDI_EVENT_PROCESSOR_H
#include "MidiEvent.h"
#include "MidiTime.h"
#include "Memory.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;
} ;

View File

@@ -0,0 +1,47 @@
/*
* MidiEventToByteSeq.h - writeToByteSeq declaration
*
* 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 MIDIEVENTTOBYTESEQ_H
#define MIDIEVENTTOBYTESEQ_H
#include <cstddef>
#include <cstdint>
#include "lmms_export.h"
/**
Write MIDI event into byte sequence.
Conforming to http://lv2plug.in/ns/ext/midi#MidiEvent
@param data Pointer to the target buffer for the byte sequence. Must
point to existing memory with at least 3 bytes size.
@param bufsize Available size of the target buffer.
@return Used size of the target buffer, or 0 if the MidiEvent could not
be converted.
*/
std::size_t LMMS_EXPORT writeToByteSeq( const class MidiEvent& ev,
uint8_t* data, std::size_t bufsize );
#endif // MIDIEVENTTOBYTESEQ_H

View File

@@ -31,7 +31,7 @@
#include <QtCore/QMap>
#include "Midi.h"
#include "MidiTime.h"
#include "TimePos.h"
#include "AutomatableModel.h"
@@ -96,11 +96,14 @@ public:
int realOutputChannel() const
{
return outputChannel() - 1;
// There's a possibility of outputChannel being 0 ("--"), which is used to keep all
// midi channels when forwarding. In that case, realOutputChannel will return the
// default channel 1 (whose value is 0).
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;

View File

@@ -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 );

View File

@@ -98,9 +98,9 @@ public:
Interpolation interpolation;
Oversampling oversampling;
qualitySettings( Mode _m )
qualitySettings(Mode m)
{
switch( _m )
switch (m)
{
case Mode_Draft:
interpolation = Interpolation_Linear;
@@ -118,9 +118,9 @@ public:
}
}
qualitySettings( Interpolation _i, Oversampling _o ) :
interpolation( _i ),
oversampling( _o )
qualitySettings(Interpolation i, Oversampling o) :
interpolation(i),
oversampling(o)
{
}
@@ -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,
@@ -188,14 +186,14 @@ public:
// audio-port-stuff
inline void addAudioPort( AudioPort * _port )
inline void addAudioPort(AudioPort * port)
{
requestChangeInModel();
m_audioPorts.push_back( _port );
m_audioPorts.push_back(port);
doneChangeInModel();
}
void removeAudioPort( AudioPort * _port );
void removeAudioPort(AudioPort * port);
// MIDI-client-stuff
@@ -220,7 +218,7 @@ public:
return m_playHandles;
}
void removePlayHandlesOfTypes( Track * _track, const quint8 types );
void removePlayHandlesOfTypes(Track * track, const quint8 types);
// methods providing information for other classes
@@ -257,23 +255,23 @@ public:
return m_masterGain;
}
inline void setMasterGain( const float _mo )
inline void setMasterGain(const float mo)
{
m_masterGain = _mo;
m_masterGain = mo;
}
static inline sample_t clip( const sample_t _s )
static inline sample_t clip(const sample_t s)
{
if( _s > 1.0f )
if (s > 1.0f)
{
return 1.0f;
}
else if( _s < -1.0f )
else if (s < -1.0f)
{
return -1.0f;
}
return _s;
return s;
}
@@ -283,7 +281,7 @@ public:
sample_t left;
sample_t right;
};
StereoSample getPeakValues(sampleFrame * _ab, const f_cnt_t _frames) const;
StereoSample getPeakValues(sampleFrame * ab, const f_cnt_t _frames) const;
bool criticalXRuns() const;
@@ -310,7 +308,7 @@ public:
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
}
void changeQuality( const struct qualitySettings & _qs );
void changeQuality(const struct qualitySettings & qs);
inline bool isMetronomeActive() const { return m_metronomeActive; }
inline void setMetronomeActive(bool value = true) { m_metronomeActive = value; }
@@ -335,7 +333,7 @@ private:
class fifoWriter : public QThread
{
public:
fifoWriter( Mixer * _mixer, fifo * _fifo );
fifoWriter(Mixer * mixer, fifo * _fifo);
void finish();
@@ -355,7 +353,7 @@ private:
Mixer( bool renderOnly );
virtual ~Mixer();
void startProcessing( bool _needs_fifo = true );
void startProcessing(bool needsFifo = true);
void stopProcessing();
@@ -365,6 +363,10 @@ private:
const surroundSampleFrame * renderNextBuffer();
void swapBuffers();
void handleMetronome();
void clearInternal();
//! Called by the audio thread to give control to other threads,
@@ -383,13 +385,8 @@ private:
int m_inputBufferRead;
int m_inputBufferWrite;
surroundSampleFrame * m_readBuf;
surroundSampleFrame * m_writeBuf;
QVector<surroundSampleFrame *> m_bufferPool;
int m_readBuffer;
int m_writeBuffer;
int m_poolDepth;
surroundSampleFrame * m_outputBufferRead;
surroundSampleFrame * m_outputBufferWrite;
// worker thread stuff
QVector<MixerWorkerThread *> m_workers;

View File

@@ -36,6 +36,7 @@ public:
virtual ~ModelView();
virtual void setModel( Model* model, bool isOldModelValid = true );
virtual void unsetModel();
Model* model()
{

View File

@@ -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;
};

View File

@@ -48,6 +48,9 @@ public:
void * m_pluginData;
std::unique_ptr<BasicFilters<>> m_filter;
// length of the declicking fade in
fpp_t m_fadeInLength;
// specifies origin of NotePlayHandle
enum Origins
{
@@ -240,19 +243,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;
}
@@ -319,7 +322,7 @@ private:
float m_unpitchedFrequency;
BaseDetuning* m_baseDetuning;
MidiTime m_songGlobalParentOffset;
TimePos m_songGlobalParentOffset;
int m_midiChannel;
Origin m_origin;

View File

@@ -97,7 +97,7 @@ public:
static inline sample_t triangleSample( const float _sample )
{
const float ph = fraction( _sample );
const float ph = absFraction( _sample );
if( ph <= 0.25f )
{
return ph * 4.0f;
@@ -111,17 +111,17 @@ public:
static inline sample_t sawSample( const float _sample )
{
return -1.0f + fraction( _sample ) * 2.0f;
return -1.0f + absFraction( _sample ) * 2.0f;
}
static inline sample_t squareSample( const float _sample )
{
return ( fraction( _sample ) > 0.5f ) ? -1.0f : 1.0f;
return ( absFraction( _sample ) > 0.5f ) ? -1.0f : 1.0f;
}
static inline sample_t moogSawSample( const float _sample )
{
const float ph = fraction( _sample );
const float ph = absFraction( _sample );
if( ph < 0.5f )
{
return -1.0f + ph * 4.0f;
@@ -131,7 +131,7 @@ public:
static inline sample_t expSample( const float _sample )
{
float ph = fraction( _sample );
float ph = absFraction( _sample );
if( ph > 0.5f )
{
ph = 1.0f - ph;

View File

@@ -37,7 +37,6 @@ class Oscilloscope : public QWidget
Q_OBJECT
public:
Q_PROPERTY( QColor normalColor READ normalColor WRITE setNormalColor )
Q_PROPERTY( QColor warningColor READ warningColor WRITE setWarningColor )
Q_PROPERTY( QColor clippingColor READ clippingColor WRITE setClippingColor )
Oscilloscope( QWidget * _parent );
@@ -48,9 +47,6 @@ public:
QColor const & normalColor() const;
void setNormalColor(QColor const & normalColor);
QColor const & warningColor() const;
void setWarningColor(QColor const & warningColor);
QColor const & clippingColor() const;
void setClippingColor(QColor const & clippingColor);
@@ -74,7 +70,6 @@ private:
bool m_active;
QColor m_normalColor;
QColor m_warningColor;
QColor m_clippingColor;
} ;

41
include/PathUtil.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef PATHUTIL_H
#define PATHUTIL_H
#include "lmms_export.h"
#include <QDir>
namespace PathUtil
{
enum class Base { Absolute, ProjectDir, FactorySample, UserSample, UserVST, Preset,
UserLADSPA, DefaultLADSPA, UserSoundfont, DefaultSoundfont, UserGIG, DefaultGIG };
//! Return the directory associated with a given base as a QString
QString LMMS_EXPORT baseLocation(const Base base);
//! Return the directory associated with a given base as a QDir
QDir LMMS_EXPORT baseQDir (const Base base);
//! Return the prefix used to denote this base in path strings
QString LMMS_EXPORT basePrefix(const Base base);
//! Check the prefix of a path and return the base it corresponds to
//! Defaults to Base::Absolute
Base LMMS_EXPORT baseLookup(const QString & path);
//! Remove the prefix from a path, iff there is one
QString LMMS_EXPORT stripPrefix(const QString & path);
//! Get the filename for a path, handling prefixed paths correctly
QString LMMS_EXPORT cleanName(const QString & path);
//! Upgrade prefix-less relative paths to the new format
QString LMMS_EXPORT oldRelativeUpgrade(const QString & input);
//! Make this path absolute
QString LMMS_EXPORT toAbsolute(const QString & input);
//! Make this path relative to a given base, return an absolute path if that fails
QString LMMS_EXPORT relativeOrAbsolute(const QString & input, const Base base);
//! Make this path relative to any base, choosing the shortest if there are
//! multiple options. Defaults to an absolute path if all bases fail.
QString LMMS_EXPORT toShortestRelative(const QString & input);
}
#endif

View File

@@ -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();

View File

@@ -40,6 +40,7 @@
#include "ToolTip.h"
#include "StepRecorder.h"
#include "StepRecorderWidget.h"
#include "PositionLine.h"
class QPainter;
class QPixmap;
@@ -55,25 +56,38 @@ class TimeLineWidget;
class PianoRoll : public QWidget
{
Q_OBJECT
Q_PROPERTY( QColor barLineColor READ barLineColor WRITE setBarLineColor )
Q_PROPERTY( QColor beatLineColor READ beatLineColor WRITE setBeatLineColor )
Q_PROPERTY( QColor lineColor READ lineColor WRITE setLineColor )
Q_PROPERTY( QColor noteModeColor READ noteModeColor WRITE setNoteModeColor )
Q_PROPERTY( QColor noteColor READ noteColor WRITE setNoteColor )
Q_PROPERTY( QColor ghostNoteColor READ ghostNoteColor WRITE setGhostNoteColor )
Q_PROPERTY( QColor noteTextColor READ noteTextColor WRITE setNoteTextColor )
Q_PROPERTY( QColor ghostNoteTextColor READ ghostNoteTextColor WRITE setGhostNoteTextColor )
Q_PROPERTY( QColor barColor READ barColor WRITE setBarColor )
Q_PROPERTY( QColor selectedNoteColor READ selectedNoteColor WRITE setSelectedNoteColor )
Q_PROPERTY( QColor textColor READ textColor WRITE setTextColor )
Q_PROPERTY( QColor textColorLight READ textColorLight WRITE setTextColorLight )
Q_PROPERTY( QColor textShadow READ textShadow WRITE setTextShadow )
Q_PROPERTY( QColor markedSemitoneColor READ markedSemitoneColor WRITE setMarkedSemitoneColor )
Q_PROPERTY( int noteOpacity READ noteOpacity WRITE setNoteOpacity )
Q_PROPERTY( bool noteBorders READ noteBorders WRITE setNoteBorders )
Q_PROPERTY( int ghostNoteOpacity READ ghostNoteOpacity WRITE setGhostNoteOpacity )
Q_PROPERTY( bool ghostNoteBorders READ ghostNoteBorders WRITE setGhostNoteBorders )
Q_PROPERTY( QColor backgroundShade READ backgroundShade WRITE setBackgroundShade )
Q_PROPERTY(QColor barLineColor MEMBER m_barLineColor)
Q_PROPERTY(QColor beatLineColor MEMBER m_beatLineColor)
Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
Q_PROPERTY(QColor noteModeColor MEMBER m_noteModeColor)
Q_PROPERTY(QColor noteColor MEMBER m_noteColor)
Q_PROPERTY(QColor ghostNoteColor MEMBER m_ghostNoteColor)
Q_PROPERTY(QColor noteTextColor MEMBER m_noteTextColor)
Q_PROPERTY(QColor ghostNoteTextColor MEMBER m_ghostNoteTextColor)
Q_PROPERTY(QColor barColor MEMBER m_barColor)
Q_PROPERTY(QColor selectedNoteColor MEMBER m_selectedNoteColor)
Q_PROPERTY(QColor textColor MEMBER m_textColor)
Q_PROPERTY(QColor textColorLight MEMBER m_textColorLight)
Q_PROPERTY(QColor textShadow MEMBER m_textShadow)
Q_PROPERTY(QColor markedSemitoneColor MEMBER m_markedSemitoneColor)
Q_PROPERTY(int noteOpacity MEMBER m_noteOpacity)
Q_PROPERTY(bool noteBorders MEMBER m_noteBorders)
Q_PROPERTY(int ghostNoteOpacity MEMBER m_ghostNoteOpacity)
Q_PROPERTY(bool ghostNoteBorders MEMBER m_ghostNoteBorders)
Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
/* white key properties */
Q_PROPERTY(int whiteKeyWidth MEMBER m_whiteKeyWidth)
Q_PROPERTY(QColor whiteKeyInactiveTextColor MEMBER m_whiteKeyInactiveTextColor)
Q_PROPERTY(QColor whiteKeyInactiveTextShadow MEMBER m_whiteKeyInactiveTextShadow)
Q_PROPERTY(QBrush whiteKeyInactiveBackground MEMBER m_whiteKeyInactiveBackground)
Q_PROPERTY(QColor whiteKeyActiveTextColor MEMBER m_whiteKeyActiveTextColor)
Q_PROPERTY(QColor whiteKeyActiveTextShadow MEMBER m_whiteKeyActiveTextShadow)
Q_PROPERTY(QBrush whiteKeyActiveBackground MEMBER m_whiteKeyActiveBackground)
/* black key properties */
Q_PROPERTY(int blackKeyWidth MEMBER m_blackKeyWidth)
Q_PROPERTY(QBrush blackKeyInactiveBackground MEMBER m_blackKeyInactiveBackground)
Q_PROPERTY(QBrush blackKeyActiveBackground MEMBER m_blackKeyActiveBackground)
public:
enum EditModes
{
@@ -125,47 +139,6 @@ public:
int quantization() const;
// qproperty access functions
QColor barLineColor() const;
void setBarLineColor( const QColor & c );
QColor beatLineColor() const;
void setBeatLineColor( const QColor & c );
QColor lineColor() const;
void setLineColor( const QColor & c );
QColor noteModeColor() const;
void setNoteModeColor( const QColor & c );
QColor noteColor() const;
void setNoteColor( const QColor & c );
QColor noteTextColor() const;
void setNoteTextColor( const QColor & c );
QColor barColor() const;
void setBarColor( const QColor & c );
QColor selectedNoteColor() const;
void setSelectedNoteColor( const QColor & c );
QColor textColor() const;
void setTextColor( const QColor & c );
QColor textColorLight() const;
void setTextColorLight( const QColor & c );
QColor textShadow() const;
void setTextShadow( const QColor & c );
QColor markedSemitoneColor() const;
void setMarkedSemitoneColor( const QColor & c );
int noteOpacity() const;
void setNoteOpacity( const int i );
bool noteBorders() const;
void setNoteBorders( const bool b );
QColor ghostNoteColor() const;
void setGhostNoteColor( const QColor & c );
QColor ghostNoteTextColor() const;
void setGhostNoteTextColor( const QColor & c );
int ghostNoteOpacity() const;
void setGhostNoteOpacity( const int i );
bool ghostNoteBorders() const;
void setGhostNoteBorders( const bool b );
QColor backgroundShade() const;
void setBackgroundShade( const QColor & c );
protected:
void keyPressEvent( QKeyEvent * ke ) override;
void keyReleaseEvent( QKeyEvent * ke ) override;
@@ -178,6 +151,7 @@ protected:
void resizeEvent( QResizeEvent * re ) override;
void wheelEvent( QWheelEvent * we ) override;
void focusOutEvent( QFocusEvent * ) override;
void focusInEvent( QFocusEvent * ) override;
int getKey( int y ) const;
void drawNoteRect( QPainter & p, int x, int y,
@@ -185,9 +159,8 @@ protected:
const QColor & selCol, const int noteOpc, const bool borderless, bool drawNoteName );
void removeSelection();
void selectAll();
NoteVector getSelectedNotes();
NoteVector getSelectedNotes() const;
void selectNotesOnKey();
int xCoordOfTick( int tick );
// for entering values with dblclick in the vol/pan bars
void enterValue( NoteVector* nv );
@@ -212,28 +185,30 @@ protected slots:
void copySelectedNotes();
void cutSelectedNotes();
void pasteNotes();
void deleteSelectedNotes();
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();
void quantizeChanged();
void noteLengthChanged();
void keyChanged();
void quantizeNotes();
void updateSemiToneMarkerMenu();
void changeNoteEditMode( int i );
void markSemiTone( int i );
void markSemiTone(int i, bool fromMenu = true);
void hidePattern( Pattern* pattern );
void selectRegionFromPixels( int xStart, int xEnd );
void clearGhostPattern();
void glueNotes();
signals:
@@ -278,6 +253,8 @@ private:
PR_BLACK_KEY
};
PositionLine * m_positionLine;
QVector<QString> m_nemStr; // gui names of each edit mode
QMenu * m_noteEditMenu; // when you right click below the key area
@@ -289,12 +266,14 @@ 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);
void shiftSemiTone(int amount);
void shiftSemiTone(NoteVector notes, int amount);
bool isSelection() const;
int selectionCount() const;
void testPlayNote( Note * n );
@@ -303,6 +282,9 @@ private:
void playChordNotes(int key, int velocity=-1);
void pauseChordNotes(int key);
void updateScrollbars();
void updatePositionLineHeight();
QList<int> getAllOctavesForKey( int keyToMirror ) const;
int noteEditTop() const;
@@ -317,12 +299,6 @@ private:
static const int cm_scrollAmtHoriz = 10;
static const int cm_scrollAmtVert = 1;
static QPixmap * s_whiteKeyBigPm;
static QPixmap * s_whiteKeyBigPressedPm;
static QPixmap * s_whiteKeySmallPm;
static QPixmap * s_whiteKeySmallPressedPm;
static QPixmap * s_blackKeyPm;
static QPixmap * s_blackKeyPressedPm;
static QPixmap * s_toolDraw;
static QPixmap * s_toolErase;
static QPixmap * s_toolSelect;
@@ -337,6 +313,7 @@ private:
ComboBoxModel m_zoomingYModel;
ComboBoxModel m_quantizeModel;
ComboBoxModel m_noteLenModel;
ComboBoxModel m_keyModel;
ComboBoxModel m_scaleModel;
ComboBoxModel m_chordModel;
@@ -354,7 +331,7 @@ private:
QScrollBar * m_leftRightScroll;
QScrollBar * m_topBottomScroll;
MidiTime m_currentPosition;
TimePos m_currentPosition;
bool m_recording;
QList<Note> m_recordingNotes;
@@ -386,10 +363,11 @@ private:
int m_moveStartX;
int m_moveStartY;
int m_oldNotesEditHeight;
int m_notesEditHeight;
int m_userSetNotesEditHeight;
int m_ppb; // pixels per bar
int m_totalKeysToScroll;
int m_pianoKeysVisible;
int m_keyLineHeight;
int m_octaveHeight;
@@ -399,10 +377,13 @@ 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
TimePos m_minResizeLen;
int m_startKey; // first key when drawing
int m_lastKey;
@@ -452,9 +433,21 @@ private:
bool m_noteBorders;
bool m_ghostNoteBorders;
QColor m_backgroundShade;
/* white key properties */
int m_whiteKeyWidth;
QColor m_whiteKeyActiveTextColor;
QColor m_whiteKeyActiveTextShadow;
QBrush m_whiteKeyActiveBackground;
QColor m_whiteKeyInactiveTextColor;
QColor m_whiteKeyInactiveTextShadow;
QBrush m_whiteKeyInactiveBackground;
/* black key properties */
int m_blackKeyWidth;
QBrush m_blackKeyActiveBackground;
QBrush m_blackKeyInactiveBackground;
signals:
void positionChanged( const MidiTime & );
void positionChanged( const TimePos & );
} ;
@@ -495,6 +488,7 @@ public:
}
QSize sizeHint() const override;
bool hasFocus() const;
signals:
void currentPatternChanged();
@@ -516,6 +510,7 @@ private:
ComboBox * m_zoomingYComboBox;
ComboBox * m_quantizeComboBox;
ComboBox * m_noteLenComboBox;
ComboBox * m_keyComboBox;
ComboBox * m_scaleComboBox;
ComboBox * m_chordComboBox;
QPushButton * m_clearGhostButton;

View File

@@ -56,6 +56,7 @@ protected:
void mouseReleaseEvent( QMouseEvent * me ) override;
void mouseMoveEvent( QMouseEvent * me ) override;
void focusOutEvent( QFocusEvent * _fe ) override;
void focusInEvent( QFocusEvent * fe ) override;
void resizeEvent( QResizeEvent * _event ) override;

View File

@@ -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;
};

View File

@@ -32,16 +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
};
@@ -58,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);
};

49
include/PositionLine.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* PositionLine.h - declaration of class PositionLine, a simple widget that
* draws a line, mainly works with TimeLineWidget
*
* 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 POSITION_LINE_H
#define POSITION_LINE_H
#include <QWidget>
class PositionLine : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool tailGradient MEMBER m_hasTailGradient)
Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
public:
PositionLine(QWidget* parent);
public slots:
void zoomChange(double zoom);
private:
void paintEvent(QPaintEvent* pe) override;
bool m_hasTailGradient;
QColor m_lineColor;
};
#endif

View File

@@ -29,6 +29,7 @@
#include "NotePlayHandle.h"
class DataFile;
class InstrumentTrack;
class PreviewTrackContainer;

View File

@@ -28,6 +28,9 @@
#define PROJECT_VERSION_H
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <limits>
#include "lmms_export.h"
/*! \brief Version number parsing and comparison
@@ -37,16 +40,17 @@
class LMMS_EXPORT ProjectVersion
{
public:
enum CompareType { Major, Minor, Release, Stage, Build };
enum CompareType : int { None = 0, Major=1, Minor=2, Release=3, Stage=4, Build=5, All = std::numeric_limits<int>::max() };
ProjectVersion(QString version, CompareType c = Build);
ProjectVersion(const char * version, CompareType c = Build);
ProjectVersion(QString version, CompareType c = All);
ProjectVersion(const char * version, CompareType c = All);
const QString& getVersion() const { return m_version; }
int getMajor() const { return m_major; }
int getMinor() const { return m_minor; }
int getRelease() const { return m_release; }
QString getStage() const { return m_stage; }
int getBuild() const { return m_build; }
int getPatch() const { return m_patch; }
const QStringList& getLabels() const { return m_labels; }
CompareType getCompareType() const { return m_compareType; }
ProjectVersion setCompareType(CompareType compareType) { m_compareType = compareType; return * this; }
@@ -55,11 +59,10 @@ public:
private:
QString m_version;
int m_major;
int m_minor;
int m_release;
QString m_stage;
int m_build;
int m_major = 0;
int m_minor = 0;
int m_patch = 0;
QStringList m_labels;
CompareType m_compareType;
} ;

View File

@@ -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,11 +80,11 @@ public:
return m_isBackwards;
}
void setBackwards( bool _backwards )
void setBackwards(bool backwards)
{
m_isBackwards = _backwards;
m_isBackwards = backwards;
}
int interpolationMode() const
{
return m_interpolationMode;
@@ -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()
@@ -251,38 +268,44 @@ public:
m_varLock.unlock();
}
static QString tryToMakeRelative( const QString & _file );
static QString tryToMakeAbsolute(const QString & file);
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;
@@ -299,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:

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -75,6 +75,8 @@ 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);
void toggleOpenLastProject(bool enabled);
@@ -132,6 +134,8 @@ private:
bool m_compactTrackButtons;
bool m_oneInstrumentTrackWindow;
bool m_sideBarOnRight;
bool m_letPreviewsFinish;
bool m_soloLegacyBehavior;
bool m_MMPZ;
bool m_disableBackup;
bool m_openLastProject;
@@ -175,6 +179,7 @@ private:
QComboBox * m_midiInterfaces;
MswMap m_midiIfaceSetupWidgets;
trMap m_midiIfaceNames;
QComboBox * m_assignableMidiDevices;
// Paths settings widgets.
QString m_workingDir;

View File

@@ -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);
@@ -441,7 +447,7 @@ private:
SaveOptions m_saveOptions;
QStringList m_errors;
QHash<QString, int> m_errors;
PlayModes m_playMode;
PlayPos m_playPos[Mode_Count];
@@ -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;

View File

@@ -28,10 +28,12 @@
#define SONG_EDITOR_H
#include <QVector>
#include <QLinearGradient>
#include "ActionGroup.h"
#include "Editor.h"
#include "TrackContainerView.h"
#include "PositionLine.h"
class QLabel;
class QScrollBar;
@@ -45,16 +47,6 @@ class Song;
class TextFloat;
class TimeLineWidget;
class positionLine : public QWidget
{
public:
positionLine( QWidget * parent );
private:
void paintEvent( QPaintEvent * pe ) override;
} ;
class SongEditor : public TrackContainerView
{
@@ -88,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 );
@@ -140,7 +132,7 @@ private:
TextFloat * m_mvsStatus;
TextFloat * m_mpsStatus;
positionLine * m_positionLine;
PositionLine * m_positionLine;
ComboBoxModel* m_zoomingModel;
ComboBoxModel* m_snappingModel;
@@ -158,12 +150,15 @@ 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;
friend class SongEditorWindow;
signals:
void zoomingValueChanged( double );
} ;
@@ -215,6 +210,9 @@ private:
ComboBox * m_zoomingComboBox;
ComboBox * m_snappingComboBox;
QLabel* m_snapSizeLabel;
QAction* m_insertBarAction;
QAction* m_removeBarAction;
};
#endif

View File

@@ -21,7 +21,7 @@
#ifndef STEP_RECORDER_H
#define STEP_RECORDER_H
#include <QTime>
#include <QElapsedTimer>
#include <QTimer>
#include <QObject>
#include <QKeyEvent>
@@ -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;
@@ -130,7 +130,7 @@ class StepRecorder : public QObject
private:
bool m_pressed;
QTime releasedTimer;
QElapsedTimer releasedTimer;
} ;
QVector<StepNote*> m_curStepNotes; // contains the current recorded step notes (i.e. while user still press the notes; before they are applied to the pattern)
@@ -140,4 +140,4 @@ class StepRecorder : public QObject
bool m_isStepInProgress = false;
};
#endif //STEP_RECORDER_H
#endif //STEP_RECORDER_H

View File

@@ -44,13 +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();
@@ -60,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;
@@ -86,7 +88,7 @@ private:
const int m_marginRight;
signals:
void positionChanged(const MidiTime & t);
void positionChanged(const TimePos & t);
} ;
#endif //STEP_RECOREDER_WIDGET_H

View File

@@ -45,16 +45,8 @@ public:
static bool processDragEnterEvent( QDragEnterEvent * _dee,
const QString & _allowed_keys );
static QString decodeMimeKey( const QMimeData * mimeData );
static QString decodeMimeValue( const QMimeData * mimeData );
static QString decodeKey( QDropEvent * _de );
static QString decodeValue( QDropEvent * _de );
static const char * mimeType()
{
return( "application/x-lmms-stringpair" );
}
} ;

View File

@@ -55,7 +55,7 @@ class LMMS_EXPORT SubWindow : public QMdiSubWindow
Q_PROPERTY( QColor borderColor READ borderColor WRITE setBorderColor )
public:
SubWindow( QWidget *parent = NULL, Qt::WindowFlags windowFlags = 0 );
SubWindow( QWidget *parent = NULL, Qt::WindowFlags windowFlags = QFlag(0) );
// same as QWidet::normalGeometry, but works properly under X11 (see https://bugreports.qt.io/browse/QTBUG-256)
QRect getTrueNormalGeometry() const;
QBrush activeColor() const;

View File

@@ -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;
}
@@ -150,6 +150,8 @@ public:
update();
}
void setXOffset(const int x);
void addToolButtons(QToolBar* _tool_bar );
@@ -160,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:
@@ -173,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 );
@@ -216,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;
@@ -240,9 +242,10 @@ private:
signals:
void positionChanged( const MidiTime & _t );
void positionChanged( const TimePos & _t );
void loopPointStateLoaded( int _n );
void positionMarkerMoved();
void loadBehaviourAtStop( int _n );
} ;

View File

@@ -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 );

View File

@@ -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,42 +25,22 @@
#ifndef TRACK_H
#define TRACK_H
#include <QtCore/QVector>
#include <QtCore/QList>
#include <QWidget>
#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
@@ -70,409 +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;
}
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 );
public slots:
void copy();
void paste();
void toggleMute();
signals:
void lengthChanged();
void positionChanged();
void destroyedTCO();
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;
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 )
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 );
// access needsUpdate member variable
bool needsUpdate();
void setNeedsUpdate( bool b );
public slots:
virtual bool close();
void cut();
void remove();
void update() override;
protected:
virtual void constructContextMenu( QMenu * )
{
}
void contextMenuEvent( QContextMenuEvent * cme ) override;
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;
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 pasteSelection( MidiTime tcoPos, QDropEvent * de );
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:
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 toggleRecording(bool on);
void recordingOn();
void recordingOff();
void clearTrack();
private:
static QPixmap * s_grip;
TrackView * m_trackView;
QPushButton * m_trackOps;
PixmapButton * m_muteBtn;
PixmapButton * m_soloBtn;
friend class TrackView;
signals:
void trackRemovalScheduled( TrackView * t );
} ;
// base-class for all tracks
//! Base-class for all tracks
class LMMS_EXPORT Track : public Model, public JournallingObject
{
Q_OBJECT
@@ -509,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;
@@ -543,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;
@@ -597,7 +177,16 @@ public:
{
return m_processingLock.tryLock();
}
QColor color()
{
return m_color;
}
bool useColor()
{
return m_hasColor;
}
BoolModel* getMutedModel();
public slots:
@@ -609,6 +198,8 @@ public slots:
void toggleSolo();
void trackColorChanged( QColor & c );
void trackColorReset();
private:
TrackContainer* m_trackContainer;
@@ -627,6 +218,9 @@ private:
tcoVector m_trackContentObjects;
QMutex m_processingLock;
QColor m_color;
bool m_hasColor;
friend class TrackView;
@@ -640,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

View File

@@ -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

View File

@@ -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 );
} ;

View 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

Some files were not shown because too many files have changed in this diff Show More