Merge branch 'master' into dynamic-effect-dialog

This commit is contained in:
Hyunjin Song
2022-11-11 11:33:17 +09:00
2534 changed files with 532640 additions and 215432 deletions

View File

@@ -30,6 +30,8 @@
#include "ui_about_dialog.h"
namespace lmms::gui
{
class AboutDialog : public QDialog, public Ui::AboutDialog
{
@@ -38,6 +40,7 @@ public:
} ;
} // namespace lmms::gui
#endif

View File

@@ -28,6 +28,9 @@
#include <QActionGroup>
namespace lmms::gui
{
/// \brief Convenience subclass of QActionGroup
///
/// This class provides the same functionality as QActionGroup, but in addition
@@ -54,4 +57,6 @@ private:
QList<QAction*> m_actions;
};
} // namespace lmms::gui
#endif

View File

@@ -37,6 +37,8 @@
#include "AudioDevice.h"
namespace lmms
{
class AudioAlsa : public QThread, public AudioDevice
{
@@ -52,7 +54,7 @@ public:
m_deviceName(deviceName),
m_deviceDescription(deviceDescription)
{}
~DeviceInfo() {}
~DeviceInfo() = default;
QString const & getDeviceName() const { return m_deviceName; }
QString const & getDeviceDescription() const { return m_deviceDescription; }
@@ -63,15 +65,15 @@ public:
};
typedef std::vector<DeviceInfo> DeviceInfoCollection;
using DeviceInfoCollection = std::vector<DeviceInfo>;
public:
AudioAlsa( bool & _success_ful, Mixer* mixer );
virtual ~AudioAlsa();
AudioAlsa( bool & _success_ful, AudioEngine* audioEngine );
~AudioAlsa() override;
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget",
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
"ALSA (Advanced Linux Sound Architecture)" );
}
@@ -80,10 +82,10 @@ public:
static DeviceInfoCollection getAvailableDevices();
private:
virtual void startProcessing();
virtual void stopProcessing();
virtual void applyQualitySettings();
virtual void run();
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
void run() override;
int setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access );
int setSWParams();
@@ -102,6 +104,8 @@ private:
} ;
#endif
} // namespace lmms
#endif // LMMS_HAVE_ALSA
#endif

View File

@@ -35,8 +35,11 @@
class QComboBox;
class LcdSpinBox;
namespace lmms::gui
{
class LcdSpinBox;
class AudioAlsaSetupWidget : public AudioDeviceSetupWidget
{
@@ -44,9 +47,9 @@ class AudioAlsaSetupWidget : public AudioDeviceSetupWidget
public:
AudioAlsaSetupWidget( QWidget * _parent );
virtual ~AudioAlsaSetupWidget();
~AudioAlsaSetupWidget() override;
virtual void saveSettings();
void saveSettings() override;
public slots:
void onCurrentIndexChanged(int index);
@@ -59,6 +62,8 @@ private:
AudioAlsa::DeviceInfoCollection m_deviceInfos;
};
#endif
} // namespace lmms::gui
#endif // LMMS_HAVE_ALSA
#endif

View File

@@ -1,5 +1,5 @@
/*
* AudioDevice.h - base-class for audio-devices, used by LMMS-mixer
* AudioDevice.h - base-class for audio-devices, used by LMMS audio engine
*
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -25,21 +25,24 @@
#ifndef AUDIO_DEVICE_H
#define AUDIO_DEVICE_H
#include <QtCore/QMutex>
#include <QMutex>
#include <samplerate.h>
#include "lmms_basics.h"
class AudioPort;
class Mixer;
class QThread;
namespace lmms
{
class AudioEngine;
class AudioPort;
class AudioDevice
{
public:
AudioDevice( const ch_cnt_t _channels, Mixer* mixer );
AudioDevice( const ch_cnt_t _channels, AudioEngine* audioEngine );
virtual ~AudioDevice();
inline void lock()
@@ -115,7 +118,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,
@@ -126,9 +129,9 @@ protected:
m_sampleRate = _new_sr;
}
Mixer* mixer()
AudioEngine* audioEngine()
{
return m_mixer;
return m_audioEngine;
}
bool hqAudio() const;
@@ -143,7 +146,7 @@ protected:
private:
sample_rate_t m_sampleRate;
ch_cnt_t m_channels;
Mixer* m_mixer;
AudioEngine* m_audioEngine;
bool m_inProcess;
QMutex m_devMutex;
@@ -153,7 +156,8 @@ private:
surroundSampleFrame * m_buffer;
} ;
};
} // namespace lmms
#endif

View File

@@ -27,6 +27,8 @@
#include "TabWidget.h"
namespace lmms::gui
{
class AudioDeviceSetupWidget : public TabWidget
{
@@ -34,12 +36,13 @@ class AudioDeviceSetupWidget : public TabWidget
public:
AudioDeviceSetupWidget( const QString & _caption, QWidget * _parent );
virtual ~AudioDeviceSetupWidget();
~AudioDeviceSetupWidget() override = default;
virtual void saveSettings() = 0;
virtual void show();
};
} // namespace lmms::gui
#endif

View File

@@ -27,48 +27,48 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
#include "AudioEngine.h"
#include "MicroTimer.h"
#include "Mixer.h"
namespace lmms
{
class AudioDummy : public QThread, public AudioDevice
{
Q_OBJECT
public:
AudioDummy( bool & _success_ful, Mixer* mixer ) :
AudioDevice( DEFAULT_CHANNELS, mixer )
AudioDummy( bool & _success_ful, AudioEngine* audioEngine ) :
AudioDevice( DEFAULT_CHANNELS, audioEngine )
{
_success_ful = true;
}
virtual ~AudioDummy()
~AudioDummy() override
{
stopProcessing();
}
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "Dummy (no sound output)" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "Dummy (no sound output)" );
}
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent ) :
AudioDeviceSetupWidget( AudioDummy::name(), _parent )
gui::AudioDeviceSetupWidget( AudioDummy::name(), _parent )
{
}
virtual ~setupWidget()
~setupWidget() override = default;
void saveSettings() override
{
}
virtual void saveSettings()
{
}
virtual void show()
void show() override
{
parentWidget()->hide();
QWidget::show();
@@ -78,33 +78,33 @@ public:
private:
virtual void startProcessing()
void startProcessing() override
{
start();
}
virtual void stopProcessing()
void stopProcessing() override
{
stopProcessingThread( this );
}
virtual void run()
void run() override
{
MicroTimer timer;
while( true )
{
timer.reset();
const surroundSampleFrame* b = mixer()->nextBuffer();
const surroundSampleFrame* b = audioEngine()->nextBuffer();
if( !b )
{
break;
}
if( mixer()->hasFifoWriter() )
if( audioEngine()->hasFifoWriter() )
{
delete[] b;
}
const int microseconds = static_cast<int>( mixer()->framesPerPeriod() * 1000000.0f / mixer()->processingSampleRate() - timer.elapsed() );
const int microseconds = static_cast<int>( audioEngine()->framesPerPeriod() * 1000000.0f / audioEngine()->processingSampleRate() - timer.elapsed() );
if( microseconds > 0 )
{
usleep( microseconds );
@@ -114,5 +114,6 @@ private:
} ;
} // namespace lmms
#endif

490
include/AudioEngine.h Normal file
View File

@@ -0,0 +1,490 @@
/*
* AudioEngine.h - device-independent audio engine for LMMS
*
* 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 AUDIO_ENGINE_H
#define AUDIO_ENGINE_H
#include <QMutex>
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
#include <QRecursiveMutex>
#endif
#include <QThread>
#include <QVector>
#include <QWaitCondition>
#include <samplerate.h>
#include "lmms_basics.h"
#include "LocklessList.h"
#include "FifoBuffer.h"
#include "AudioEngineProfiler.h"
#include "PlayHandle.h"
namespace lmms
{
class AudioDevice;
class MidiClient;
class AudioPort;
class AudioEngineWorkerThread;
const fpp_t MINIMUM_BUFFER_SIZE = 32;
const fpp_t DEFAULT_BUFFER_SIZE = 256;
const int BYTES_PER_SAMPLE = sizeof( sample_t );
const int BYTES_PER_INT_SAMPLE = sizeof( int_sample_t );
const int BYTES_PER_FRAME = sizeof( sampleFrame );
const int BYTES_PER_SURROUND_FRAME = sizeof( surroundSampleFrame );
const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
class LMMS_EXPORT AudioEngine : public QObject
{
Q_OBJECT
public:
/**
* @brief RAII helper for requestChangesInModel.
* Used by AudioEngine::requestChangesGuard.
*/
class RequestChangesGuard {
friend class AudioEngine;
private:
RequestChangesGuard(AudioEngine* audioEngine)
: m_audioEngine{audioEngine}
{
m_audioEngine->requestChangeInModel();
}
public:
RequestChangesGuard()
: m_audioEngine{nullptr}
{
}
RequestChangesGuard(RequestChangesGuard&& other)
: RequestChangesGuard()
{
std::swap(other.m_audioEngine, m_audioEngine);
}
// Disallow copy.
RequestChangesGuard(const RequestChangesGuard&) = delete;
RequestChangesGuard& operator=(const RequestChangesGuard&) = delete;
~RequestChangesGuard() {
if (m_audioEngine) {
m_audioEngine->doneChangeInModel();
}
}
private:
AudioEngine* m_audioEngine;
};
struct qualitySettings
{
enum Mode
{
Mode_Draft,
Mode_HighQuality,
Mode_FinalMix
} ;
enum Interpolation
{
Interpolation_Linear,
Interpolation_SincFastest,
Interpolation_SincMedium,
Interpolation_SincBest
} ;
enum Oversampling
{
Oversampling_None,
Oversampling_2x,
Oversampling_4x,
Oversampling_8x
} ;
Interpolation interpolation;
Oversampling oversampling;
qualitySettings(Mode m)
{
switch (m)
{
case Mode_Draft:
interpolation = Interpolation_Linear;
oversampling = Oversampling_None;
break;
case Mode_HighQuality:
interpolation =
Interpolation_SincFastest;
oversampling = Oversampling_2x;
break;
case Mode_FinalMix:
interpolation = Interpolation_SincBest;
oversampling = Oversampling_8x;
break;
}
}
qualitySettings(Interpolation i, Oversampling o) :
interpolation(i),
oversampling(o)
{
}
int sampleRateMultiplier() const
{
switch( oversampling )
{
case Oversampling_None: return 1;
case Oversampling_2x: return 2;
case Oversampling_4x: return 4;
case Oversampling_8x: return 8;
}
return 1;
}
int libsrcInterpolation() const
{
switch( interpolation )
{
case Interpolation_Linear:
return SRC_ZERO_ORDER_HOLD;
case Interpolation_SincFastest:
return SRC_SINC_FASTEST;
case Interpolation_SincMedium:
return SRC_SINC_MEDIUM_QUALITY;
case Interpolation_SincBest:
return SRC_SINC_BEST_QUALITY;
}
return SRC_LINEAR;
}
} ;
void initDevices();
void clear();
void clearNewPlayHandles();
// audio-device-stuff
// Returns the current audio device's name. This is not necessarily
// the user's preferred audio device, in case you were thinking that.
inline const QString & audioDevName() const
{
return m_audioDevName;
}
inline bool audioDevStartFailed() const
{
return m_audioDevStartFailed;
}
//! Set new audio device. Old device will be deleted,
//! unless it's stored using storeAudioDevice
void setAudioDevice( AudioDevice * _dev,
const struct qualitySettings & _qs,
bool _needs_fifo,
bool startNow );
void storeAudioDevice();
void restoreAudioDevice();
inline AudioDevice * audioDev()
{
return m_audioDev;
}
// audio-port-stuff
inline void addAudioPort(AudioPort * port)
{
requestChangeInModel();
m_audioPorts.push_back(port);
doneChangeInModel();
}
void removeAudioPort(AudioPort * port);
// MIDI-client-stuff
inline const QString & midiClientName() const
{
return m_midiClientName;
}
inline MidiClient * midiClient()
{
return m_midiClient;
}
// play-handle stuff
bool addPlayHandle( PlayHandle* handle );
void removePlayHandle( PlayHandle* handle );
inline PlayHandleList& playHandles()
{
return m_playHandles;
}
void removePlayHandlesOfTypes(Track * track, const quint8 types);
// methods providing information for other classes
inline fpp_t framesPerPeriod() const
{
return m_framesPerPeriod;
}
AudioEngineProfiler& profiler()
{
return m_profiler;
}
int cpuLoad() const
{
return m_profiler.cpuLoad();
}
const qualitySettings & currentQualitySettings() const
{
return m_qualitySettings;
}
sample_rate_t baseSampleRate() const;
sample_rate_t outputSampleRate() const;
sample_rate_t inputSampleRate() const;
sample_rate_t processingSampleRate() const;
inline float masterGain() const
{
return m_masterGain;
}
inline void setMasterGain(const float mo)
{
m_masterGain = mo;
}
static inline sample_t clip(const sample_t s)
{
if (s > 1.0f)
{
return 1.0f;
}
else if (s < -1.0f)
{
return -1.0f;
}
return s;
}
struct StereoSample
{
StereoSample(sample_t _left, sample_t _right) : left(_left), right(_right) {}
sample_t left;
sample_t right;
};
StereoSample getPeakValues(sampleFrame * ab, const f_cnt_t _frames) const;
bool criticalXRuns() const;
inline bool hasFifoWriter() const
{
return m_fifoWriter != nullptr;
}
void pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames );
inline const sampleFrame * inputBuffer()
{
return m_inputBuffer[ m_inputBufferRead ];
}
inline f_cnt_t inputBufferFrames() const
{
return m_inputBufferFrames[ m_inputBufferRead ];
}
inline const surroundSampleFrame * nextBuffer()
{
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
}
void changeQuality(const struct qualitySettings & qs);
inline bool isMetronomeActive() const { return m_metronomeActive; }
inline void setMetronomeActive(bool value = true) { m_metronomeActive = value; }
//! Block until a change in model can be done (i.e. wait for audio thread)
void requestChangeInModel();
void doneChangeInModel();
RequestChangesGuard requestChangesGuard()
{
return RequestChangesGuard{this};
}
static bool isAudioDevNameValid(QString name);
static bool isMidiDevNameValid(QString name);
signals:
void qualitySettingsChanged();
void sampleRateChanged();
void nextAudioBuffer( const lmms::surroundSampleFrame * buffer );
private:
using Fifo = FifoBuffer<surroundSampleFrame*>;
class fifoWriter : public QThread
{
public:
fifoWriter( AudioEngine * audioEngine, Fifo * fifo );
void finish();
private:
AudioEngine * m_audioEngine;
Fifo * m_fifo;
volatile bool m_writing;
void run() override;
void write( surroundSampleFrame * buffer );
} ;
AudioEngine( bool renderOnly );
~AudioEngine() override;
void startProcessing(bool needsFifo = true);
void stopProcessing();
AudioDevice * tryAudioDevices();
MidiClient * tryMidiClients();
const surroundSampleFrame * renderNextBuffer();
void swapBuffers();
void handleMetronome();
void clearInternal();
//! Called by the audio thread to give control to other threads,
//! such that they can do changes in the model (like e.g. removing effects)
void runChangesInModel();
bool m_renderOnly;
QVector<AudioPort *> m_audioPorts;
fpp_t m_framesPerPeriod;
sampleFrame * m_inputBuffer[2];
f_cnt_t m_inputBufferFrames[2];
f_cnt_t m_inputBufferSize[2];
int m_inputBufferRead;
int m_inputBufferWrite;
surroundSampleFrame * m_outputBufferRead;
surroundSampleFrame * m_outputBufferWrite;
// worker thread stuff
QVector<AudioEngineWorkerThread *> m_workers;
int m_numWorkers;
// playhandle stuff
PlayHandleList m_playHandles;
// place where new playhandles are added temporarily
LocklessList<PlayHandle *> m_newPlayHandles;
ConstPlayHandleList m_playHandlesToRemove;
struct qualitySettings m_qualitySettings;
float m_masterGain;
bool m_isProcessing;
// audio device stuff
void doSetAudioDevice( AudioDevice *_dev );
AudioDevice * m_audioDev;
AudioDevice * m_oldAudioDev;
QString m_audioDevName;
bool m_audioDevStartFailed;
// MIDI device stuff
MidiClient * m_midiClient;
QString m_midiClientName;
// FIFO stuff
Fifo * m_fifo;
fifoWriter * m_fifoWriter;
AudioEngineProfiler m_profiler;
bool m_metronomeActive;
bool m_clearSignal;
bool m_changesSignal;
unsigned int m_changes;
QMutex m_changesMutex;
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
QRecursiveMutex m_doChangesMutex;
#else
QMutex m_doChangesMutex;
#endif
QMutex m_waitChangesMutex;
QWaitCondition m_changesAudioEngineCondition;
QWaitCondition m_changesRequestCondition;
bool m_waitingForWrite;
friend class Engine;
friend class AudioEngineWorkerThread;
friend class ProjectRenderer;
} ;
} // namespace lmms
#endif

View File

@@ -1,5 +1,5 @@
/*
* MixerProfiler.h - class for profiling performance of Mixer
* AudioEngineProfiler.h - class for profiling performance of AudioEngine
*
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -22,19 +22,22 @@
*
*/
#ifndef MIXER_PROFILER_H
#define MIXER_PROFILER_H
#ifndef AUDIO_ENGINE_PROFILER_H
#define AUDIO_ENGINE_PROFILER_H
#include <QFile>
#include "lmms_basics.h"
#include "MicroTimer.h"
class MixerProfiler
namespace lmms
{
class AudioEngineProfiler
{
public:
MixerProfiler();
~MixerProfiler();
AudioEngineProfiler();
~AudioEngineProfiler() = default;
void startPeriod()
{
@@ -55,7 +58,8 @@ private:
MicroTimer m_periodTimer;
int m_cpuLoad;
QFile m_outputFile;
};
} // namespace lmms
#endif

View File

@@ -1,5 +1,5 @@
/*
* MixerWorkerThread.h - declaration of class MixerWorkerThread
* AudioEngineWorkerThread.h - declaration of class AudioEngineWorkerThread
*
* Copyright (c) 2009-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -22,18 +22,22 @@
*
*/
#ifndef MIXER_WORKER_THREAD_H
#define MIXER_WORKER_THREAD_H
#ifndef AUDIO_ENGINE_WORKER_THREAD_H
#define AUDIO_ENGINE_WORKER_THREAD_H
#include <QtCore/QThread>
#include <QThread>
#include <atomic>
class QWaitCondition;
class Mixer;
namespace lmms
{
class AudioEngine;
class ThreadableJob;
class MixerWorkerThread : public QThread
class AudioEngineWorkerThread : public QThread
{
Q_OBJECT
public:
@@ -47,7 +51,8 @@ public:
Dynamic // jobs can be added while processing queue
} ;
#define JOB_QUEUE_SIZE 8192
static constexpr size_t JOB_QUEUE_SIZE = 8192;
JobQueue() :
m_items(),
m_writeIndex( 0 ),
@@ -69,12 +74,11 @@ public:
std::atomic_int m_writeIndex;
std::atomic_int m_itemsDone;
OperationMode m_opMode;
} ;
MixerWorkerThread( Mixer* mixer );
virtual ~MixerWorkerThread();
AudioEngineWorkerThread( AudioEngine* audioEngine );
~AudioEngineWorkerThread() override;
virtual void quit();
@@ -106,15 +110,15 @@ public:
private:
virtual void run();
void run() override;
static JobQueue globalJobQueue;
static QWaitCondition * queueReadyWaitCond;
static QList<MixerWorkerThread *> workerThreads;
static QList<AudioEngineWorkerThread *> workerThreads;
volatile bool m_quit;
} ;
} // namespace lmms
#endif

View File

@@ -26,19 +26,21 @@
#ifndef AUDIO_FILE_DEVICE_H
#define AUDIO_FILE_DEVICE_H
#include <QtCore/QFile>
#include <QFile>
#include "AudioDevice.h"
#include "OutputSettings.h"
namespace lmms
{
class AudioFileDevice : public AudioDevice
{
public:
AudioFileDevice(OutputSettings const & outputSettings,
const ch_cnt_t _channels, const QString & _file,
Mixer* mixer );
virtual ~AudioFileDevice();
AudioEngine* audioEngine );
~AudioFileDevice() override;
QString outputFile() const
{
@@ -66,13 +68,9 @@ private:
OutputSettings m_outputSettings;
} ;
using AudioFileDeviceInstantiaton
= AudioFileDevice* (*)(const QString&, const OutputSettings&, const ch_cnt_t, AudioEngine*, bool&);
typedef AudioFileDevice * ( * AudioFileDeviceInstantiaton )
( const QString & outputFilename,
OutputSettings const & outputSettings,
const ch_cnt_t channels,
Mixer* mixer,
bool & successful );
} // namespace lmms
#endif

View File

@@ -30,6 +30,9 @@
#include "AudioFileDevice.h"
#include <sndfile.h>
namespace lmms
{
class AudioFileFlac: public AudioFileDevice
{
public:
@@ -37,15 +40,15 @@ public:
ch_cnt_t const channels,
bool& successful,
QString const& file,
Mixer* mixer
AudioEngine* audioEngine
);
virtual ~AudioFileFlac();
~AudioFileFlac() override;
static AudioFileDevice* getInst(QString const& outputFilename,
OutputSettings const& outputSettings,
ch_cnt_t const channels,
Mixer* mixer,
AudioEngine* audioEngine,
bool& successful)
{
return new AudioFileFlac(
@@ -53,7 +56,7 @@ public:
channels,
successful,
outputFilename,
mixer
audioEngine
);
}
@@ -62,7 +65,7 @@ private:
SF_INFO m_sfinfo;
SNDFILE* m_sf;
virtual void writeBuffer(surroundSampleFrame const* _ab,
void writeBuffer(surroundSampleFrame const* _ab,
fpp_t const frames,
float master_gain) override;
@@ -71,4 +74,7 @@ private:
};
} // namespace lmms
#endif //AUDIO_FILE_FLAC_H

View File

@@ -34,6 +34,8 @@
#include "lame/lame.h"
namespace lmms
{
class AudioFileMP3 : public AudioFileDevice
{
@@ -42,23 +44,23 @@ public:
const ch_cnt_t _channels,
bool & successful,
const QString & _file,
Mixer* mixer );
virtual ~AudioFileMP3();
AudioEngine* audioEngine );
~AudioFileMP3() override;
static AudioFileDevice * getInst( const QString & outputFilename,
OutputSettings const & outputSettings,
const ch_cnt_t channels,
Mixer* mixer,
AudioEngine* audioEngine,
bool & successful )
{
return new AudioFileMP3( outputSettings, channels, successful,
outputFilename, mixer );
outputFilename, audioEngine );
}
protected:
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
void writeBuffer( const surroundSampleFrame * /* _buf*/,
const fpp_t /*_frames*/,
const float /*_master_gain*/ );
const float /*_master_gain*/ ) override;
private:
void flushRemainingBuffers();
@@ -69,6 +71,8 @@ private:
lame_t m_lame;
};
#endif
} // namespace lmms
#endif // LMMS_HAVE_MP3LAME
#endif

View File

@@ -34,6 +34,8 @@
#include "AudioFileDevice.h"
namespace lmms
{
class AudioFileOgg : public AudioFileDevice
{
@@ -42,24 +44,23 @@ public:
const ch_cnt_t _channels,
bool & _success_ful,
const QString & _file,
Mixer* mixer );
virtual ~AudioFileOgg();
AudioEngine* audioEngine );
~AudioFileOgg() override;
static AudioFileDevice * getInst( const QString & outputFilename,
OutputSettings const & outputSettings,
const ch_cnt_t channels,
Mixer* mixer,
AudioEngine* audioEngine,
bool & successful )
{
return new AudioFileOgg( outputSettings, channels, successful,
outputFilename, mixer );
return new AudioFileOgg( outputSettings, channels, successful, outputFilename, audioEngine );
}
private:
virtual void writeBuffer( const surroundSampleFrame * _ab,
void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain );
const float _master_gain ) override;
bool startEncoding();
void finishEncoding();
@@ -108,6 +109,8 @@ private:
} ;
#endif
} // namespace lmms
#endif // LMMS_HAVE_OGGVORBIS
#endif

View File

@@ -31,6 +31,8 @@
#include <sndfile.h>
namespace lmms
{
class AudioFileWave : public AudioFileDevice
{
@@ -39,24 +41,24 @@ public:
const ch_cnt_t channels,
bool & successful,
const QString & file,
Mixer* mixer );
virtual ~AudioFileWave();
AudioEngine* audioEngine );
~AudioFileWave() override;
static AudioFileDevice * getInst( const QString & outputFilename,
OutputSettings const & outputSettings,
const ch_cnt_t channels,
Mixer* mixer,
AudioEngine* audioEngine,
bool & successful )
{
return new AudioFileWave( outputSettings, channels, successful,
outputFilename, mixer );
outputFilename, audioEngine );
}
private:
virtual void writeBuffer( const surroundSampleFrame * _ab,
void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
float _master_gain );
float _master_gain ) override;
bool startEncoding();
void finishEncoding();
@@ -66,4 +68,7 @@ private:
SNDFILE * m_sf;
} ;
} // namespace lmms
#endif

View File

@@ -34,49 +34,57 @@
#include "weak_libjack.h"
#endif
#include <QtCore/QVector>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <atomic>
#include <QVector>
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
class QLineEdit;
class LcdSpinBox;
namespace lmms
{
class MidiJack;
namespace gui
{
class LcdSpinBox;
}
class AudioJack : public QObject, public AudioDevice
{
Q_OBJECT
public:
AudioJack( bool & _success_ful, Mixer* mixer );
virtual ~AudioJack();
AudioJack( bool & _success_ful, AudioEngine* audioEngine );
~AudioJack() override;
// this is to allow the jack midi connection to use the same jack client connection
// 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() { 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)" );
}
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
~setupWidget() override;
virtual void saveSettings();
void saveSettings() override;
private:
QLineEdit * m_clientName;
LcdSpinBox * m_channels;
gui::LcdSpinBox * m_channels;
} ;
@@ -88,13 +96,13 @@ private slots:
private:
bool initJackClient();
virtual void startProcessing();
virtual void stopProcessing();
virtual void applyQualitySettings();
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
virtual void registerPort( AudioPort * _port );
virtual void unregisterPort( AudioPort * _port );
virtual void renamePort( AudioPort * _port );
void registerPort( AudioPort * _port ) override;
void unregisterPort( AudioPort * _port ) override;
void renamePort( AudioPort * _port ) override;
int processCallback( jack_nframes_t _nframes, void * _udata );
@@ -106,9 +114,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;
@@ -123,7 +131,7 @@ private:
jack_port_t * ports[2];
} ;
typedef QMap<AudioPort *, StereoPort> JackPortMap;
using JackPortMap = QMap<AudioPort *, StereoPort>;
JackPortMap m_portMap;
#endif
@@ -132,6 +140,8 @@ signals:
} ;
#endif
} // namespace lmms
#endif // LMMS_HAVE_JACK
#endif

View File

@@ -34,46 +34,53 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
class LcdSpinBox;
class QLineEdit;
namespace lmms
{
namespace gui
{
class LcdSpinBox;
}
class AudioOss : public QThread, public AudioDevice
{
Q_OBJECT
public:
AudioOss( bool & _success_ful, Mixer* mixer );
virtual ~AudioOss();
AudioOss( bool & _success_ful, AudioEngine* audioEngine );
~AudioOss() override;
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();
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
~setupWidget() override;
virtual void saveSettings();
void saveSettings() override;
private:
QLineEdit * m_device;
LcdSpinBox * m_channels;
gui::LcdSpinBox * m_channels;
} ;
private:
virtual void startProcessing();
virtual void stopProcessing();
virtual void applyQualitySettings();
virtual void run();
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
void run() override;
int m_audioFD;
@@ -81,7 +88,8 @@ private:
} ;
#endif
} // namespace lmms
#endif // LMMS_HAVE_OSS
#endif

View File

@@ -26,13 +26,15 @@
#define AUDIO_PORT_H
#include <memory>
#include <QtCore/QString>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
#include <QString>
#include <QMutex>
#include "MemoryManager.h"
#include "PlayHandle.h"
namespace lmms
{
class EffectChain;
class FloatModel;
class BoolModel;
@@ -42,8 +44,8 @@ class AudioPort : public ThreadableJob
MM_OPERATORS
public:
AudioPort( const QString & _name, bool _has_effect_chain = true,
FloatModel * volumeModel = NULL, FloatModel * panningModel = NULL,
BoolModel * mutedModel = NULL );
FloatModel * volumeModel = nullptr, FloatModel * panningModel = nullptr,
BoolModel * mutedModel = nullptr );
virtual ~AudioPort();
inline sampleFrame * buffer()
@@ -71,11 +73,11 @@ public:
void setExtOutputEnabled( bool _enabled );
// next effect-channel after this audio-port
// next mixer-channel after this audio-port
// (-1 = none 0 = master)
inline fx_ch_t nextFxChannel() const
inline mix_ch_t nextMixerChannel() const
{
return m_nextFxChannel;
return m_nextMixerChannel;
}
inline EffectChain * effects()
@@ -83,9 +85,9 @@ public:
return m_effects.get();
}
void setNextFxChannel( const fx_ch_t _chnl )
void setNextMixerChannel( const mix_ch_t _chnl )
{
m_nextFxChannel = _chnl;
m_nextMixerChannel = _chnl;
}
@@ -100,8 +102,8 @@ public:
bool processEffects();
// ThreadableJob stuff
virtual void doProcessing();
virtual bool requiresProcessing() const
void doProcessing() override;
bool requiresProcessing() const override
{
return true;
}
@@ -116,7 +118,7 @@ private:
QMutex m_portBufferLock;
bool m_extOutputEnabled;
fx_ch_t m_nextFxChannel;
mix_ch_t m_nextMixerChannel;
QString m_name;
@@ -129,10 +131,11 @@ private:
FloatModel * m_panningModel;
BoolModel * m_mutedModel;
friend class Mixer;
friend class MixerWorkerThread;
friend class AudioEngine;
friend class AudioEngineWorkerThread;
} ;
} // namespace lmms
#endif

View File

@@ -25,14 +25,33 @@
#ifndef AUDIO_PORTAUDIO_H
#define AUDIO_PORTAUDIO_H
#include <QtCore/QObject>
#include <QObject>
#include "lmmsconfig.h"
#include "ComboBoxModel.h"
#ifdef LMMS_HAVE_PORTAUDIO
# include <portaudio.h>
# include "AudioDevice.h"
# include "AudioDeviceSetupWidget.h"
# if defined paNeverDropInput || defined paNonInterleaved
# define PORTAUDIO_V19
# else
# define PORTAUDIO_V18
# endif
#endif
namespace lmms
{
class AudioPortAudioSetupUtil : public QObject
{
Q_OBJECT
Q_OBJECT
public slots:
void updateBackends();
void updateDevices();
@@ -41,38 +60,28 @@ public slots:
public:
ComboBoxModel m_backendModel;
ComboBoxModel m_deviceModel;
} ;
};
#ifdef LMMS_HAVE_PORTAUDIO
#include <portaudio.h>
#include <QtCore/QSemaphore>
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
#if defined paNeverDropInput || defined paNonInterleaved
# define PORTAUDIO_V19
#else
# define PORTAUDIO_V18
#endif
namespace gui
{
class ComboBox;
class LcdSpinBox;
}
class AudioPortAudio : public AudioDevice
{
public:
AudioPortAudio( bool & _success_ful, Mixer* mixer );
virtual ~AudioPortAudio();
AudioPortAudio( bool & _success_ful, AudioEngine* audioEngine );
~AudioPortAudio() override;
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "PortAudio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PortAudio" );
}
@@ -81,26 +90,26 @@ public:
unsigned long _framesPerBuffer );
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
~setupWidget() override;
virtual void saveSettings();
virtual void show();
void saveSettings() override;
void show() override;
private:
ComboBox * m_backend;
ComboBox * m_device;
gui::ComboBox * m_backend;
gui::ComboBox * m_device;
AudioPortAudioSetupUtil m_setupUtil;
} ;
private:
virtual void startProcessing();
virtual void stopProcessing();
virtual void applyQualitySettings();
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
#ifdef PORTAUDIO_V19
static int _process_callback( const void *_inputBuffer, void * _outputBuffer,
@@ -122,10 +131,10 @@ private:
unsigned long _framesPerBuffer, PaTimestamp _outTime, void * _arg );
typedef double PaTime;
typedef PaDeviceID PaDeviceIndex;
using PaTime = double;
using PaDeviceIndex = PaDeviceID;
typedef struct PaStreamParameters
using PaStreamParameters = struct
{
PaDeviceIndex device;
int channelCount;
@@ -134,7 +143,7 @@ private:
void *hostApiSpecificStreamInfo;
} PaStreamParameters;
#endif
#endif // PORTAUDIO_V19
PaStream * m_paStream;
PaStreamParameters m_outputParameters;
@@ -150,6 +159,8 @@ private:
} ;
#endif
#endif // LMMS_HAVE_PORTAUDIO
} // namespace lmms
#endif

View File

@@ -36,37 +36,43 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
class LcdSpinBox;
class QLineEdit;
namespace lmms
{
namespace gui
{
class LcdSpinBox;
}
class AudioPulseAudio : public QThread, public AudioDevice
{
Q_OBJECT
public:
AudioPulseAudio( bool & _success_ful, Mixer* mixer );
virtual ~AudioPulseAudio();
AudioPulseAudio( bool & _success_ful, AudioEngine* audioEngine );
~AudioPulseAudio() override;
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "PulseAudio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PulseAudio" );
}
static QString probeDevice();
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
~setupWidget() override;
virtual void saveSettings();
void saveSettings() override;
private:
QLineEdit * m_device;
LcdSpinBox * m_channels;
gui::LcdSpinBox * m_channels;
} ;
@@ -80,10 +86,10 @@ public:
private:
virtual void startProcessing();
virtual void stopProcessing();
virtual void applyQualitySettings();
virtual void run();
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
void run() override;
volatile bool m_quit;
@@ -94,6 +100,8 @@ private:
} ;
#endif
} // namespace lmms
#endif // LMMS_HAVE_PULSEAUDIO
#endif

View File

@@ -26,34 +26,37 @@
#ifndef AUDIO_SAMPLE_RECORDER_H
#define AUDIO_SAMPLE_RECORDER_H
#include <QtCore/QList>
#include <QtCore/QPair>
#include <QList>
#include <QPair>
#include "AudioDevice.h"
namespace lmms
{
class SampleBuffer;
class AudioSampleRecorder : public AudioDevice
{
public:
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful,
Mixer* mixer );
virtual ~AudioSampleRecorder();
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful, AudioEngine* audioEngine );
~AudioSampleRecorder() override;
f_cnt_t framesRecorded() const;
void createSampleBuffer( SampleBuffer** sampleBuffer );
private:
virtual void writeBuffer( const surroundSampleFrame * _ab,
void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain );
const float _master_gain ) override;
typedef QList<QPair<sampleFrame *, fpp_t> > BufferList;
using BufferList = QList<QPair<sampleFrame*, fpp_t>>;
BufferList m_buffers;
} ;
} // namespace lmms
#endif

View File

@@ -30,7 +30,6 @@
#ifdef LMMS_HAVE_SDL
#ifdef LMMS_HAVE_SDL2
#include <SDL2/SDL.h>
#include <SDL2/SDL_audio.h>
#else
#include <SDL/SDL.h>
@@ -42,27 +41,29 @@
class QLineEdit;
namespace lmms
{
class AudioSdl : public AudioDevice
{
public:
AudioSdl( bool & _success_ful, Mixer* mixer );
virtual ~AudioSdl();
AudioSdl( bool & _success_ful, AudioEngine* audioEngine );
~AudioSdl() override;
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget",
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
"SDL (Simple DirectMedia Layer)" );
}
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
~setupWidget() override = default;
virtual void saveSettings();
void saveSettings() override;
private:
QLineEdit * m_device;
@@ -71,9 +72,9 @@ public:
private:
virtual void startProcessing();
virtual void stopProcessing();
virtual void applyQualitySettings();
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
static void sdlAudioCallback( void * _udata, Uint8 * _buf, int _len );
void sdlAudioCallback( Uint8 * _buf, int _len );
@@ -109,6 +110,9 @@ private:
} ;
#endif
} // namespace lmms
#endif // LMMS_HAVE_SDL
#endif

View File

@@ -36,40 +36,47 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
class LcdSpinBox;
class QLineEdit;
namespace lmms
{
namespace gui
{
class LcdSpinBox;
}
class AudioSndio : public QThread, public AudioDevice
{
Q_OBJECT
public:
AudioSndio( bool & _success_ful, Mixer * _mixer );
virtual ~AudioSndio();
AudioSndio( bool & _success_ful, AudioEngine * _audioEngine );
~AudioSndio() override;
inline static QString name( void )
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "sndio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "sndio" );
}
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
virtual ~setupWidget();
~setupWidget() override = default;
virtual void saveSettings( void );
void saveSettings() override;
private:
QLineEdit * m_device;
LcdSpinBox * m_channels;
gui::LcdSpinBox * m_channels;
} ;
private:
virtual void startProcessing( void );
virtual void stopProcessing( void );
virtual void applyQualitySettings( void );
virtual void run( void );
void startProcessing() override;
void stopProcessing() override;
void applyQualitySettings() override;
void run() override;
struct sio_hdl *m_hdl;
struct sio_par m_par;
@@ -78,6 +85,8 @@ private:
} ;
#endif /* LMMS_HAVE_SNDIO */
} // namespace lmms
#endif /* _AUDIO_SNDIO_H */
#endif // LMMS_HAVE_SNDIO
#endif // _AUDIO_SNDIO_H

View File

@@ -25,7 +25,7 @@
#ifndef AUDIO_SOUNDIO_H
#define AUDIO_SOUNDIO_H
#include <QtCore/QObject>
#include <QObject>
#include "lmmsconfig.h"
#include "ComboBoxModel.h"
@@ -37,15 +37,21 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
namespace lmms
{
namespace gui
{
class ComboBox;
class LcdSpinBox;
}
// Exists only to work around "Error: Meta object features not supported for nested classes"
class AudioSoundIoSetupUtil : public QObject
{
Q_OBJECT
public:
virtual ~AudioSoundIoSetupUtil();
virtual ~AudioSoundIoSetupUtil() = default;
void *m_setupWidget;
public slots:
@@ -56,15 +62,15 @@ public slots:
class AudioSoundIo : public AudioDevice
{
public:
AudioSoundIo( bool & _success_ful, Mixer* mixer );
AudioSoundIo( bool & _success_ful, AudioEngine* audioEngine );
virtual ~AudioSoundIo();
inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget", "soundio" );
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "soundio" );
}
class setupWidget : public AudioDeviceSetupWidget
class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
@@ -78,8 +84,8 @@ public:
private:
AudioSoundIoSetupUtil m_setupUtil;
ComboBox * m_backend;
ComboBox * m_device;
gui::ComboBox * m_backend;
gui::ComboBox * m_device;
ComboBoxModel m_backendModel;
ComboBoxModel m_deviceModel;
@@ -110,6 +116,7 @@ private:
fpp_t m_outBufFrameIndex;
bool m_stopped;
bool m_outstreamStarted;
int m_disconnectErr;
void onBackendDisconnect(int err);
@@ -133,6 +140,9 @@ private:
};
#endif
} // namespace lmms
#endif // LMMS_HAVE_SOUNDIO
#endif

View File

@@ -30,6 +30,8 @@
#include "AutomatableModelView.h"
namespace lmms::gui
{
class automatableButtonGroup;
@@ -40,7 +42,7 @@ class LMMS_EXPORT AutomatableButton : public QPushButton, public BoolModelView
public:
AutomatableButton( QWidget * _parent, const QString & _name
= QString() );
virtual ~AutomatableButton();
~AutomatableButton() override;
inline void setCheckable( bool _on )
{
@@ -48,7 +50,7 @@ public:
model()->setJournalling( _on );
}
virtual void modelChanged();
void modelChanged() override;
public slots:
@@ -62,9 +64,9 @@ public slots:
protected:
virtual void contextMenuEvent( QContextMenuEvent * _me );
virtual void mousePressEvent( QMouseEvent * _me );
virtual void mouseReleaseEvent( QMouseEvent * _me );
void contextMenuEvent( QContextMenuEvent * _me ) override;
void mousePressEvent( QMouseEvent * _me ) override;
void mouseReleaseEvent( QMouseEvent * _me ) override;
private:
@@ -85,14 +87,14 @@ class LMMS_EXPORT automatableButtonGroup : public QWidget, public IntModelView
public:
automatableButtonGroup( QWidget * _parent, const QString & _name
= QString() );
virtual ~automatableButtonGroup();
~automatableButtonGroup() override;
void addButton( AutomatableButton * _btn );
void removeButton( AutomatableButton * _btn );
void activateButton( AutomatableButton * _btn );
virtual void modelChanged();
void modelChanged() override;
private slots:
@@ -105,5 +107,6 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -25,16 +25,20 @@
#ifndef AUTOMATABLE_MODEL_H
#define AUTOMATABLE_MODEL_H
#include <QtCore/QMap>
#include <QtCore/QMutex>
#include <QMap>
#include <QMutex>
#include "JournallingObject.h"
#include "Model.h"
#include "MidiTime.h"
#include "TimePos.h"
#include "ValueBuffer.h"
#include "MemoryManager.h"
#include "ModelVisitor.h"
namespace lmms
{
// simple way to map a property of a view to a model
#define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \
public: \
@@ -74,8 +78,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
Q_OBJECT
MM_OPERATORS
public:
typedef QVector<AutomatableModel *> AutoModelVector;
using AutoModelVector = QVector<AutomatableModel*>;
enum ScaleType
{
@@ -85,7 +88,7 @@ public:
};
virtual ~AutomatableModel();
~AutomatableModel() override;
// Implement those by using the MODEL_IS_VISITABLE macro
virtual void accept(ModelVisitor& v) = 0;
@@ -120,7 +123,7 @@ public:
bool isAutomated() const;
bool isAutomatedOrControlled() const
{
return isAutomated() || m_controllerConnection != NULL;
return isAutomated() || m_controllerConnection != nullptr;
}
ControllerConnection* controllerConnection() const
@@ -148,7 +151,18 @@ public:
template<class T>
inline T value( int frameOffset = 0 ) const
{
if( unlikely( hasLinkedModels() || m_controllerConnection != NULL ) )
if (m_controllerConnection)
{
if (!m_useControllerValue)
{
return castValue<T>(m_value);
}
else
{
return castValue<T>(controllerValue(frameOffset));
}
}
else if (hasLinkedModels())
{
return castValue<T>( controllerValue( frameOffset ) );
}
@@ -236,6 +250,7 @@ public:
m_centerValue = centerVal;
}
//! link @p m1 and @p m2, let @p m1 take the values of @p m2
static void linkModels( AutomatableModel* m1, AutomatableModel* m2 );
static void unlinkModels( AutomatableModel* m1, AutomatableModel* m2 );
@@ -255,7 +270,7 @@ public:
specified DOM element using <name> as attribute/node name */
virtual void loadSettings( const QDomElement& element, const QString& name );
virtual QString nodeName() const
QString nodeName() const override
{
return "automatablemodel";
}
@@ -280,7 +295,7 @@ public:
return false;
}
float globalAutomationValueAt( const MidiTime& time );
float globalAutomationValueAt( const TimePos& time );
void setStrictStepSize( const bool b )
{
@@ -297,9 +312,15 @@ public:
s_periodCounter = 0;
}
bool useControllerValue()
{
return m_useControllerValue;
}
public slots:
virtual void reset();
void unlinkControllerConnection();
void setUseControllerValue(bool b = true);
protected:
@@ -308,7 +329,7 @@ protected:
const float min = 0,
const float max = 0,
const float step = 0,
Model* parent = NULL,
Model* parent = nullptr,
const QString& displayName = QString(),
bool defaultConstructed = false );
//! returns a value which is in range between min() and
@@ -337,12 +358,12 @@ private:
static bool mustQuoteName(const QString &name);
virtual void saveSettings( QDomDocument& doc, QDomElement& element )
void saveSettings( QDomDocument& doc, QDomElement& element ) override
{
saveSettings( doc, element, "value" );
}
virtual void loadSettings( const QDomElement& element )
void loadSettings( const QDomElement& element ) override
{
loadSettings( element, "value" );
}
@@ -359,7 +380,7 @@ private:
template<class T> void roundAt( T &value, const T &where ) const;
ScaleType m_scaleType; //! scale type, linear by default
ScaleType m_scaleType; //!< scale type, linear by default
float m_value;
float m_initValue;
float m_minValue;
@@ -394,9 +415,11 @@ private:
// prevent several threads from attempting to write the same vb at the same time
QMutex m_valueBufferMutex;
bool m_useControllerValue;
signals:
void initValueChanged( float val );
void destroyed( jo_id_t id );
void destroyed( lmms::jo_id_t id );
} ;
@@ -437,7 +460,7 @@ class LMMS_EXPORT FloatModel : public TypedAutomatableModel<float>
MODEL_IS_VISITABLE
public:
FloatModel( float val = 0, float min = 0, float max = 0, float step = 0,
Model * parent = NULL,
Model * parent = nullptr,
const QString& displayName = QString(),
bool defaultConstructed = false ) :
TypedAutomatableModel( val, min, max, step, parent, displayName, defaultConstructed )
@@ -455,7 +478,7 @@ class LMMS_EXPORT IntModel : public TypedAutomatableModel<int>
MODEL_IS_VISITABLE
public:
IntModel( int val = 0, int min = 0, int max = 0,
Model* parent = NULL,
Model* parent = nullptr,
const QString& displayName = QString(),
bool defaultConstructed = false ) :
TypedAutomatableModel( val, min, max, 1, parent, displayName, defaultConstructed )
@@ -471,7 +494,7 @@ class LMMS_EXPORT BoolModel : public TypedAutomatableModel<bool>
MODEL_IS_VISITABLE
public:
BoolModel( const bool val = false,
Model* parent = NULL,
Model* parent = nullptr,
const QString& displayName = QString(),
bool defaultConstructed = false ) :
TypedAutomatableModel( val, false, true, 1, parent, displayName, defaultConstructed )
@@ -480,7 +503,9 @@ public:
QString displayValue( const float val ) const override;
} ;
typedef QMap<AutomatableModel*, float> AutomatedValueMap;
using AutomatedValueMap = QMap<AutomatableModel*, float>;
} // namespace lmms
#endif

View File

@@ -32,11 +32,14 @@
class QMenu;
class QMouseEvent;
namespace lmms::gui
{
class LMMS_EXPORT AutomatableModelView : public ModelView
{
public:
AutomatableModelView( Model* model, QWidget* _this );
virtual ~AutomatableModelView() = default;
~AutomatableModelView() override = default;
// some basic functions for convenience
AutomatableModel* modelUntyped()
@@ -49,7 +52,8 @@ public:
return castModel<AutomatableModel>();
}
virtual void setModel( Model* model, bool isOldModelValid = true );
void setModel( Model* model, bool isOldModelValid = true ) override;
void unsetModel() override;
template<typename T>
inline T value() const
@@ -69,12 +73,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
} ;
@@ -127,5 +135,7 @@ using FloatModelView = TypedModelView<FloatModel>;
using IntModelView = TypedModelView<IntModel>;
using BoolModelView = TypedModelView<BoolModel>;
} // namespace lmms::gui
#endif

View File

@@ -31,13 +31,15 @@
#include "AutomatableModelView.h"
namespace lmms::gui
{
class AutomatableSlider : public QSlider, public IntModelView
{
Q_OBJECT
public:
AutomatableSlider( QWidget * _parent, const QString & _name = QString() );
virtual ~AutomatableSlider();
~AutomatableSlider() override = default;
bool showStatus()
{
@@ -51,12 +53,12 @@ signals:
protected:
virtual void contextMenuEvent( QContextMenuEvent * _me );
virtual void mousePressEvent( QMouseEvent * _me );
virtual void mouseReleaseEvent( QMouseEvent * _me );
virtual void wheelEvent( QWheelEvent * _me );
void contextMenuEvent( QContextMenuEvent * _me ) override;
void mousePressEvent( QMouseEvent * _me ) override;
void mouseReleaseEvent( QMouseEvent * _me ) override;
void wheelEvent( QWheelEvent * _me ) override;
virtual void modelChanged();
void modelChanged() override;
private:
@@ -71,7 +73,8 @@ private slots:
} ;
typedef IntModel sliderModel;
using sliderModel = IntModel;
} // namespace lmms::gui
#endif

View File

@@ -1,6 +1,6 @@
/*
* AutomationPattern.h - declaration of class AutomationPattern, which contains
* all information about an automation pattern
* AutomationClip.h - declaration of class AutomationClip, which contains
* all information about an automation clip
*
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
@@ -24,21 +24,33 @@
*
*/
#ifndef AUTOMATION_PATTERN_H
#define AUTOMATION_PATTERN_H
#ifndef AUTOMATION_CLIP_H
#define AUTOMATION_CLIP_H
#include <QtCore/QMap>
#include <QtCore/QPointer>
#include <QMap>
#include <QPointer>
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
#include <QRecursiveMutex>
#endif
#include "Track.h"
#include "AutomationNode.h"
#include "Clip.h"
namespace lmms
{
class AutomationTrack;
class MidiTime;
class TimePos;
namespace gui
{
class AutomationClipView;
} // namespace gui
class LMMS_EXPORT AutomationPattern : public TrackContentObject
class LMMS_EXPORT AutomationClip : public Clip
{
Q_OBJECT
public:
@@ -49,12 +61,14 @@ public:
CubicHermiteProgression
} ;
typedef QMap<int, float> timeMap;
typedef QVector<QPointer<AutomatableModel> > objectVector;
using timeMap = QMap<int, AutomationNode>;
using objectVector = QVector<QPointer<AutomatableModel>>;
AutomationPattern( AutomationTrack * _auto_track );
AutomationPattern( const AutomationPattern & _pat_to_copy );
virtual ~AutomationPattern() = default;
using TimemapIterator = timeMap::const_iterator;
AutomationClip( AutomationTrack * _auto_track );
AutomationClip( const AutomationClip & _clip_to_copy );
~AutomationClip() override = default;
bool addObject( AutomatableModel * _obj, bool _search_dup = true );
@@ -74,19 +88,32 @@ public:
}
void setTension( QString _new_tension );
MidiTime timeMapLength() const;
TimePos timeMapLength() const;
void updateLength();
MidiTime putValue( const MidiTime & time,
const float value,
const bool quantPos = true,
const bool ignoreSurroundingPoints = true );
TimePos putValue(
const TimePos & time,
const float value,
const bool quantPos = true,
const bool ignoreSurroundingPoints = true
);
void removeValue( const MidiTime & time );
TimePos putValues(
const TimePos & time,
const float inValue,
const float outValue,
const bool quantPos = true,
const bool ignoreSurroundingPoints = true
);
void recordValue(MidiTime time, float value);
void removeNode(const TimePos & time);
void removeNodes(const int tick0, const int tick1);
MidiTime setDragValue( const MidiTime & time,
void resetNodes(const int tick0, const int tick1);
void recordValue(TimePos time, float value);
TimePos setDragValue( const TimePos & time,
const float value,
const bool quantPos = true,
const bool controlKey = false );
@@ -109,16 +136,6 @@ public:
return m_timeMap;
}
inline const timeMap & getTangents() const
{
return m_tangents;
}
inline timeMap & getTangents()
{
return m_tangents;
}
inline float getMin() const
{
return firstObject()->minValue<float>();
@@ -134,24 +151,24 @@ 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;
// settings-management
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
static const QString classNodeName() { return "automationpattern"; }
QString nodeName() const { return classNodeName(); }
static const QString classNodeName() { return "automationclip"; }
QString nodeName() const override { return classNodeName(); }
virtual TrackContentObjectView * createView( TrackView * _tv );
gui::ClipView * createView( gui::TrackView * _tv ) override;
static bool isAutomated( const AutomatableModel * _m );
static QVector<AutomationPattern *> patternsForModel( const AutomatableModel * _m );
static AutomationPattern * globalAutomationPattern( AutomatableModel * _m );
static QVector<AutomationClip *> clipsForModel( const AutomatableModel * _m );
static AutomationClip * globalAutomationClip( AutomatableModel * _m );
static void resolveAllIDs();
bool isRecording() const { return m_isRecording; }
@@ -162,7 +179,7 @@ public:
public slots:
void clear();
void objectDestroyed( jo_id_t );
void objectDestroyed( lmms::jo_id_t );
void flipY( int min, int max );
void flipY();
void flipX( int length = -1 );
@@ -170,21 +187,30 @@ public slots:
private:
void cleanObjects();
void generateTangents();
void generateTangents( timeMap::const_iterator it, int numToGenerate );
void generateTangents(timeMap::iterator it, int numToGenerate);
float valueAt( timeMap::const_iterator v, int offset ) const;
// Mutex to make methods involving automation clips thread safe
// Mutable so we can lock it from const objects
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
mutable QRecursiveMutex m_clipMutex;
#else
mutable QMutex m_clipMutex;
#endif
AutomationTrack * m_autoTrack;
QVector<jo_id_t> m_idsToResolve;
objectVector m_objects;
timeMap m_timeMap; // actual values
timeMap m_oldTimeMap; // old values for storing the values before setDragValue() is called.
timeMap m_tangents; // slope at each point for calculating spline
float m_tension;
bool m_hasAutomation;
ProgressionTypes m_progressionType;
bool m_dragging;
bool m_dragKeepOutValue; // Should we keep the current dragged node's outValue?
float m_dragOutValue; // The outValue of the dragged node's
bool m_isRecording;
float m_lastRecordedValue;
@@ -193,9 +219,45 @@ private:
static const float DEFAULT_MIN_VALUE;
static const float DEFAULT_MAX_VALUE;
friend class AutomationPatternView;
friend class gui::AutomationClipView;
friend class AutomationNode;
} ;
//Short-hand functions to access node values in an automation clip;
// replacement for CPP macros with the same purpose; could be refactored
// further in the future.
inline float INVAL(AutomationClip::TimemapIterator it)
{
return it->getInValue();
}
inline float OUTVAL(AutomationClip::TimemapIterator it)
{
return it->getOutValue();
}
inline float OFFSET(AutomationClip::TimemapIterator it)
{
return it->getValueOffset();
}
inline float INTAN(AutomationClip::TimemapIterator it)
{
return it->getInTangent();
}
inline float OUTTAN(AutomationClip::TimemapIterator it)
{
return it->getOutTangent();
}
inline int POS(AutomationClip::TimemapIterator it)
{
return it.key();
}
} // namespace lmms
#endif

View File

@@ -1,5 +1,5 @@
/*
* AutomationPatternView.h - declaration of class AutomationPatternView
* AutomationClipView.h - declaration of class AutomationClipView
*
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -22,29 +22,35 @@
*
*/
#ifndef AUTOMATION_PATTERN_VIEW_H
#define AUTOMATION_PATTERN_VIEW_H
#ifndef AUTOMATION_CLIP_VIEW_H
#define AUTOMATION_CLIP_VIEW_H
#include <QStaticText>
#include "Track.h"
#include "ClipView.h"
class AutomationPattern;
namespace lmms
{
class AutomationClip;
namespace gui
{
class AutomationPatternView : public TrackContentObjectView
class AutomationClipView : public ClipView
{
Q_OBJECT
public:
AutomationPatternView( AutomationPattern * _pat, TrackView * _parent );
virtual ~AutomationPatternView();
AutomationClipView( AutomationClip * _clip, TrackView * _parent );
~AutomationClipView() override = default;
public slots:
/// Opens this view's pattern in the global automation editor
/// Opens this view's clip in the global automation editor
void openInAutomationEditor();
virtual void update();
void update() override;
protected slots:
@@ -56,23 +62,27 @@ protected slots:
void flipX();
protected:
virtual void constructContextMenu( QMenu * );
virtual void mouseDoubleClickEvent(QMouseEvent * me );
virtual void paintEvent( QPaintEvent * pe );
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
void constructContextMenu( QMenu * ) override;
void mouseDoubleClickEvent(QMouseEvent * me ) override;
void paintEvent( QPaintEvent * pe ) override;
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void dropEvent( QDropEvent * _de ) override;
private:
AutomationPattern * m_pat;
AutomationClip * m_clip;
QPixmap m_paintPixmap;
QStaticText m_staticTextName;
static QPixmap * s_pat_rec;
static QPixmap * s_clip_rec;
void scaleTimemapToFit( float oldMin, float oldMax );
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -26,25 +26,30 @@
#ifndef AUTOMATION_EDITOR_H
#define AUTOMATION_EDITOR_H
#include <QtCore/QMutex>
#include <QVector>
#include <QWidget>
#include "Editor.h"
#include "lmms_basics.h"
#include "JournallingObject.h"
#include "MidiTime.h"
#include "AutomationPattern.h"
#include "TimePos.h"
#include "AutomationClip.h"
#include "ComboBoxModel.h"
#include "Knob.h"
class QPainter;
class QPixmap;
class QScrollBar;
class ComboBox;
namespace lmms
{
class NotePlayHandle;
namespace gui
{
class Knob;
class ComboBox;
class TimeLineWidget;
@@ -52,87 +57,69 @@ class TimeLineWidget;
class AutomationEditor : public QWidget, public JournallingObject
{
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 vertexColor READ vertexColor WRITE setVertexColor)
Q_PROPERTY(QBrush scaleColor READ scaleColor WRITE setScaleColor)
Q_PROPERTY(QBrush graphColor READ graphColor WRITE setGraphColor)
Q_PROPERTY(QColor crossColor READ crossColor WRITE setCrossColor)
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 nodeInValueColor MEMBER m_nodeInValueColor)
Q_PROPERTY(QColor nodeOutValueColor MEMBER m_nodeOutValueColor)
Q_PROPERTY(QBrush scaleColor MEMBER m_scaleColor)
Q_PROPERTY(QBrush graphColor MEMBER m_graphColor)
Q_PROPERTY(QColor crossColor MEMBER m_crossColor)
Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
public:
void setCurrentPattern(AutomationPattern * new_pattern);
void setCurrentClip(AutomationClip * new_clip);
inline const AutomationPattern * currentPattern() const
inline const AutomationClip * currentClip() const
{
return m_pattern;
return m_clip;
}
inline bool validPattern() const
inline bool validClip() const
{
return m_pattern != nullptr;
return m_clip != nullptr;
}
virtual void saveSettings(QDomDocument & doc, QDomElement & parent);
virtual void loadSettings(const QDomElement & parent);
QString nodeName() const
void saveSettings(QDomDocument & doc, QDomElement & parent) override;
void loadSettings(const QDomElement & parent) override;
QString nodeName() const override
{
return "automationeditor";
}
// qproperty access methods
QColor barLineColor() const;
void setBarLineColor(const QColor & c);
QColor beatLineColor() const;
void setBeatLineColor(const QColor & c);
QColor lineColor() const;
void setLineColor(const QColor & c);
QBrush graphColor() const;
void setGraphColor(const QBrush & c);
QColor vertexColor() const;
void setVertexColor(const QColor & c);
QBrush scaleColor() const;
void setScaleColor(const QBrush & c);
QColor crossColor() const;
void setCrossColor(const QColor & c);
QColor backgroundShade() const;
void setBackgroundShade(const QColor & c);
enum EditModes
{
DRAW,
ERASE,
SELECT,
MOVE
DRAW_OUTVALUES
};
public slots:
void update();
void updateAfterPatternChange();
void updateAfterClipChange();
protected:
typedef AutomationPattern::timeMap timeMap;
using timeMap = AutomationClip::timeMap;
virtual void keyPressEvent(QKeyEvent * ke);
virtual void leaveEvent(QEvent * e);
virtual void mousePressEvent(QMouseEvent * mouseEvent);
virtual void mouseReleaseEvent(QMouseEvent * mouseEvent);
virtual void mouseMoveEvent(QMouseEvent * mouseEvent);
virtual void paintEvent(QPaintEvent * pe);
virtual void resizeEvent(QResizeEvent * re);
virtual void wheelEvent(QWheelEvent * we);
void keyPressEvent(QKeyEvent * ke) override;
void leaveEvent(QEvent * e) override;
void mousePressEvent(QMouseEvent * mouseEvent) override;
void mouseDoubleClickEvent(QMouseEvent * mouseEvent) override;
void mouseReleaseEvent(QMouseEvent * mouseEvent) override;
void mouseMoveEvent(QMouseEvent * mouseEvent) override;
void paintEvent(QPaintEvent * pe) override;
void resizeEvent(QResizeEvent * re) override;
void wheelEvent(QWheelEvent * we) override;
float getLevel( int y );
int xCoordOfTick( int tick );
float yCoordOfLevel( float level );
inline void drawLevelTick( QPainter & p, int tick, float value);// bool is_selected ); //NEEDS Change in CSS
void removeSelection();
void selectAll();
void getSelectedValues(timeMap & selected_values );
inline void drawLevelTick(QPainter & p, int tick, float value);
timeMap::iterator getNodeAt(int x, int y, bool outValue = false, int r = 5);
void drawLine( int x0, float y0, int x1, float y1 );
void removePoints( int x0, int x1 );
bool fineTuneValue(timeMap::iterator node, bool editingOutValue);
protected slots:
void play();
@@ -144,21 +131,16 @@ protected slots:
void setEditMode(AutomationEditor::EditModes mode);
void setEditMode(int mode);
void setProgressionType(AutomationPattern::ProgressionTypes type);
void setProgressionType(AutomationClip::ProgressionTypes type);
void setProgressionType(int type);
void setTension();
void copySelectedValues();
void cutSelectedValues();
void pasteValues();
void deleteSelectedValues();
void updatePosition( const MidiTime & t );
void updatePosition( const lmms::TimePos & t );
void zoomingXChanged();
void zoomingYChanged();
/// Updates the pattern's quantization using the current user selected value.
/// Updates the clip's quantization using the current user selected value.
void setQuantization();
private:
@@ -167,8 +149,10 @@ private:
{
NONE,
MOVE_VALUE,
SELECT_VALUES,
MOVE_SELECTION
ERASE_VALUES,
MOVE_OUTVALUE,
RESET_OUTVALUES,
DRAW_LINE
} ;
// some constants...
@@ -176,18 +160,18 @@ private:
static const int TOP_MARGIN = 16;
static const int DEFAULT_Y_DELTA = 6;
static const int DEFAULT_STEPS_PER_TACT = 16;
static const int DEFAULT_PPT = 12 * DEFAULT_STEPS_PER_TACT;
static const int DEFAULT_STEPS_PER_BAR = 16;
static const int DEFAULT_PPB = 12 * DEFAULT_STEPS_PER_BAR;
static const int VALUES_WIDTH = 64;
AutomationEditor();
AutomationEditor( const AutomationEditor & );
virtual ~AutomationEditor();
~AutomationEditor() override;
static QPixmap * s_toolDraw;
static QPixmap * s_toolErase;
static QPixmap * s_toolSelect;
static QPixmap * s_toolDrawOut;
static QPixmap * s_toolMove;
static QPixmap * s_toolYFlip;
static QPixmap * s_toolXFlip;
@@ -196,12 +180,11 @@ private:
ComboBoxModel m_zoomingYModel;
ComboBoxModel m_quantizeModel;
static const QVector<double> m_zoomXLevels;
static const QVector<float> m_zoomXLevels;
FloatModel * m_tensionModel;
QMutex m_patternMutex;
AutomationPattern * m_pattern;
AutomationClip * m_clip;
float m_minLevel;
float m_maxLevel;
float m_step;
@@ -209,37 +192,31 @@ 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;
tick_t m_selectStartTick;
tick_t m_selectedTick;
float m_selectStartLevel;
float m_selectedLevels;
float m_moveStartLevel;
tick_t m_moveStartTick;
int m_moveXOffset;
float m_drawLastLevel;
tick_t m_drawLastTick;
int m_ppt;
int m_ppb;
int m_y_delta;
bool m_y_auto;
timeMap m_valuesToCopy;
timeMap m_selValuesForMove;
// Time position (key) of automation node whose outValue is being dragged
int m_draggedOutValueKey;
EditModes m_editMode;
bool m_mouseDownLeft;
bool m_mouseDownRight; //true if right click is being held down
TimeLineWidget * m_timeLine;
@@ -247,13 +224,14 @@ private:
void drawCross(QPainter & p );
void drawAutomationPoint( QPainter & p, timeMap::iterator it );
bool inBBEditor();
bool inPatternEditor();
QColor m_barLineColor;
QColor m_beatLineColor;
QColor m_lineColor;
QBrush m_graphColor;
QColor m_vertexColor;
QColor m_nodeInValueColor;
QColor m_nodeOutValueColor;
QBrush m_scaleColor;
QColor m_crossColor;
QColor m_backgroundShade;
@@ -262,8 +240,8 @@ private:
signals:
void currentPatternChanged();
void positionChanged( const MidiTime & );
void currentClipChanged();
void positionChanged( const lmms::TimePos & );
} ;
@@ -277,29 +255,32 @@ class AutomationEditorWindow : public Editor
static const int INITIAL_HEIGHT = 480;
public:
AutomationEditorWindow();
~AutomationEditorWindow();
~AutomationEditorWindow() override = default;
void setCurrentPattern(AutomationPattern* pattern);
const AutomationPattern* currentPattern();
void setCurrentClip(AutomationClip* clip);
const AutomationClip* currentClip();
virtual void dropEvent( QDropEvent * _de );
virtual void dragEnterEvent( QDragEnterEvent * _dee );
void dropEvent( QDropEvent * _de ) override;
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void open(AutomationPattern* pattern);
void open(AutomationClip* clip);
AutomationEditor* m_editor;
QSize sizeHint() const;
QSize sizeHint() const override;
public slots:
void clearCurrentPattern();
void clearCurrentClip();
signals:
void currentPatternChanged();
void currentClipChanged();
protected:
void focusInEvent(QFocusEvent * event) override;
protected slots:
void play();
void stop();
void play() override;
void stop() override;
private slots:
void updateWindowTitle();
@@ -319,5 +300,8 @@ private:
ComboBox * m_quantizeComboBox;
};
} // namespace gui
} // namespace lmms
#endif

159
include/AutomationNode.h Normal file
View File

@@ -0,0 +1,159 @@
/*
* AutomationNode.h - Declaration of class AutomationNode, which contains
* all information about an automation node
*
* Copyright (c) 2020 Ian Caio <iancaio_dev/at/hotmail.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 AUTOMATION_NODE_H
#define AUTOMATION_NODE_H
namespace lmms
{
class AutomationClip;
// Note: We use the default copy-assignment on the AutomationClip constructor. It's
// fine for now as we don't have dynamic allocated members, but if any are added we should
// have an user-defined one to perform a deep-copy.
class AutomationNode
{
public:
AutomationNode(); // Dummy constructor for the QMap
AutomationNode(AutomationClip* clip, float value, int pos);
AutomationNode(AutomationClip* clip, float inValue, float outValue, int pos);
AutomationNode& operator+=(float f)
{
m_inValue += f;
m_outValue += f;
return *this;
}
AutomationNode& operator-=(float f)
{
m_inValue -= f;
m_outValue -= f;
return *this;
}
AutomationNode& operator*=(float f)
{
m_inValue *= f;
m_outValue *= f;
return *this;
}
AutomationNode& operator/=(float f)
{
m_inValue /= f;
m_outValue /= f;
return *this;
}
inline const float getInValue() const
{
return m_inValue;
}
void setInValue(float value);
inline const float getOutValue() const
{
return m_outValue;
}
void setOutValue(float value);
void resetOutValue();
/**
* @brief Gets the offset between inValue and outValue
* @return Float representing the offset between inValue and outValue
*/
inline const float getValueOffset() const
{
return m_outValue - m_inValue;
}
/**
* @brief Gets the tangent of the left side of the node
* @return Float with the tangent from the inValue side
*/
inline const float getInTangent() const
{
return m_inTangent;
}
/**
* @brief Sets the tangent of the left side of the node
* @param Float with the tangent for the inValue side
*/
inline void setInTangent(float tangent)
{
m_inTangent = tangent;
}
/**
* @brief Gets the tangent of the right side of the node
* @return Float with the tangent from the outValue side
*/
inline const float getOutTangent() const
{
return m_outTangent;
}
/**
* @brief Sets the tangent of the right side of the node
* @param Float with the tangent for the outValue side
*/
inline void setOutTangent(float tangent)
{
m_outTangent = tangent;
}
/**
* @brief Sets the clip this node belongs to
* @param AutomationClip* clip that m_clip will be
* set to
*/
inline void setClip(AutomationClip* clip)
{
m_clip = clip;
}
private:
// Clip that this node belongs to
AutomationClip* m_clip;
// Time position of this node (matches the timeMap key)
int m_pos;
// Values of this node
float m_inValue;
float m_outValue;
// Slope at each point for calculating spline
// We might have discrete jumps between curves, so we possibly have
// two different tangents for each side of the curve. If inValue and
// outValue are equal, inTangent and outTangent are equal too.
float m_inTangent;
float m_outTangent;
};
} // namespace lmms
#endif

View File

@@ -29,28 +29,30 @@
#include "Track.h"
namespace lmms
{
class AutomationTrack : public Track
{
Q_OBJECT
public:
AutomationTrack( TrackContainer* tc, bool _hidden = false );
virtual ~AutomationTrack() = default;
~AutomationTrack() override = default;
virtual bool play( const MidiTime & _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _tco_num = -1 );
bool play( const TimePos & _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _clip_num = -1 ) override;
virtual QString nodeName() const
QString nodeName() const override
{
return "automationtrack";
}
virtual TrackView * createView( TrackContainerView* );
virtual TrackContentObject * createTCO( const MidiTime & _pos );
gui::TrackView * createView( gui::TrackContainerView* ) override;
Clip* createClip(const TimePos & pos) override;
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void loadTrackSpecificSettings( const QDomElement & _this );
void saveTrackSpecificSettings( QDomDocument & _doc,
QDomElement & _parent ) override;
void loadTrackSpecificSettings( const QDomElement & _this ) override;
private:
friend class AutomationTrackView;
@@ -58,17 +60,6 @@ private:
} ;
class AutomationTrackView : public TrackView
{
public:
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
virtual ~AutomationTrackView() = default;
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
} ;
} // namespace lmms
#endif

View File

@@ -0,0 +1,55 @@
/*
* AutomationTrackView.h - declaration of class AutomationTrackView
*
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/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 AUTOMATION_TRACK_VIEW_H
#define AUTOMATION_TRACK_VIEW_H
#include "TrackView.h"
namespace lmms
{
class AutomationTrack;
namespace gui
{
class AutomationTrackView : public TrackView
{
public:
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
~AutomationTrackView() override = default;
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void dropEvent( QDropEvent * _de ) override;
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -1,234 +0,0 @@
/*
* BBTrack.h - class BBTrack, a wrapper for using bbEditor
* (which is a singleton-class) as track
*
* 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 BB_TRACK_H
#define BB_TRACK_H
#include <QtCore/QObject>
#include <QtCore/QMap>
#include <QStaticText>
#include "Track.h"
class TrackLabelButton;
class TrackContainer;
class BBTCO : public TrackContentObject
{
public:
BBTCO( Track * _track );
virtual ~BBTCO() = default;
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
inline virtual QString nodeName() const
{
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();
virtual TrackContentObjectView * createView( TrackView * _tv );
private:
QColor m_color;
bool m_useStyleColor;
friend class BBTCOView;
} ;
class BBTCOView : public TrackContentObjectView
{
Q_OBJECT
public:
BBTCOView( TrackContentObject * _tco, TrackView * _tv );
virtual ~BBTCOView() = default;
QColor color() const
{
return( m_bbTCO->m_color );
}
void setColor( QColor _new_color );
public slots:
virtual void update();
protected slots:
void openInBBEditor();
void resetName();
void changeName();
void changeColor();
void resetColor();
protected:
virtual void paintEvent( QPaintEvent * pe );
virtual void mouseDoubleClickEvent( QMouseEvent * _me );
virtual void constructContextMenu( QMenu * );
private:
BBTCO * m_bbTCO;
QPixmap m_paintPixmap;
QStaticText m_staticTextName;
} ;
class LMMS_EXPORT BBTrack : public Track
{
Q_OBJECT
public:
BBTrack( TrackContainer* tc );
virtual ~BBTrack();
virtual bool play( const MidiTime & _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _tco_num = -1 );
virtual TrackView * createView( TrackContainerView* tcv );
virtual TrackContentObject * createTCO( const MidiTime & _pos );
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void loadTrackSpecificSettings( const QDomElement & _this );
static BBTrack * findBBTrack( int _bb_num );
static void swapBBTracks( Track * _track1, Track * _track2 );
int index()
{
return s_infoMap[this];
}
bool automationDisabled( Track * _track )
{
return( m_disabledTracks.contains( _track ) );
}
void disableAutomation( Track * _track )
{
m_disabledTracks.append( _track );
}
void enableAutomation( Track * _track )
{
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 virtual QString nodeName() const
{
return( "bbtrack" );
}
private:
QList<Track *> m_disabledTracks;
typedef QMap<BBTrack *, int> infoMap;
static infoMap s_infoMap;
static QColor * s_lastTCOColor;
friend class BBTrackView;
} ;
class BBTrackView : public TrackView
{
Q_OBJECT
public:
BBTrackView( BBTrack* bbt, TrackContainerView* tcv );
virtual ~BBTrackView();
virtual bool close();
const BBTrack * getBBTrack() const
{
return( m_bbTrack );
}
public slots:
void clickedTrackLabel();
private:
BBTrack * m_bbTrack;
TrackLabelButton * m_trackLabel;
} ;
#endif

View File

@@ -1,83 +0,0 @@
/*
* BBTrackContainer.h - model-component of BB-Editor
*
* 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 BB_TRACK_CONTAINER_H
#define BB_TRACK_CONTAINER_H
#include "TrackContainer.h"
#include "ComboBoxModel.h"
class LMMS_EXPORT BBTrackContainer : public TrackContainer
{
Q_OBJECT
mapPropertyFromModel(int,currentBB,setCurrentBB,m_bbComboBoxModel);
public:
BBTrackContainer();
virtual ~BBTrackContainer();
virtual bool play( MidiTime _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _tco_num = -1 );
virtual void updateAfterTrackAdd() override;
inline virtual QString nodeName() const override
{
return "bbtrackcontainer";
}
tact_t lengthOfBB( int _bb ) const;
inline tact_t lengthOfCurrentBB()
{
return lengthOfBB( currentBB() );
}
int numOfBBs() const;
void removeBB( int _bb );
void swapBB( int _bb1, int _bb2 );
void updateBBTrack( TrackContentObject * _tco );
void fixIncorrectPositions();
void createTCOsForBB( int _bb );
AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum) const override;
public slots:
void play();
void stop();
void updateComboBox();
void currentBBChanged();
private:
ComboBoxModel m_bbComboBoxModel;
friend class BBEditor;
} ;
#endif

View File

@@ -34,14 +34,17 @@ class QString;
#include "lmms_basics.h"
#include "lmms_math.h"
#include "Engine.h"
#include "Mixer.h"
#include "AudioEngine.h"
#define MAXLEN 11
#define MIPMAPSIZE 2 << ( MAXLEN + 1 )
#define MIPMAPSIZE3 3 << ( MAXLEN + 1 )
#define MAXTBL 23
#define MINTLEN 2 << 0
#define MAXTLEN 3 << MAXLEN
namespace lmms
{
constexpr int MAXLEN = 11;
constexpr int MIPMAPSIZE = 2 << ( MAXLEN + 1 );
constexpr int MIPMAPSIZE3 = 3 << ( MAXLEN + 1 );
constexpr int MAXTBL = 23;
constexpr int MINTLEN = 2 << 0;
constexpr int MAXTLEN = 3 << MAXLEN;
// table for table sizes
const int TLENS[MAXTBL+1] = { 2 << 0, 3 << 0, 2 << 1, 3 << 1,
@@ -51,29 +54,30 @@ const int TLENS[MAXTBL+1] = { 2 << 0, 3 << 0, 2 << 1, 3 << 1,
2 << 8, 3 << 8, 2 << 9, 3 << 9,
2 << 10, 3 << 10, 2 << 11, 3 << 11 };
typedef struct
struct WaveMipMap
{
public:
inline sample_t sampleAt( int table, int ph )
inline sample_t sampleAt(int table, int ph)
{
if( table % 2 == 0 )
{ return m_data[ TLENS[ table ] + ph ]; }
if (table % 2 == 0) { return m_data[TLENS[table] + ph]; }
else
{ return m_data3[ TLENS[ table ] + ph ]; }
{
return m_data3[TLENS[table] + ph];
}
}
inline void setSampleAt( int table, int ph, sample_t sample )
inline void setSampleAt(int table, int ph, sample_t sample)
{
if( table % 2 == 0 )
{ m_data[ TLENS[ table ] + ph ] = sample; }
if (table % 2 == 0) { m_data[TLENS[table] + ph] = sample; }
else
{ m_data3[ TLENS[ table ] + ph ] = sample; }
{
m_data3[TLENS[table] + ph] = sample;
}
}
private:
sample_t m_data [ MIPMAPSIZE ];
sample_t m_data3 [ MIPMAPSIZE3 ];
} WaveMipMap;
sample_t m_data[MIPMAPSIZE];
sample_t m_data3[MIPMAPSIZE3];
};
QDataStream& operator<< ( QDataStream &out, WaveMipMap &waveMipMap );
@@ -94,15 +98,15 @@ public:
NumBLWaveforms
};
BandLimitedWave() {};
virtual ~BandLimitedWave() {};
BandLimitedWave() = default;
virtual ~BandLimitedWave() = default;
/*! \brief This method converts frequency to wavelength. The oscillate function takes wavelength as argument so
* use this to convert your note frequency to wavelength before using it.
*/
static inline float freqToLen( float f )
{
return freqToLen( f, Engine::mixer()->processingSampleRate() );
return freqToLen( f, Engine::audioEngine()->processingSampleRate() );
}
/*! \brief This method converts frequency to wavelength, but you can use any custom sample rate with it.
@@ -163,10 +167,11 @@ public:
static bool s_wavesGenerated;
static WaveMipMap s_waveforms [NumBLWaveforms];
static std::array<WaveMipMap, NumBLWaveforms> s_waveforms;
static QString s_wavetableDir;
};
} // namespace lmms
#endif

View File

@@ -36,13 +36,16 @@
#define __USE_XOPEN
#endif
#include <math.h>
#include <cmath>
#include "lmms_basics.h"
#include "lmms_constants.h"
#include "interpolation.h"
#include "MemoryManager.h"
namespace lmms
{
template<ch_cnt_t CHANNELS=DEFAULT_CHANNELS> class BasicFilters;
template<ch_cnt_t CHANNELS>
@@ -55,7 +58,7 @@ public:
m_sampleRate = sampleRate;
clearHistory();
}
virtual ~LinkwitzRiley() {}
virtual ~LinkwitzRiley() = default;
inline void clearHistory()
{
@@ -135,10 +138,10 @@ private:
double m_a, m_a0, m_a1, m_a2;
double m_b1, m_b2, m_b3, m_b4;
typedef double frame[CHANNELS];
using frame = std::array<double, CHANNELS>;
frame m_z1, m_z2, m_z3, m_z4;
};
typedef LinkwitzRiley<2> StereoLinkwitzRiley;
using StereoLinkwitzRiley = LinkwitzRiley<2>;
template<ch_cnt_t CHANNELS>
class BiQuad
@@ -149,7 +152,7 @@ public:
{
clearHistory();
}
virtual ~BiQuad() {}
virtual ~BiQuad() = default;
inline void setCoeffs( float a1, float a2, float b0, float b1, float b2 )
{
@@ -181,7 +184,7 @@ private:
friend class BasicFilters<CHANNELS>; // needed for subfilter stuff in BasicFilters
};
typedef BiQuad<2> StereoBiQuad;
using StereoBiQuad = BiQuad<2>;
template<ch_cnt_t CHANNELS>
class OnePole
@@ -197,7 +200,7 @@ public:
m_z1[i] = 0.0;
}
}
virtual ~OnePole() {}
virtual ~OnePole() = default;
inline void setCoeffs( float a0, float b1 )
{
@@ -215,7 +218,7 @@ private:
float m_a0, m_b1;
float m_z1 [CHANNELS];
};
typedef OnePole<2> StereoOnePole;
using StereoOnePole = OnePole<2>;
template<ch_cnt_t CHANNELS>
class BasicFilters
@@ -273,7 +276,7 @@ public:
m_type = _idx == DoubleLowPass
? LowPass
: Moog;
if( m_subFilter == NULL )
if( m_subFilter == nullptr )
{
m_subFilter = new BasicFilters<CHANNELS>(
static_cast<sample_rate_t>(
@@ -286,7 +289,7 @@ public:
m_doubleFilter( false ),
m_sampleRate( (float) _sample_rate ),
m_sampleRatio( 1.0f / m_sampleRate ),
m_subFilter( NULL )
m_subFilter( nullptr )
{
clearHistory();
}
@@ -886,7 +889,7 @@ private:
// coeffs for Lowpass_SV (state-variant lowpass)
float m_svf1, m_svf2, m_svq;
typedef sample_t frame[CHANNELS];
using frame = std::array<sample_t, CHANNELS>;
// in/out history for moog-filter
frame m_y1, m_y2, m_y3, m_y4, m_oldx, m_oldy1, m_oldy2, m_oldy3;
@@ -913,4 +916,6 @@ private:
} ;
} // namespace lmms
#endif

View File

@@ -29,10 +29,14 @@
#include "lmms_export.h"
#include "lmms_basics.h"
namespace lmms
{
class LMMS_EXPORT BufferManager
{
public:
static void init( fpp_t framesPerPeriod );
static void init( fpp_t fpp );
static sampleFrame * acquire();
// audio-buffer-mgm
static void clear( sampleFrame * ab, const f_cnt_t frames,
@@ -42,6 +46,12 @@ public:
const f_cnt_t offset = 0 );
#endif
static void release( sampleFrame * buf );
private:
static fpp_t s_framesPerPeriod;
};
} // namespace lmms
#endif

View File

@@ -27,23 +27,27 @@
#ifndef CPULOAD_WIDGET_H
#define CPULOAD_WIDGET_H
#include <QtCore/QTimer>
#include <QTimer>
#include <QPixmap>
#include <QWidget>
#include "lmms_basics.h"
namespace lmms::gui
{
class CPULoadWidget : public QWidget
{
Q_OBJECT
public:
CPULoadWidget( QWidget * _parent );
virtual ~CPULoadWidget();
~CPULoadWidget() override = default;
protected:
virtual void paintEvent( QPaintEvent * _ev );
void paintEvent( QPaintEvent * _ev ) override;
protected slots:
@@ -64,4 +68,6 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -30,6 +30,9 @@
#include "lmms_export.h"
namespace lmms::gui
{
///
/// \brief A context menu with a caption
///
@@ -38,10 +41,10 @@ class LMMS_EXPORT CaptionMenu : public QMenu
Q_OBJECT
public:
CaptionMenu( const QString & _title, QWidget * _parent = 0 );
virtual ~CaptionMenu();
~CaptionMenu() override = default;
} ;
} // namespace lmms::gui
#endif

197
include/Clip.h Normal file
View File

@@ -0,0 +1,197 @@
/*
* TrackConteintObject.h - declaration of Clip 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"
namespace lmms
{
class Track;
class TrackContainer;
namespace gui
{
class ClipView;
class TrackView;
} // namespace gui
class LMMS_EXPORT Clip : public Model, public JournallingObject
{
Q_OBJECT
MM_OPERATORS
mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel);
mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel);
public:
Clip( Track * track );
~Clip() override;
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;
}
/*! \brief Specify whether or not a TCO automatically resizes.
*
* If a TCO does automatically resize, it cannot be manually
* resized by clicking and dragging its edge.
*
*/
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 gui::ClipView * createView( gui::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 Clip* a, const Clip* b);
TimePos startTimeOffset() const;
void setStartTimeOffset( const TimePos &startTimeOffset );
// Will copy the state of a clip to another clip
static void copyStateTo( Clip *src, Clip *dst );
public slots:
void toggleMute();
signals:
void lengthChanged();
void positionChanged();
void destroyedClip();
void colorChanged();
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 ClipView;
} ;
} // namespace lmms
#endif

255
include/ClipView.h Normal file
View File

@@ -0,0 +1,255 @@
/*
* ClipView.h - declaration of ClipView class
*
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef TRACK_CONTENT_OBJECT_VIEW_H
#define TRACK_CONTENT_OBJECT_VIEW_H
#include <QVector>
#include "ModelView.h"
#include "Rubberband.h"
#include "Clip.h"
class QMenu;
class QContextMenuEvent;
namespace lmms
{
class DataFile;
class Clip;
namespace gui
{
class TextFloat;
class TrackView;
class ClipView : 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 patternClipBackground READ patternClipBackground WRITE setPatternClipBackground )
Q_PROPERTY( bool gradient READ gradient WRITE setGradient )
// We have to use a QSize here because using QPoint isn't supported.
// width -> x, height -> y
Q_PROPERTY( QSize mouseHotspotHand MEMBER m_mouseHotspotHand )
Q_PROPERTY( QSize mouseHotspotKnife MEMBER m_mouseHotspotKnife )
public:
const static int BORDER_WIDTH = 2;
ClipView( Clip * clip, TrackView * tv );
~ClipView() override;
bool fixedClips();
inline Clip * getClip()
{
return m_clip;
}
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 patternClipBackground() 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 setPatternClipBackground(const QColor& c);
void setGradient( const bool & b );
// access needsUpdate member variable
bool needsUpdate();
void setNeedsUpdate( bool b );
// Method to get a QVector of Clips to be affected by a context menu action
QVector<ClipView *> getClickedClips();
// Methods to remove, copy, cut, paste and mute a QVector of Clip views
void copy( QVector<ClipView *> clipvs );
void cut( QVector<ClipView *> clipvs );
void paste();
// remove and toggleMute are static because they don't depend
// being called from a particular Clip view, but can be called anywhere as long
// as a valid Clip view list is given, while copy/cut require an instance for
// some metadata to be written to the clipboard.
static void remove( QVector<ClipView *> clipvs );
static void toggleMute( QVector<ClipView *> clipvs );
static void mergeClips(QVector<ClipView*> clipvs);
// Returns true if selection can be merged and false if not
static bool canMergeSelection(QVector<ClipView*> clipvs);
QColor getColorForDisplay( QColor );
void inline setMarkerPos(int x) { m_markerPos = x; }
void inline setMarkerEnabled(bool e) { m_marker = e; }
public slots:
virtual bool close();
void remove();
void update() override;
void selectColor();
void randomizeColor();
void resetColor();
protected:
enum ContextMenuAction
{
Remove,
Cut,
Copy,
Paste,
Mute,
Merge
};
TrackView * m_trackView;
TimePos m_initialClipPos;
TimePos m_initialClipEnd;
bool m_marker = false;
int m_markerPos = 0;
virtual void constructContextMenu( QMenu * )
{
}
void contextMenuEvent( QContextMenuEvent * cme ) override;
void contextMenuAction( ContextMenuAction action );
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 resizeEvent( QResizeEvent * re ) override
{
m_needsUpdate = true;
selectableObject::resizeEvent( re );
}
bool unquantizedModHeld( QMouseEvent * me );
TimePos quantizeSplitPos( TimePos, bool shiftMode );
float pixelsPerBar();
DataFile createClipDataFiles(const QVector<ClipView *> & clips) const;
virtual void paintTextLabel(QString const & text, QPainter & painter);
protected slots:
void updateLength();
void updatePosition();
private:
enum Actions
{
NoAction,
Move,
MoveSelection,
Resize,
ResizeLeft,
Split,
CopySelection,
ToggleSelected
} ;
static TextFloat * s_textFloat;
Clip * m_clip;
Actions m_action;
QPoint m_initialMousePos;
QPoint m_initialMouseGlobalPos;
QVector<TimePos> m_initialOffsets;
TextFloat * m_hint;
// qproperty fields
QColor m_mutedColor;
QColor m_mutedBackgroundColor;
QColor m_selectedColor;
QColor m_textColor;
QColor m_textBackgroundColor;
QColor m_textShadowColor;
QColor m_patternClipBackground;
bool m_gradient;
QSize m_mouseHotspotHand; // QSize must be used because QPoint
QSize m_mouseHotspotKnife; // isn't supported by property system
QCursor m_cursorHand;
QCursor m_cursorKnife;
bool m_cursorSetYet;
bool m_needsUpdate;
inline void setInitialPos( QPoint pos )
{
m_initialMousePos = pos;
m_initialMouseGlobalPos = mapToGlobal( pos );
m_initialClipPos = m_clip->startPosition();
m_initialClipEnd = m_initialClipPos + m_clip->length();
}
void setInitialOffsets();
bool mouseMovedDistance( QMouseEvent * me, int distance );
TimePos draggedClipPos( QMouseEvent * me );
int knifeMarkerPos( QMouseEvent * me );
void setColor(const QColor* color);
//! Return true iff the clip could be split. Currently only implemented for samples
virtual bool splitClip( const TimePos pos ){ return false; };
void updateCursor(QMouseEvent * me);
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -1,5 +1,5 @@
/*
* Clipboard.h - the clipboard for patterns, notes etc.
* Clipboard.h - the clipboard for clips, notes etc.
*
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -25,29 +25,47 @@
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include <QtCore/QMap>
#include <QMap>
#include <QDomElement>
class QMimeData;
class JournallingObject;
class Clipboard
namespace lmms::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;
} ;
} // namespace lmms::Clipboard
#endif

72
include/ColorChooser.h Normal file
View File

@@ -0,0 +1,72 @@
/* ColorChooser.h - declaration and definition of ColorChooser class.
*
* Copyright (c) 2019 CYBERDEViLNL <cyberdevilnl/at/protonmail/dot/ch>
*
* 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 COLOR_CHOOSER_H
#define COLOR_CHOOSER_H
#include <QApplication>
#include <QColor>
#include <QColorDialog>
#include <QKeyEvent>
#include <QVector>
namespace lmms::gui
{
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() = default;
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
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);
};
} // namespace lmms::gui
#endif

View File

@@ -32,14 +32,15 @@
#include "ComboBoxModel.h"
#include "AutomatableModelView.h"
namespace lmms::gui
{
class LMMS_EXPORT ComboBox : public QWidget, public IntModelView
{
Q_OBJECT
public:
ComboBox( QWidget* parent = NULL, const QString& name = QString() );
virtual ~ComboBox();
ComboBox( QWidget* parent = nullptr, const QString& name = QString() );
~ComboBox() override = default;
ComboBoxModel* model()
{
@@ -51,16 +52,18 @@ public:
return castModel<ComboBoxModel>();
}
static constexpr int DEFAULT_HEIGHT = 22;
public slots:
void selectNext();
void selectPrevious();
protected:
virtual void contextMenuEvent( QContextMenuEvent* event );
virtual void mousePressEvent( QMouseEvent* event );
virtual void paintEvent( QPaintEvent* event );
virtual void wheelEvent( QWheelEvent* event );
void contextMenuEvent( QContextMenuEvent* event ) override;
void mousePressEvent( QMouseEvent* event ) override;
void paintEvent( QPaintEvent* event ) override;
void wheelEvent( QWheelEvent* event ) override;
private:
@@ -78,4 +81,6 @@ private slots:
} ;
} // namespace lmms::gui
#endif

View File

@@ -32,26 +32,30 @@
#include "AutomatableModel.h"
#include "embed.h"
namespace lmms
{
class LMMS_EXPORT ComboBoxModel : public IntModel
{
Q_OBJECT
MODEL_IS_VISITABLE
public:
ComboBoxModel( Model* parent = NULL,
ComboBoxModel( Model* parent = nullptr,
const QString& displayName = QString(),
bool isDefaultConstructed = false ) :
IntModel( 0, 0, 0, parent, displayName, isDefaultConstructed )
{
}
virtual ~ComboBoxModel()
~ComboBoxModel() override
{
clear();
}
void addItem( QString item, std::unique_ptr<PixmapLoader> loader = nullptr );
void replaceItem(std::size_t index, QString item, std::unique_ptr<PixmapLoader> loader = nullptr);
void clear();
int findText( const QString& txt ) const;
@@ -83,11 +87,12 @@ public:
private:
typedef std::pair<QString, std::unique_ptr<PixmapLoader> > Item;
using Item = std::pair<QString, std::unique_ptr<PixmapLoader>>;
std::vector<Item> m_items;
} ;
} // namespace lmms
#endif

View File

@@ -28,16 +28,20 @@
#include "lmmsconfig.h"
#include <QtCore/QMap>
#include <QtCore/QPair>
#include <QtCore/QStringList>
#include <QtCore/QVector>
#include <QtCore/QObject>
#include <QMap>
#include <QPair>
#include <QStringList>
#include <QVector>
#include <QObject>
#include "lmms_export.h"
class LmmsCore;
namespace lmms
{
class Engine;
const QString PROJECTS_PATH = "projects/";
const QString TEMPLATE_PATH = "templates/";
@@ -49,69 +53,39 @@ 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()
{
if( s_instanceOfMe == NULL )
if(s_instanceOfMe == nullptr )
{
s_instanceOfMe = new ConfigManager();
}
return s_instanceOfMe;
}
const QString & dataDir() const
{
return m_dataDir;
}
const QString & workingDir() const
{
return m_workingDir;
}
QString userProjectsDir() const
{
return workingDir() + PROJECTS_PATH;
}
void initPortableWorkingDir();
QString userTemplateDir() const
{
return workingDir() + TEMPLATE_PATH;
}
void initInstalledWorkingDir();
QString userPresetsDir() const
{
return workingDir() + PRESETS_PATH;
}
void initDevelopmentWorkingDir();
QString userSamplesDir() const
const QString & dataDir() const
{
return workingDir() + SAMPLES_PATH;
}
QString userGigDir() const
{
return workingDir() + GIG_PATH;
}
QString userSf2Dir() const
{
return workingDir() + SF2_PATH;
}
QString userLadspaDir() const
{
return workingDir() + LADSPA_PATH;
}
QString userVstDir() const
{
return m_vstDir;
return m_dataDir;
}
QString factoryProjectsDir() const
@@ -134,37 +108,27 @@ public:
return dataDir() + SAMPLES_PATH;
}
QString defaultVersion() const;
QString defaultArtworkDir() const
QString userProjectsDir() const
{
return m_dataDir + DEFAULT_THEME_PATH;
return workingDir() + PROJECTS_PATH;
}
QString artworkDir() const
QString userTemplateDir() const
{
return m_artworkDir;
return workingDir() + TEMPLATE_PATH;
}
QString trackIconsDir() const
QString userPresetsDir() const
{
return m_dataDir + TRACK_ICON_PATH;
return workingDir() + PRESETS_PATH;
}
QString localeDir() const
QString userSamplesDir() const
{
return m_dataDir + LOCALE_PATH;
return workingDir() + SAMPLES_PATH;
}
const QString & gigDir() const
{
return m_gigDir;
}
const QString & sf2Dir() const
{
return m_sf2Dir;
}
const QString & vstDir() const
{
@@ -173,18 +137,20 @@ public:
const QString & ladspaDir() const
{
return m_ladDir;
return m_ladspaDir;
}
const QString recoveryFile() const
const QString & sf2Dir() const
{
return m_workingDir + "recover.mmp";
return m_sf2Dir;
}
const QString & version() const
#ifdef LMMS_HAVE_FLUIDSYNTH
const QString & sf2File() const
{
return m_version;
return m_sf2File;
}
#endif
#ifdef LMMS_HAVE_STK
const QString & stkDir() const
@@ -193,16 +159,55 @@ public:
}
#endif
#ifdef LMMS_HAVE_FLUIDSYNTH
const QString & defaultSoundfont() const
const QString & gigDir() const
{
return m_defaultSoundfont;
return m_gigDir;
}
#endif
const QString & backgroundArtwork() const
QString userVstDir() const
{
return m_backgroundArtwork;
return m_vstDir;
}
QString userLadspaDir() const
{
return workingDir() + LADSPA_PATH;
}
QString userSf2Dir() const
{
return workingDir() + SF2_PATH;
}
QString userGigDir() const
{
return workingDir() + GIG_PATH;
}
QString defaultThemeDir() const
{
return m_dataDir + DEFAULT_THEME_PATH;
}
QString themeDir() const
{
return m_themeDir;
}
const QString & backgroundPicFile() const
{
return m_backgroundPicFile;
}
QString trackIconsDir() const
{
return m_dataDir + TRACK_ICON_PATH;
}
const QString recoveryFile() const
{
return m_workingDir + "recover.mmp";
}
inline const QStringList & recentlyOpenedProjects() const
@@ -210,39 +215,55 @@ public:
return m_recentlyOpenedProjects;
}
static QStringList availabeVstEmbedMethods();
QString localeDir() const
{
return m_dataDir + LOCALE_PATH;
}
const QString & version() const
{
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 availableVstEmbedMethods();
QString vstEmbedMethod() const;
// returns true if the working dir (e.g. ~/lmms) exists on disk
// Returns true if the working dir (e.g. ~/lmms) exists on disk.
bool hasWorkingDir() const;
void addRecentlyOpenedProject( const QString & _file );
void addRecentlyOpenedProject(const QString & _file);
const QString & value( const QString & cls,
const QString & attribute ) const;
const QString & value( const QString & cls,
const QString & value(const QString & cls,
const QString & attribute) const;
const QString & value(const QString & cls,
const QString & attribute,
const QString & defaultVal ) const;
void setValue( const QString & cls, const QString & attribute,
const QString & value );
void deleteValue( const QString & cls, const QString & attribute);
const QString & defaultVal) const;
void setValue(const QString & cls, const QString & attribute,
const QString & value);
void deleteValue(const QString & cls, const QString & attribute);
void loadConfigFile( const QString & configFile = "" );
void loadConfigFile(const QString & configFile = "");
void saveConfigFile();
void setWorkingDir( const QString & _wd );
void setVSTDir( const QString & _vd );
void setArtworkDir( const QString & _ad );
void setLADSPADir( const QString & _fd );
void setVersion( const QString & _cv );
void setSTKDir( const QString & _fd );
void setDefaultSoundfont( const QString & _sf );
void setBackgroundArtwork( const QString & _ba );
void setGIGDir( const QString & gd );
void setSF2Dir( const QString & sfd );
void setWorkingDir(const QString & workingDir);
void setVSTDir(const QString & vstDir);
void setLADSPADir(const QString & ladspaDir);
void setSF2Dir(const QString & sf2Dir);
void setSF2File(const QString & sf2File);
void setSTKDir(const QString & stkDir);
void setGIGDir(const QString & gigDir);
void setThemeDir(const QString & themeDir);
void setBackgroundPicFile(const QString & backgroundPicFile);
// creates the working directory & subdirectories on disk.
// Creates the working directory & subdirectories on disk.
void createWorkingDir();
signals:
@@ -252,38 +273,45 @@ private:
static ConfigManager * s_instanceOfMe;
ConfigManager();
ConfigManager( const ConfigManager & _c );
~ConfigManager();
ConfigManager(const ConfigManager & _c);
~ConfigManager() override;
void upgrade_1_1_90();
void upgrade_1_1_91();
void upgrade_1_2_2();
void upgrade();
QString m_lmmsRcFile;
// List of all upgrade methods
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
QString m_workingDir;
QString m_dataDir;
QString m_artworkDir;
QString m_vstDir;
QString m_ladDir;
QString m_gigDir;
QString m_ladspaDir;
QString m_sf2Dir;
QString m_version;
#ifdef LMMS_HAVE_FLUIDSYNTH
QString m_sf2File;
#endif
#ifdef LMMS_HAVE_STK
QString m_stkDir;
#endif
#ifdef LMMS_HAVE_FLUIDSYNTH
QString m_defaultSoundfont;
#endif
QString m_backgroundArtwork;
QString m_gigDir;
QString m_themeDir;
QString m_backgroundPicFile;
QString m_lmmsRcFile;
QString m_version;
unsigned int m_configVersion;
QStringList m_recentlyOpenedProjects;
typedef QVector<QPair<QString, QString> > stringPairVector;
typedef QMap<QString, stringPairVector> settingsMap;
using stringPairVector = QVector<QPair<QString, QString>>;
using settingsMap = QMap<QString, stringPairVector>;
settingsMap m_settings;
friend class LmmsCore;
friend class Engine;
};
} ;
} // namespace lmms
#endif

144
include/ControlLayout.h Normal file
View File

@@ -0,0 +1,144 @@
/*
* ControlLayout.h - layout for controls
*
* Copyright (c) 2019-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.
*
*/
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CONTROLLAYOUT_H
#define CONTROLLAYOUT_H
#include <QLayout>
#include <QMultiMap>
#include <QStyle>
class QLayoutItem;
class QRect;
class QString;
class QLineEdit;
namespace lmms::gui
{
/**
Layout for controls (models)
Originally token from Qt's FlowLayout example. Modified.
Features a search bar, as well as looking up widgets with string keys
Keys have to be provided in the widgets' objectNames
*/
class ControlLayout : public QLayout
{
Q_OBJECT
public:
explicit ControlLayout(QWidget *parent,
int margin = -1, int hSpacing = -1, int vSpacing = -1);
~ControlLayout() override;
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QLayoutItem *itemByString(const QString& key) const;
QSize minimumSize() const override;
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&);
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QMap<QString, QLayoutItem *>::const_iterator pairAt(int index) const;
QMultiMap<QString, QLayoutItem *> m_itemMap;
int m_hSpace;
int m_vSpace;
// relevant dimension is width, as later, heightForWidth() will be called
// 400 looks good and is ~4 knobs in a row
constexpr const static int m_minWidth = 400;
QLineEdit* m_searchBar;
//! name of search bar, must be ASCII sorted before any alpha numerics
static constexpr const char* s_searchBarName = "!!searchBar!!";
};
} // namespace lmms::gui
#endif // CONTROLLAYOUT_H

View File

@@ -33,12 +33,20 @@
#include "JournallingObject.h"
#include "ValueBuffer.h"
class ControllerDialog;
namespace lmms
{
class Controller;
class ControllerConnection;
typedef QVector<Controller *> ControllerVector;
namespace gui
{
class ControllerDialog;
} // namespace gui
using ControllerVector = QVector<Controller*>;
class LMMS_EXPORT Controller : public Model, public JournallingObject
{
@@ -60,7 +68,7 @@ public:
Controller( ControllerTypes _type, Model * _parent,
const QString & _display_name );
virtual ~Controller();
~Controller() override;
virtual float currentValue( int _offset );
// The per-controller get-value-in-buffers function
@@ -101,9 +109,9 @@ public:
}
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
virtual void loadSettings( const QDomElement & _this );
virtual QString nodeName() const;
void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
void loadSettings( const QDomElement & _this ) override;
QString nodeName() const override;
static Controller * create( ControllerTypes _tt, Model * _parent );
static Controller * create( const QDomElement & _this,
@@ -132,7 +140,7 @@ public:
bool hasModel( const Model * m ) const;
public slots:
virtual ControllerDialog * createDialog( QWidget * _parent );
virtual gui::ControllerDialog * createDialog( QWidget * _parent );
virtual void setName( const QString & _new_name )
{
@@ -166,12 +174,15 @@ protected:
signals:
// The value changed while the mixer isn't running (i.e: MIDI CC)
// The value changed while the audio engine isn't running (i.e: MIDI CC)
void valueChanged();
friend class ControllerDialog;
friend class gui::ControllerDialog;
} ;
} // namespace lmms
#endif

View File

@@ -30,27 +30,34 @@
#ifndef CONTROLLER_CONNECTION_H
#define CONTROLLER_CONNECTION_H
#include <QtCore/QObject>
#include <QtCore/QVector>
#include <QObject>
#include <QVector>
#include "Controller.h"
#include "JournallingObject.h"
#include "ValueBuffer.h"
namespace lmms
{
class ControllerConnection;
typedef QVector<ControllerConnection *> ControllerConnectionVector;
namespace gui
{
class ControllerConnectionDialog;
}
using ControllerConnectionVector = QVector<ControllerConnection*>;
class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject
{
Q_OBJECT
public:
ControllerConnection( Controller * _controller );
ControllerConnection(Controller * _controller);
ControllerConnection( int _controllerId );
virtual ~ControllerConnection();
~ControllerConnection() override;
inline Controller * getController()
{
@@ -85,20 +92,19 @@ public:
static void finalizeConnections();
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
void loadSettings( const QDomElement & _this ) override;
static inline const QString classNodeName()
{
return "connection";
}
virtual QString nodeName() const
QString nodeName() const override
{
return classNodeName();
}
public slots:
void deleteConnection();
@@ -113,11 +119,14 @@ protected:
static ControllerConnectionVector s_connections;
signals:
// The value changed while the mixer isn't running (i.e: MIDI CC)
// The value changed while the audio engine isn't running (i.e: MIDI CC)
void valueChanged();
friend class ControllerConnectionDialog;
friend class gui::ControllerConnectionDialog;
};
} // namespace lmms
#endif

View File

@@ -38,7 +38,15 @@
class QLineEdit;
class QListView;
class QScrollArea;
namespace lmms
{
class AutoDetectMidiController;
namespace gui
{
class ComboBox;
class GroupBox;
class TabWidget;
@@ -47,14 +55,13 @@ class LedCheckBox;
class MidiPortMenu;
class ControllerConnectionDialog : public QDialog
{
Q_OBJECT
public:
ControllerConnectionDialog( QWidget * _parent,
const AutomatableModel * _target_model );
virtual ~ControllerConnectionDialog();
~ControllerConnectionDialog() override;
Controller * chosenController()
{
@@ -99,4 +106,9 @@ private:
AutoDetectMidiController * m_midiController;
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -30,8 +30,13 @@
#include "ModelView.h"
namespace lmms
{
class Controller;
namespace gui
{
class ControllerDialog : public QWidget, public ModelView
{
@@ -39,7 +44,7 @@ class ControllerDialog : public QWidget, public ModelView
public:
ControllerDialog( Controller * _controller, QWidget * _parent );
virtual ~ControllerDialog();
~ControllerDialog() override = default;
signals:
@@ -47,8 +52,13 @@ signals:
protected:
virtual void closeEvent( QCloseEvent * _ce );
void closeEvent( QCloseEvent * _ce ) override;
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -36,33 +36,41 @@ class QPushButton;
class QScrollArea;
class QVBoxLayout;
class ControllerView;
namespace lmms
{
class Controller;
namespace gui
{
class ControllerView;
class ControllerRackView : public QWidget, public SerializingObject
{
Q_OBJECT
public:
ControllerRackView();
virtual ~ControllerRackView();
~ControllerRackView() override = default;
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
inline virtual QString nodeName() const
inline QString nodeName() const override
{
return "ControllerRackView";
}
public slots:
void deleteController( ControllerView * _view );
void onControllerAdded( Controller * );
void onControllerRemoved( Controller * );
void deleteController( lmms::gui::ControllerView * _view );
void onControllerAdded( lmms::Controller * );
void onControllerRemoved( lmms::Controller * );
protected:
virtual void closeEvent( QCloseEvent * _ce );
void closeEvent( QCloseEvent * _ce ) override;
private slots:
void addController();
@@ -80,4 +88,8 @@ private:
int m_nextIndex;
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -36,6 +36,10 @@ class QLabel;
class QPushButton;
class QMdiSubWindow;
namespace lmms::gui
{
class LedCheckBox;
@@ -44,7 +48,7 @@ class ControllerView : public QFrame, public ModelView
Q_OBJECT
public:
ControllerView( Controller * _controller, QWidget * _parent );
virtual ~ControllerView();
~ControllerView() override;
inline Controller * getController()
{
@@ -64,13 +68,13 @@ public slots:
void renameController();
signals:
void deleteController( ControllerView * _view );
void deleteController( lmms::gui::ControllerView * _view );
protected:
virtual void contextMenuEvent( QContextMenuEvent * _me );
virtual void modelChanged();
virtual void mouseDoubleClickEvent( QMouseEvent * event );
void contextMenuEvent( QContextMenuEvent * _me ) override;
void modelChanged() override;
void mouseDoubleClickEvent( QMouseEvent * event ) override;
private:
@@ -81,4 +85,7 @@ private:
} ;
} // namespace lmms::gui
#endif

149
include/Controls.h Normal file
View File

@@ -0,0 +1,149 @@
/*
* Controls.h - labeled control widgets
*
* Copyright (c) 2019-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 CONTROLS_H
#define CONTROLS_H
// headers only required for covariance
#include "AutomatableModel.h"
#include "ComboBoxModel.h"
class QString;
class QWidget;
class QLabel;
namespace lmms
{
class AutomatableModel;
namespace gui
{
class AutomatableModelView;
class Knob;
class ComboBox;
class LedCheckBox;
/**
These classes provide
- a control with a text label
- a type safe way to set a model
(justification: setting the wrong typed model to a widget will cause
hard-to-find runtime errors)
*/
class Control
{
public:
virtual QWidget* topWidget() = 0;
virtual void setText(const QString& text) = 0;
virtual void setModel(AutomatableModel* model) = 0;
virtual AutomatableModel* model() = 0;
virtual AutomatableModelView* modelView() = 0;
virtual ~Control() = default;
};
class KnobControl : public Control
{
Knob* m_knob;
public:
void setText(const QString& text) override;
QWidget* topWidget() override;
void setModel(AutomatableModel* model) override;
FloatModel* model() override;
AutomatableModelView* modelView() override;
KnobControl(QWidget* parent = nullptr);
~KnobControl() override = default;
};
class ComboControl : public Control
{
QWidget* m_widget;
ComboBox* m_combo;
QLabel* m_label;
public:
void setText(const QString& text) override;
QWidget* topWidget() override { return m_widget; }
void setModel(AutomatableModel* model) override;
ComboBoxModel* model() override;
AutomatableModelView* modelView() override;
ComboControl(QWidget* parent = nullptr);
~ComboControl() override = default;
};
class LcdControl : public Control
{
class LcdSpinBox* m_lcd;
public:
void setText(const QString& text) override;
QWidget* topWidget() override;
void setModel(AutomatableModel* model) override;
IntModel* model() override;
AutomatableModelView* modelView() override;
LcdControl(int numDigits, QWidget* parent = nullptr);
~LcdControl() override = default;
};
class CheckControl : public Control
{
QWidget* m_widget;
LedCheckBox* m_checkBox;
QLabel* m_label;
public:
void setText(const QString& text) override;
QWidget* topWidget() override;
void setModel(AutomatableModel* model) override;
BoolModel* model() override;
AutomatableModelView* modelView() override;
CheckControl(QWidget* parent = nullptr);
~CheckControl() override = default;
};
} // namespace gui
} // namespace lmms
#endif // CONTROLS_H

37
include/CustomTextKnob.h Normal file
View File

@@ -0,0 +1,37 @@
/* Text customizable knob */
#ifndef CUSTOM_TEXT_KNOB_H
#define CUSTOM_TEXT_KNOB_H
#include "Knob.h"
namespace lmms::gui
{
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 = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
CustomTextKnob( QWidget * _parent = nullptr, 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:
QString displayValue() const override;
protected:
QString m_value_text;
} ;
} // namespace lmms::gui
#endif

View File

@@ -27,6 +27,7 @@
#ifndef DATA_FILE_H
#define DATA_FILE_H
#include <map>
#include <QDomDocument>
#include "lmms_export.h"
@@ -34,9 +35,18 @@
class QTextStream;
namespace lmms
{
class ProjectVersion;
class LMMS_EXPORT DataFile : public QDomDocument
{
MM_OPERATORS
using UpgradeMethod = void(DataFile::*)();
public:
enum Types
{
@@ -48,15 +58,16 @@ public:
ClipboardData,
JournalData,
EffectSettings,
MidiClip,
TypeCount
} ;
typedef Types Type;
using Type = Types;
DataFile( const QString& fileName );
DataFile( const QByteArray& data );
DataFile( Type type );
virtual ~DataFile();
virtual ~DataFile() = default;
///
/// \brief validate
@@ -67,7 +78,9 @@ public:
QString nameWithExtension( const QString& fn ) const;
void write( QTextStream& strm );
bool writeFile( const QString& fn );
bool writeFile(const QString& fn, bool withResources = false);
bool copyResources(const QString& resourcesDir); //!< Copies resources to the resourcesDir and changes the DataFile to use local paths to them
bool hasLocalPlugins(QDomElement parent = QDomElement(), bool firstCall = true) const;
QDomElement& content()
{
@@ -84,6 +97,8 @@ public:
return m_type;
}
unsigned int legacyFileVersion();
private:
static Type type( const QString& typeName );
static QString typeName( Type type );
@@ -107,8 +122,22 @@ 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();
void upgrade_automationNodes();
void upgrade_extendedNoteRange();
void upgrade_defaultTripleOscillatorHQ();
void upgrade_mixerRename();
void upgrade_bbTcoRename();
// 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;
// Map with DOM elements that access resources (for making bundles)
using ResourcesMap = std::map<QString, std::vector<QString>>;
static const ResourcesMap ELEMENTS_WITH_RESOURCES;
void upgrade();
@@ -122,17 +151,15 @@ private:
} ;
static typeDescStruct s_types[TypeCount];
QString m_fileName; //!< The origin file name or "" if this DataFile didn't originate from a file
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 );
} // namespace lmms
#endif

View File

@@ -32,6 +32,9 @@
#include "interpolation.h"
#include "MemoryManager.h"
namespace lmms
{
// brief usage
// Classes:
@@ -63,7 +66,7 @@ template<ch_cnt_t CHANNELS>
class CombFeedback
{
public:
typedef double frame[CHANNELS];
using frame = std::array<double, CHANNELS>;
CombFeedback( int maxDelay ) :
m_size( maxDelay ),
@@ -72,7 +75,7 @@ public:
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>(maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedback()
@@ -85,7 +88,7 @@ public:
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -134,7 +137,7 @@ private:
template<ch_cnt_t CHANNELS>
class CombFeedfwd
{
typedef double frame[CHANNELS];
using frame = std::array<double, CHANNELS>;
CombFeedfwd( int maxDelay ) :
m_size( maxDelay ),
@@ -143,7 +146,7 @@ class CombFeedfwd
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedfwd()
@@ -156,7 +159,7 @@ class CombFeedfwd
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -205,7 +208,7 @@ private:
template<ch_cnt_t CHANNELS>
class CombFeedbackDualtap
{
typedef double frame[CHANNELS];
using frame = std::array<double, CHANNELS>;
CombFeedbackDualtap( int maxDelay ) :
m_size( maxDelay ),
@@ -214,7 +217,7 @@ class CombFeedbackDualtap
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~CombFeedbackDualtap()
@@ -227,7 +230,7 @@ class CombFeedbackDualtap
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -286,7 +289,7 @@ template<ch_cnt_t CHANNELS>
class AllpassDelay
{
public:
typedef double frame[CHANNELS];
using frame = std::array<double, CHANNELS>;
AllpassDelay( int maxDelay ) :
m_size( maxDelay ),
@@ -295,7 +298,7 @@ public:
m_delay( 0 ),
m_fraction( 0.0 )
{
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
virtual ~AllpassDelay()
@@ -308,7 +311,7 @@ public:
if( maxDelay > m_size )
{
MM_FREE( m_buffer );
m_buffer = MM_ALLOC( frame, maxDelay );
m_buffer = MM_ALLOC<frame>( maxDelay );
memset( m_buffer, 0, sizeof( frame ) * maxDelay );
}
m_size = maxDelay;
@@ -355,9 +358,11 @@ private:
};
// convenience typedefs for stereo effects
typedef CombFeedback<2> StereoCombFeedback;
typedef CombFeedfwd<2> StereoCombFeedfwd;
typedef CombFeedbackDualtap<2> StereoCombFeedbackDualtap;
typedef AllpassDelay<2> StereoAllpassDelay;
using StereoCombFeedback = CombFeedback<2>;
using StereoCombFeedfwd = CombFeedfwd<2>;
using StereoCombFeedbackDualtap = CombFeedbackDualtap<2>;
using StereoAllpassDelay = AllpassDelay<2>;
} // namespace lmms
#endif

View File

@@ -0,0 +1,69 @@
/*
* 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>
namespace lmms
{
/**
* @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
}
} // namespace lmms
#endif // DEPRECATIONHELPER_H

View File

@@ -29,6 +29,9 @@
#include "InlineAutomation.h"
#include "MemoryManager.h"
namespace lmms
{
class DetuningHelper : public InlineAutomation
{
Q_OBJECT
@@ -39,21 +42,19 @@ public:
{
}
virtual ~DetuningHelper()
{
}
~DetuningHelper() override = default;
virtual float defaultValue() const
float defaultValue() const override
{
return 0;
}
virtual QString displayName() const
QString displayName() const override
{
return tr( "Note detuning" );
}
inline virtual QString nodeName() const
inline QString nodeName() const override
{
return "detuning";
}
@@ -61,4 +62,6 @@ public:
} ;
} // namespace lmms
#endif

View File

@@ -24,22 +24,25 @@
*/
#ifndef _DRUMSYNTH_H__
#define _DRUMSYNTH_H__
#ifndef DRUMSYNTH_H
#define DRUMSYNTH_H
#include <stdint.h>
#include "lmms_basics.h"
class QString;
namespace lmms
{
class DrumSynth {
public:
DrumSynth() {};
DrumSynth() = default;
int GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs);
private:
float LoudestEnv(void);
int LongestEnv(void);
float LoudestEnv();
int LongestEnv();
void UpdateEnv(int e, long t);
void GetEnv(int env, const char *sec, const char *key, QString ini);
@@ -51,4 +54,7 @@ class DrumSynth {
};
#endif
} // namespace lmms
#endif // DRUMSYNTH_H

View File

@@ -31,14 +31,14 @@
#include "lmms_basics.h"
namespace DspEffectLibrary
namespace lmms::DspEffectLibrary
{
template<typename T>
class MonoBase
{
public:
typedef class MonoBypass bypassType;
using bypassType = class MonoBypass;
static void process( sample_t * * _buf, const f_cnt_t _frames )
{
@@ -53,7 +53,7 @@ namespace DspEffectLibrary
class StereoBase
{
public:
typedef class StereoBypass bypassType;
using bypassType = class StereoBypass;
static void process( sample_t * * _buf, const f_cnt_t _frames )
{
@@ -164,7 +164,7 @@ namespace DspEffectLibrary
class Chain : public FX0::bypassType
{
public:
typedef typename FX0::sample_t sample_t;
using sample_t = typename FX0::sample_t;
Chain( const FX0& fx0, const FX1& fx1 = FX1() ) :
m_FX0( fx0 ),
m_FX1( fx1 )
@@ -329,7 +329,7 @@ namespace DspEffectLibrary
} ;
} ;
} // namespace lmms::DspEffectLibrary
#endif

View File

@@ -25,10 +25,20 @@
#ifndef DUMMY_EFFECT_H
#define DUMMY_EFFECT_H
#include <QDomElement>
#include "Effect.h"
#include "EffectControls.h"
#include "EffectControlDialog.h"
namespace lmms
{
namespace gui
{
class Knob;
class DummyEffectControlDialog : public EffectControlDialog
{
@@ -40,6 +50,7 @@ public:
} ;
} // namespace gui
class DummyEffectControls : public EffectControls
{
@@ -49,31 +60,29 @@ public:
{
}
virtual ~DummyEffectControls()
{
}
~DummyEffectControls() override = default;
virtual int controlCount()
int controlCount() override
{
return 0;
}
virtual void saveSettings( QDomDocument &, QDomElement & )
void saveSettings( QDomDocument &, QDomElement & ) override
{
}
virtual void loadSettings( const QDomElement & )
void loadSettings( const QDomElement & ) override
{
}
virtual QString nodeName() const
QString nodeName() const override
{
return "DummyControls";
}
virtual EffectControlDialog * createView()
gui::EffectControlDialog * createView() override
{
return new DummyEffectControlDialog( this );
return new gui::DummyEffectControlDialog( this );
}
} ;
@@ -84,23 +93,21 @@ class DummyEffect : public Effect
Q_OBJECT
public:
DummyEffect( Model * _parent, const QDomElement& originalPluginData ) :
Effect( NULL, _parent, NULL ),
Effect( nullptr, _parent, nullptr ),
m_controls( this ),
m_originalPluginData( originalPluginData )
{
setName();
}
virtual ~DummyEffect()
{
}
~DummyEffect() override = default;
virtual EffectControls * controls()
EffectControls * controls() override
{
return &m_controls;
}
bool processAudioBuffer( sampleFrame *, const fpp_t )
bool processAudioBuffer( sampleFrame *, const fpp_t ) override
{
return false;
}
@@ -140,4 +147,6 @@ private:
} ;
} // namespace lmms
#endif

View File

@@ -30,47 +30,51 @@
#include "InstrumentView.h"
#include "Engine.h"
#include <string.h>
#include <cstring>
#include "Mixer.h"
#include "AudioEngine.h"
namespace lmms
{
class DummyInstrument : public Instrument
{
public:
DummyInstrument( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, NULL )
Instrument( _instrument_track, nullptr )
{
}
virtual ~DummyInstrument()
{
}
~DummyInstrument() override = default;
virtual void playNote( NotePlayHandle *, sampleFrame * buffer )
void playNote( NotePlayHandle *, sampleFrame * buffer ) override
{
memset( buffer, 0, sizeof( sampleFrame ) *
Engine::mixer()->framesPerPeriod() );
Engine::audioEngine()->framesPerPeriod() );
}
virtual void saveSettings( QDomDocument &, QDomElement & )
void saveSettings( QDomDocument &, QDomElement & ) override
{
}
virtual void loadSettings( const QDomElement & )
void loadSettings( const QDomElement & ) override
{
}
virtual QString nodeName() const
QString nodeName() const override
{
return "dummyinstrument";
}
virtual PluginView * instantiateView( QWidget * _parent )
gui::PluginView * instantiateView( QWidget * _parent ) override
{
return new InstrumentViewFixedSize( this, _parent );
return new gui::InstrumentViewFixedSize( this, _parent );
}
} ;
} // namespace lmms
#endif

View File

@@ -30,39 +30,42 @@
#include "PluginView.h"
namespace lmms
{
class DummyPlugin : public Plugin
{
public:
DummyPlugin() :
Plugin( NULL, NULL )
Plugin( nullptr, nullptr )
{
}
virtual ~DummyPlugin()
~DummyPlugin() override = default;
void saveSettings( QDomDocument &, QDomElement & ) override
{
}
virtual void saveSettings( QDomDocument &, QDomElement & )
void loadSettings( const QDomElement & ) override
{
}
virtual void loadSettings( const QDomElement & )
{
}
virtual QString nodeName() const
QString nodeName() const override
{
return "DummyPlugin";
}
protected:
virtual PluginView * instantiateView( QWidget * _parent )
gui::PluginView * instantiateView( QWidget * _parent ) override
{
return new PluginView( this, _parent );
return new gui::PluginView( this, _parent );
}
} ;
} // namespace lmms
#endif

View File

@@ -30,6 +30,15 @@
class QAction;
namespace lmms::gui
{
static const int Quantizations[] = {
1, 2, 4, 8, 16, 32, 64,
3, 6, 12, 24, 48, 96, 192
};
class DropToolBar;
/// \brief Superclass for editors with a toolbar.
@@ -47,7 +56,7 @@ protected:
DropToolBar * addDropToolBar(Qt::ToolBarArea whereToAdd, QString const & windowTitle);
DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle);
virtual void closeEvent( QCloseEvent * _ce );
void closeEvent( QCloseEvent * _ce ) override;
protected slots:
virtual void play() {}
virtual void record() {}
@@ -58,6 +67,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:
@@ -67,7 +81,7 @@ protected:
/// \param record If set true, the editor's toolbar will contain record
/// buttons in addition to the play and stop buttons.
Editor(bool record = false, bool record_step = false);
virtual ~Editor();
~Editor() override = default;
DropToolBar* m_toolBar;
@@ -92,9 +106,11 @@ signals:
void dropped(QDropEvent* event);
protected:
void dragEnterEvent(QDragEnterEvent* event);
void dropEvent(QDropEvent* event);
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent* event) override;
};
} // namespace lmms::gui
#endif

View File

@@ -28,14 +28,24 @@
#include "Plugin.h"
#include "Engine.h"
#include "Mixer.h"
#include "AudioEngine.h"
#include "AutomatableModel.h"
#include "TempoSyncKnobModel.h"
#include "MemoryManager.h"
namespace lmms
{
class EffectChain;
class EffectControls;
namespace gui
{
class EffectView;
} // namespace gui
class LMMS_EXPORT Effect : public Plugin
{
@@ -45,12 +55,12 @@ public:
Effect( const Plugin::Descriptor * _desc,
Model * _parent,
const Descriptor::SubPluginFeatures::Key * _key );
virtual ~Effect();
~Effect() override;
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
inline virtual QString nodeName() const
inline QString nodeName() const override
{
return "effect";
}
@@ -103,8 +113,8 @@ public:
inline f_cnt_t timeout() const
{
const float samples = Engine::mixer()->processingSampleRate() * m_autoQuitModel.value() / 1000.0f;
return 1 + ( static_cast<int>( samples ) / Engine::mixer()->framesPerPeriod() );
const float samples = Engine::audioEngine()->processingSampleRate() * m_autoQuitModel.value() / 1000.0f;
return 1 + ( static_cast<int>( samples ) / Engine::audioEngine()->framesPerPeriod() );
}
inline float wetLevel() const
@@ -170,7 +180,7 @@ protected:
*/
void checkGate( double _out_sum );
virtual PluginView * instantiateView( QWidget * );
gui::PluginView* instantiateView( QWidget * ) override;
// some effects might not be capable of higher sample-rates so they can
// sample it down before processing and back after processing
@@ -179,9 +189,9 @@ protected:
sample_rate_t _dst_sr )
{
resample( 0, _src_buf,
Engine::mixer()->processingSampleRate(),
Engine::audioEngine()->processingSampleRate(),
_dst_buf, _dst_sr,
Engine::mixer()->framesPerPeriod() );
Engine::audioEngine()->framesPerPeriod() );
}
inline void sampleBack( const sampleFrame * _src_buf,
@@ -189,9 +199,9 @@ protected:
sample_rate_t _src_sr )
{
resample( 1, _src_buf, _src_sr, _dst_buf,
Engine::mixer()->processingSampleRate(),
Engine::mixer()->framesPerPeriod() * _src_sr /
Engine::mixer()->processingSampleRate() );
Engine::audioEngine()->processingSampleRate(),
Engine::audioEngine()->framesPerPeriod() * _src_sr /
Engine::audioEngine()->processingSampleRate() );
}
void reinitSRC();
@@ -221,14 +231,14 @@ private:
SRC_STATE * m_srcState[2];
friend class EffectView;
friend class gui::EffectView;
friend class EffectChain;
} ;
using EffectKey = Effect::Descriptor::SubPluginFeatures::Key;
using EffectKeyList = Effect::Descriptor::SubPluginFeatures::KeyList;
typedef Effect::Descriptor::SubPluginFeatures::Key EffectKey;
typedef Effect::Descriptor::SubPluginFeatures::KeyList EffectKeyList;
} // namespace lmms
#endif

View File

@@ -30,20 +30,30 @@
#include "SerializingObject.h"
#include "AutomatableModel.h"
namespace lmms
{
class Effect;
namespace gui
{
class EffectRackView;
} // namespace gui
class LMMS_EXPORT EffectChain : public Model, public SerializingObject
{
Q_OBJECT
public:
EffectChain( Model * _parent );
virtual ~EffectChain();
~EffectChain() override;
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
inline virtual QString nodeName() const
inline QString nodeName() const override
{
return "fxchain";
}
@@ -59,13 +69,13 @@ public:
private:
typedef QVector<Effect *> EffectList;
using EffectList = QVector<Effect*>;
EffectList m_effects;
BoolModel m_enabledModel;
friend class EffectRackView;
friend class gui::EffectRackView;
signals:
@@ -73,5 +83,7 @@ signals:
} ;
} // namespace lmms
#endif

View File

@@ -30,15 +30,21 @@
#include "ModelView.h"
namespace lmms
{
class EffectControls;
namespace gui
{
class LMMS_EXPORT EffectControlDialog : public QWidget, public ModelView
{
Q_OBJECT
public:
EffectControlDialog( EffectControls * _controls );
virtual ~EffectControlDialog();
~EffectControlDialog() override = default;
virtual bool isResizable() const {return false;}
@@ -48,10 +54,14 @@ signals:
protected:
virtual void closeEvent( QCloseEvent * _ce );
void closeEvent( QCloseEvent * _ce ) override;
EffectControls * m_effectControls;
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -29,8 +29,16 @@
#include "JournallingObject.h"
#include "Effect.h"
namespace lmms
{
namespace gui
{
class EffectControlDialog;
} // namespace gui
class EffectControls : public JournallingObject, public Model
{
@@ -43,12 +51,10 @@ public:
{
}
virtual ~EffectControls()
{
}
~EffectControls() override = default;
virtual int controlCount() = 0;
virtual EffectControlDialog * createView() = 0;
virtual gui::EffectControlDialog * createView() = 0;
void setViewVisible( bool _visible )
@@ -73,4 +79,7 @@ private:
} ;
} // namespace lmms
#endif

View File

@@ -35,6 +35,9 @@
class QScrollArea;
class QVBoxLayout;
namespace lmms::gui
{
class EffectView;
class GroupBox;
@@ -43,15 +46,16 @@ class EffectRackView : public QWidget, public ModelView
{
Q_OBJECT
public:
EffectRackView( EffectChain* model, QWidget* parent = NULL );
virtual ~EffectRackView();
EffectRackView( EffectChain* model, QWidget* parent = nullptr );
~EffectRackView() override;
static constexpr int DEFAULT_WIDTH = 245;
public slots:
void clearViews();
void moveUp( EffectView* view );
void moveDown( EffectView* view );
void deletePlugin( EffectView* view );
void moveUp( lmms::gui::EffectView* view );
void moveDown( lmms::gui::EffectView* view );
void deletePlugin( lmms::gui::EffectView* view );
private slots:
@@ -60,7 +64,7 @@ private slots:
private:
virtual void modelChanged();
void modelChanged() override;
inline EffectChain* fxChain()
{
@@ -82,4 +86,6 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -29,19 +29,21 @@
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include "EffectChain.h"
#include "Effect.h"
namespace Ui { class EffectSelectDialog; }
namespace lmms::gui
{
class EffectSelectDialog : public QDialog
{
Q_OBJECT
public:
EffectSelectDialog( QWidget * _parent );
virtual ~EffectSelectDialog();
~EffectSelectDialog() override;
Effect * instantiateSelectedPlugin( EffectChain * _parent );
@@ -66,5 +68,7 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -35,6 +35,9 @@ class QLabel;
class QPushButton;
class QMdiSubWindow;
namespace lmms::gui
{
class EffectControlDialog;
class Knob;
class LedCheckBox;
@@ -46,7 +49,7 @@ class EffectView : public PluginView
Q_OBJECT
public:
EffectView( Effect * _model, QWidget * _parent );
virtual ~EffectView();
~EffectView() override;
inline Effect * effect()
{
@@ -57,6 +60,7 @@ public:
return castModel<Effect>();
}
static constexpr int DEFAULT_WIDTH = 215;
public slots:
void editControls();
@@ -67,15 +71,15 @@ public slots:
signals:
void moveUp( EffectView * _plugin );
void moveDown( EffectView * _plugin );
void deletePlugin( EffectView * _plugin );
void moveUp( lmms::gui::EffectView * _plugin );
void moveDown( lmms::gui::EffectView * _plugin );
void deletePlugin( lmms::gui::EffectView * _plugin );
protected:
virtual void contextMenuEvent( QContextMenuEvent * _me );
virtual void paintEvent( QPaintEvent * _pe );
virtual void modelChanged();
void contextMenuEvent( QContextMenuEvent * _me ) override;
void paintEvent( QPaintEvent * _pe ) override;
void modelChanged() override;
private:
@@ -89,4 +93,7 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -26,35 +26,31 @@
#ifndef ENGINE_H
#define ENGINE_H
#include <QtCore/QString>
#include <QtCore/QObject>
#include <QString>
#include <QObject>
#include "lmmsconfig.h"
#include "lmms_export.h"
#include "lmms_basics.h"
class BBTrackContainer;
class DummyTrackContainer;
class FxMixer;
class ProjectJournal;
namespace lmms
{
class AudioEngine;
class Mixer;
class PatternStore;
class ProjectJournal;
class Song;
class Ladspa2LMMS;
namespace gui
{
class GuiApplication;
}
// Note: This class is called 'LmmsCore' instead of 'Engine' because of naming
// conflicts caused by ZynAddSubFX. See https://github.com/LMMS/lmms/issues/2269
// and https://github.com/LMMS/lmms/pull/2118 for more details.
//
// The workaround was to rename Lmms' Engine so that it has a different symbol
// name in the object files, but typedef it back to 'Engine' and keep it inside
// of Engine.h so that the rest of the codebase can be oblivious to this issue
// (and it could be fixed without changing every single file).
class LmmsCore;
typedef LmmsCore Engine;
class LMMS_EXPORT LmmsCore : public QObject
class LMMS_EXPORT Engine : public QObject
{
Q_OBJECT
public:
@@ -62,14 +58,14 @@ public:
static void destroy();
// core
static Mixer *mixer()
static AudioEngine *audioEngine()
{
return s_mixer;
return s_audioEngine;
}
static FxMixer * fxMixer()
static Mixer * mixer()
{
return s_fxMixer;
return s_mixer;
}
static Song * getSong()
@@ -77,9 +73,9 @@ public:
return s_song;
}
static BBTrackContainer * getBBTrackContainer()
static PatternStore * patternStore()
{
return s_bbTrackContainer;
return s_patternStore;
}
static ProjectJournal * projectJournal()
@@ -87,16 +83,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;
@@ -106,11 +106,11 @@ public:
static void updateFramesPerTick();
static inline LmmsCore * inst()
static inline Engine * inst()
{
if( s_instanceOfMe == NULL )
if( s_instanceOfMe == nullptr )
{
s_instanceOfMe = new LmmsCore();
s_instanceOfMe = new Engine();
}
return s_instanceOfMe;
}
@@ -126,32 +126,36 @@ private:
// small helper function which sets the pointer to NULL before actually deleting
// the object it refers to
template<class T>
static inline void deleteHelper( T * * ptr )
static inline void deleteHelper(T** ptr)
{
T * tmp = *ptr;
*ptr = NULL;
T* tmp = *ptr;
*ptr = nullptr;
delete tmp;
}
static float s_framesPerTick;
// core
static Mixer *s_mixer;
static FxMixer * s_fxMixer;
static AudioEngine *s_audioEngine;
static Mixer * s_mixer;
static Song * s_song;
static BBTrackContainer * s_bbTrackContainer;
static PatternStore * s_patternStore;
static ProjectJournal * s_projectJournal;
static DummyTrackContainer * s_dummyTC;
static Ladspa2LMMS * s_ladspaManager;
#ifdef LMMS_HAVE_LV2
static class Lv2Manager* s_lv2Manager;
#endif
static Ladspa2LMMS* s_ladspaManager;
static void* s_dndPluginKey;
// even though most methods are static, an instance is needed for Qt slots/signals
static LmmsCore * s_instanceOfMe;
static Engine* s_instanceOfMe;
friend class GuiApplication;
friend class gui::GuiApplication;
};
} // namespace lmms
#endif

View File

@@ -25,7 +25,7 @@
#ifndef ENVELOPE_AND_LFO_PARAMETERS_H
#define ENVELOPE_AND_LFO_PARAMETERS_H
#include <QtCore/QVector>
#include <QVector>
#include "JournallingObject.h"
#include "AutomatableModel.h"
@@ -33,6 +33,15 @@
#include "TempoSyncKnobModel.h"
#include "lmms_basics.h"
namespace lmms
{
namespace gui
{
class EnvelopeAndLfoView;
}
class LMMS_EXPORT EnvelopeAndLfoParameters : public Model, public JournallingObject
{
@@ -41,13 +50,9 @@ public:
class LfoInstances
{
public:
LfoInstances()
{
}
LfoInstances() = default;
~LfoInstances()
{
}
~LfoInstances() = default;
inline bool isEmpty() const
{
@@ -62,14 +67,14 @@ public:
private:
QMutex m_lfoListMutex;
typedef QList<EnvelopeAndLfoParameters *> LfoList;
using LfoList = QList<EnvelopeAndLfoParameters*>;
LfoList m_lfos;
} ;
EnvelopeAndLfoParameters( float _value_for_zero_amount,
Model * _parent );
virtual ~EnvelopeAndLfoParameters();
~EnvelopeAndLfoParameters() override;
static inline float expKnobVal( float _val )
{
@@ -91,9 +96,9 @@ public:
}
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
virtual QString nodeName() const
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
QString nodeName() const override
{
return "el";
}
@@ -179,8 +184,10 @@ private:
void updateLfoShapeData();
friend class EnvelopeAndLfoView;
friend class gui::EnvelopeAndLfoView;
} ;
} // namespace lmms
#endif

View File

@@ -33,8 +33,14 @@
class QPaintEvent;
class QPixmap;
namespace lmms
{
class EnvelopeAndLfoParameters;
namespace gui
{
class automatableButtonGroup;
class Knob;
class LedCheckBox;
@@ -48,16 +54,16 @@ class EnvelopeAndLfoView : public QWidget, public ModelView
Q_OBJECT
public:
EnvelopeAndLfoView( QWidget * _parent );
virtual ~EnvelopeAndLfoView();
~EnvelopeAndLfoView() override;
protected:
virtual void modelChanged();
void modelChanged() override;
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
virtual void mousePressEvent( QMouseEvent * _me );
virtual void paintEvent( QPaintEvent * _pe );
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void dropEvent( QDropEvent * _de ) override;
void mousePressEvent( QMouseEvent * _me ) override;
void paintEvent( QPaintEvent * _pe ) override;
protected slots:
@@ -94,4 +100,8 @@ private:
float m_randomGraph;
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -26,33 +26,37 @@
#ifndef EXPORT_FILTER_H
#define EXPORT_FILTER_H
#include <QtCore/QFile>
#include <QFile>
#include "TrackContainer.h"
#include "Plugin.h"
namespace lmms
{
class LMMS_EXPORT ExportFilter : public Plugin
{
public:
ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, NULL ) {}
virtual ~ExportFilter() {}
ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, nullptr ) {}
~ExportFilter() override = default;
virtual bool tryExport(const TrackContainer::TrackList &tracks,
const TrackContainer::TrackList &tracksBB,
const TrackContainer::TrackList &patternTracks,
int tempo, int masterPitch, const QString &filename ) = 0;
protected:
virtual void saveSettings( QDomDocument &, QDomElement & )
void saveSettings( QDomDocument &, QDomElement & ) override
{
}
virtual void loadSettings( const QDomElement & )
void loadSettings( const QDomElement & ) override
{
}
virtual QString nodeName() const
QString nodeName() const override
{
return "import_filter";
}
@@ -63,4 +67,6 @@ private:
} ;
} // namespace lmms
#endif

View File

@@ -34,6 +34,10 @@
#include "ProjectRenderer.h"
#include "RenderManager.h"
namespace lmms::gui
{
class ExportProjectDialog : public QDialog, public Ui::ExportProjectDialog
{
Q_OBJECT
@@ -41,14 +45,14 @@ public:
ExportProjectDialog( const QString & _file_name, QWidget * _parent, bool multi_export );
protected:
virtual void reject( void );
virtual void closeEvent( QCloseEvent * _ce );
void reject() override;
void closeEvent( QCloseEvent * _ce ) override;
private slots:
void startBtnClicked( void );
void startBtnClicked();
void updateTitleBar( int );
void accept();
void accept() override;
void startExport();
void onFileFormatChanged(int);
@@ -63,4 +67,8 @@ private:
std::unique_ptr<RenderManager> m_renderManager;
} ;
} // namespace lmms::gui
#endif

View File

@@ -26,9 +26,13 @@
#ifndef FADE_BUTTON_H
#define FADE_BUTTON_H
#include <QtCore/QTime>
#include <QAbstractButton>
#include <QColor>
#include <QElapsedTimer>
namespace lmms::gui
{
class FadeButton : public QAbstractButton
@@ -40,23 +44,23 @@ public:
const QColor & _hold_color,
QWidget * _parent );
virtual ~FadeButton();
~FadeButton() override = default;
void setActiveColor( const QColor & activated_color );
public slots:
void activate();
void activateOnce();
void noteEnd();
protected:
virtual void customEvent( QEvent * );
virtual void paintEvent( QPaintEvent * _pe );
void paintEvent( QPaintEvent * _pe ) override;
private:
QTime m_stateTimer;
QTime m_releaseTimer;
QElapsedTimer m_stateTimer;
QElapsedTimer m_releaseTimer;
// the default color of the widget
QColor m_normalColor;
@@ -66,10 +70,11 @@ private:
QColor m_holdColor;
int activeNotes;
void signalUpdate();
QColor fadeToColor(QColor, QColor, QTime, float);
QColor fadeToColor(QColor, QColor, QElapsedTimer, float);
} ;
} // namespace lmms::gui
#endif

View File

@@ -1,5 +1,5 @@
/*
* Fader.h - fader-widget used in FX-mixer - partly taken from Hydrogen
* Fader.h - fader-widget used in Mixer - partly taken from Hydrogen
*
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -48,12 +48,16 @@
#ifndef FADER_H
#define FADER_H
#include <QtCore/QTime>
#include <QWidget>
#include <QElapsedTimer>
#include <QPixmap>
#include <QWidget>
#include "AutomatableModelView.h"
namespace lmms::gui
{
class TextFloat;
@@ -68,7 +72,7 @@ public:
Fader( FloatModel * _model, const QString & _name, QWidget * _parent );
Fader( FloatModel * _model, const QString & _name, QWidget * _parent, QPixmap * back, QPixmap * leds, QPixmap * knob );
virtual ~Fader() = default;
~Fader() override = default;
void init(FloatModel * model, QString const & name);
@@ -98,7 +102,7 @@ public:
void setDisplayConversion( bool b )
{
m_displayConversion = b;
m_conversionFactor = b ? 100.0 : 1.0;
}
inline void setHintText( const QString & _txt_before,
@@ -109,13 +113,13 @@ public:
}
private:
virtual void contextMenuEvent( QContextMenuEvent * _me );
virtual void mousePressEvent( QMouseEvent *ev );
virtual void mouseDoubleClickEvent( QMouseEvent* mouseEvent );
virtual void mouseMoveEvent( QMouseEvent *ev );
virtual void mouseReleaseEvent( QMouseEvent * _me );
virtual void wheelEvent( QWheelEvent *ev );
virtual void paintEvent( QPaintEvent *ev );
void contextMenuEvent( QContextMenuEvent * _me ) override;
void mousePressEvent( QMouseEvent *ev ) override;
void mouseDoubleClickEvent( QMouseEvent* mouseEvent ) override;
void mouseMoveEvent( QMouseEvent *ev ) override;
void mouseReleaseEvent( QMouseEvent * _me ) override;
void wheelEvent( QWheelEvent *ev ) override;
void paintEvent( QPaintEvent *ev ) override;
inline bool clips(float const & value) const { return value >= 1.0f; }
@@ -130,7 +134,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 +148,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 +158,7 @@ private:
QPixmap * m_back;
QPixmap * m_leds;
QPixmap * m_knob;
bool m_displayConversion;
bool m_levelsDisplayedInDBFS;
int m_moveStartPoint;
@@ -169,4 +172,7 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -1,5 +1,5 @@
/*
* fifo_buffer.h - FIFO fixed-size buffer
* FifoBuffer.h - FIFO fixed-size buffer
*
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
@@ -25,70 +25,73 @@
#ifndef FIFO_BUFFER_H
#define FIFO_BUFFER_H
#include <QtCore/QSemaphore>
#include <QSemaphore>
namespace lmms
{
template<typename T>
class fifoBuffer
class FifoBuffer
{
public:
fifoBuffer( int _size ) :
m_reader_sem( _size ),
m_writer_sem( _size ),
m_reader_index( 0 ),
m_writer_index( 0 ),
m_size( _size )
FifoBuffer(int size) :
m_readSem(size),
m_writeSem(size),
m_readIndex(0),
m_writeIndex(0),
m_size(size)
{
m_buffer = new T[_size];
m_reader_sem.acquire( _size );
m_buffer = new T[size];
m_readSem.acquire(size);
}
~fifoBuffer()
~FifoBuffer()
{
delete[] m_buffer;
m_reader_sem.release( m_size );
m_readSem.release(m_size);
}
void write( T _element )
void write(T element)
{
m_writer_sem.acquire();
m_buffer[m_writer_index++] = _element;
m_writer_index %= m_size;
m_reader_sem.release();
m_writeSem.acquire();
m_buffer[m_writeIndex++] = element;
m_writeIndex %= m_size;
m_readSem.release();
}
T read()
{
m_reader_sem.acquire();
T element = m_buffer[m_reader_index++];
m_reader_index %= m_size;
m_writer_sem.release();
return( element );
m_readSem.acquire();
T element = m_buffer[m_readIndex++];
m_readIndex %= m_size;
m_writeSem.release();
return element;
}
void waitUntilRead()
{
m_writer_sem.acquire( m_size );
m_writer_sem.release( m_size );
m_writeSem.acquire(m_size);
m_writeSem.release(m_size);
}
bool available()
{
return( m_reader_sem.available() );
return m_readSem.available();
}
private:
QSemaphore m_reader_sem;
QSemaphore m_writer_sem;
int m_reader_index;
int m_writer_index;
QSemaphore m_readSem;
QSemaphore m_writeSem;
int m_readIndex;
int m_writeIndex;
int m_size;
T * m_buffer;
} ;
} // namespace lmms
#endif

View File

@@ -26,8 +26,12 @@
#ifndef FILE_BROWSER_H
#define FILE_BROWSER_H
#include <QtCore/QDir>
#include <QtCore/QMutex>
#include <QCheckBox>
#include <QDir>
#include <QMutex>
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
#include <QRecursiveMutex>
#endif
#include <QTreeWidget>
@@ -36,32 +40,48 @@
class QLineEdit;
class FileItem;
namespace lmms
{
class InstrumentTrack;
class FileBrowserTreeWidget;
class PlayHandle;
class TrackContainer;
namespace gui
{
class FileItem;
class FileBrowserTreeWidget;
class FileBrowser : public SideBarWidget
{
Q_OBJECT
public:
/**
Create a file browser side bar widget
@param directories '*'-separated list of directories to search for.
If a directory of factory files should be in the list it
must be the last one (for the factory files delimiter to work)
@param filter Filter as used in QDir::match
@param recurse *to be documented*
*/
FileBrowser( const QString & directories, const QString & filter,
const QString & title, const QPixmap & pm,
QWidget * parent, bool dirs_as_items = false, bool recurse = false );
virtual ~FileBrowser() = default;
QWidget * parent, bool dirs_as_items = false, bool recurse = false,
const QString& userDir = "",
const QString& factoryDir = "");
~FileBrowser() override = default;
private slots:
void reloadTree( void );
void expandItems( QTreeWidgetItem * item=NULL, QList<QString> expandedDirs = QList<QString>() );
void reloadTree();
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:
virtual void keyPressEvent( QKeyEvent * ke );
void keyPressEvent( QKeyEvent * ke ) override;
void addItems( const QString & path );
@@ -69,12 +89,17 @@ private:
QLineEdit * m_filterEdit;
QString m_directories;
QString m_filter;
QString m_directories; //!< Directories to search, split with '*'
QString m_filter; //!< Filter as used in QDir::match()
bool m_dirsAsItems;
bool m_recurse;
void addContentCheckBox();
QCheckBox* m_showUserContent = nullptr;
QCheckBox* m_showFactoryContent = nullptr;
QString m_userDir;
QString m_factoryDir;
} ;
@@ -85,7 +110,7 @@ class FileBrowserTreeWidget : public QTreeWidget
Q_OBJECT
public:
FileBrowserTreeWidget( QWidget * parent );
virtual ~FileBrowserTreeWidget() = default;
~FileBrowserTreeWidget() override = default;
//! This method returns a QList with paths (QString's) of all directories
//! that are expanded in the tree.
@@ -93,32 +118,48 @@ public:
protected:
virtual void contextMenuEvent( QContextMenuEvent * e );
virtual void mousePressEvent( QMouseEvent * me );
virtual void mouseMoveEvent( QMouseEvent * me );
virtual void mouseReleaseEvent( QMouseEvent * me );
void contextMenuEvent( QContextMenuEvent * e ) override;
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;
#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0))
QRecursiveMutex m_pphMutex;
#else
QMutex m_pphMutex;
#endif
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( lmms::gui::FileItem* item, bool songEditor );
bool openInNewSampleTrack( lmms::gui::FileItem* item );
void sendToActiveInstrumentTrack( lmms::gui::FileItem* item );
void updateDirectory( QTreeWidgetItem * item );
void openContainingFolder( lmms::gui::FileItem* item );
} ;
@@ -131,7 +172,7 @@ public:
Directory( const QString & filename, const QString & path,
const QString & filter );
void update( void );
void update();
inline QString fullName( QString path = QString() )
{
@@ -154,7 +195,7 @@ public:
private:
void initPixmaps( void );
void initPixmaps();
bool addItems( const QString & path );
@@ -163,7 +204,14 @@ private:
static QPixmap * s_folderOpenedPixmap;
static QPixmap * s_folderLockedPixmap;
//! Directories that lead here
//! Initially, this is just set to the current path of a directory
//! If, however, you have e.g. 'TripleOscillator/xyz' in two of the
//! file browser's search directories 'a' and 'b', this will have two
//! entries 'a/TripleOscillator' and 'b/TripleOscillator'
//! and 'xyz' in the tree widget
QStringList m_directories;
//! Filter as used in QDir::match()
QString m_filter;
int m_dirCount;
@@ -208,23 +256,28 @@ public:
return QFileInfo(m_path, text(0)).absoluteFilePath();
}
inline FileTypes type( void ) const
inline FileTypes type() const
{
return( m_type );
}
inline FileHandling handling( void ) const
inline FileHandling handling() const
{
return( m_handling );
}
QString extension( void );
inline bool isTrack() const
{
return m_handling == LoadAsPreset || m_handling == LoadByPlugin;
}
QString extension();
static QString extension( const QString & file );
private:
void initPixmaps( void );
void determineFileType( void );
void initPixmaps();
void determineFileType();
static QPixmap * s_projectFilePixmap;
static QPixmap * s_presetFilePixmap;
@@ -241,4 +294,8 @@ private:
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -30,6 +30,10 @@
#include "lmms_export.h"
namespace lmms::gui
{
class LMMS_EXPORT FileDialog : public QFileDialog
{
Q_OBJECT
@@ -46,9 +50,11 @@ 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();
};
#endif // FILEDIALOG_HPP
} // namespace lmms::gui
#endif // FILEDIALOG_H

View File

@@ -1,211 +0,0 @@
/*
* FxMixer.h - effect-mixer for LMMS
*
* Copyright (c) 2008-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 FX_MIXER_H
#define FX_MIXER_H
#include "Model.h"
#include "EffectChain.h"
#include "JournallingObject.h"
#include "ThreadableJob.h"
#include <atomic>
class FxRoute;
typedef QVector<FxRoute *> FxRouteVector;
class FxChannel : public ThreadableJob
{
public:
FxChannel( int idx, Model * _parent );
virtual ~FxChannel();
EffectChain m_fxChain;
// set to true when input fed from mixToChannel or child channel
bool m_hasInput;
// set to true if any effect in the channel is enabled and running
bool m_stillRunning;
float m_peakLeft;
float m_peakRight;
sampleFrame * m_buffer;
bool m_muteBeforeSolo;
BoolModel m_muteModel;
BoolModel m_soloModel;
FloatModel m_volumeModel;
QString m_name;
QMutex m_lock;
int m_channelIndex; // what channel index are we
bool m_queued; // are we queued up for rendering yet?
bool m_muted; // are we muted? updated per period so we don't have to call m_muteModel.value() twice
// pointers to other channels that this one sends to
FxRouteVector m_sends;
// pointers to other channels that send to this one
FxRouteVector m_receives;
virtual bool requiresProcessing() const { return true; }
void unmuteForSolo();
std::atomic_int m_dependenciesMet;
void incrementDeps();
void processed();
private:
virtual void doProcessing();
};
class FxRoute : public QObject
{
Q_OBJECT
public:
FxRoute( FxChannel * from, FxChannel * to, float amount );
virtual ~FxRoute();
fx_ch_t senderIndex() const
{
return m_from->m_channelIndex;
}
fx_ch_t receiverIndex() const
{
return m_to->m_channelIndex;
}
FloatModel * amount()
{
return &m_amount;
}
FxChannel * sender() const
{
return m_from;
}
FxChannel * receiver() const
{
return m_to;
}
void updateName();
private:
FxChannel * m_from;
FxChannel * m_to;
FloatModel m_amount;
};
class LMMS_EXPORT FxMixer : public Model, public JournallingObject
{
Q_OBJECT
public:
FxMixer();
virtual ~FxMixer();
void mixToChannel( const sampleFrame * _buf, fx_ch_t _ch );
void prepareMasterMix();
void masterMix( sampleFrame * _buf );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
virtual QString nodeName() const
{
return "fxmixer";
}
FxChannel * effectChannel( int _ch )
{
return m_fxChannels[_ch];
}
// make the output of channel fromChannel go to the input of channel toChannel
// it is safe to call even if the send already exists
FxRoute * createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel,
float amount = 1.0f);
FxRoute * createRoute( FxChannel * from, FxChannel * to, float amount );
// delete the connection made by createChannelSend
void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel);
void deleteChannelSend( FxRoute * route );
// determine if adding a send from sendFrom to
// sendTo would result in an infinite mixer loop.
bool isInfiniteLoop(fx_ch_t fromChannel, fx_ch_t toChannel);
bool checkInfiniteLoop( FxChannel * from, FxChannel * to );
// return the FloatModel of fromChannel sending its output to the input of
// toChannel. NULL if there is no send.
FloatModel * channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel);
// add a new channel to the Fx Mixer.
// returns the index of the channel that was just added
int createChannel();
// delete a channel from the FX mixer.
void deleteChannel(int index);
// delete all the mixer channels except master and remove all effects
void clear();
// re-arrange channels
void moveChannelLeft(int index);
void moveChannelRight(int index);
// reset a channel's name, fx, sends, etc
void clearChannel(fx_ch_t channelIndex);
// rename channels when moving etc. if they still have their original name
void validateChannelName( int index, int oldIndex );
void toggledSolo();
void activateSolo();
void deactivateSolo();
inline fx_ch_t numChannels() const
{
return m_fxChannels.size();
}
FxRouteVector m_fxRoutes;
private:
// the fx channels in the mixer. index 0 is always master.
QVector<FxChannel *> m_fxChannels;
// make sure we have at least num channels
void allocateChannelsTo(int num);
int m_lastSoloed;
} ;
#endif

View File

@@ -35,8 +35,15 @@
#include "ModelView.h"
#include "lmms_basics.h"
namespace lmms
{
class graphModel;
namespace gui
{
class LMMS_EXPORT Graph : public QWidget, public ModelView
{
@@ -60,7 +67,7 @@ public:
int _width = 132,
int _height = 104
);
virtual ~Graph() = default;
~Graph() override = default;
void setForeground( const QPixmap & _pixmap );
@@ -87,19 +94,19 @@ public:
signals:
void drawn();
protected:
virtual void paintEvent( QPaintEvent * _pe );
virtual void dropEvent( QDropEvent * _de );
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void mousePressEvent( QMouseEvent * _me );
virtual void mouseMoveEvent( QMouseEvent * _me );
virtual void mouseReleaseEvent( QMouseEvent * _me );
void paintEvent( QPaintEvent * _pe ) override;
void dropEvent( QDropEvent * _de ) override;
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void mousePressEvent( QMouseEvent * _me ) override;
void mouseMoveEvent( QMouseEvent * _me ) override;
void mouseReleaseEvent( QMouseEvent * _me ) override;
protected slots:
void updateGraph( int _startPos, int _endPos );
void updateGraph();
private:
virtual void modelChanged();
void modelChanged() override;
void changeSampleAt( int _x, int _y );
void drawLineAt( int _x, int _y, int _lastx );
@@ -116,6 +123,9 @@ private:
} ;
} // namespace gui
/**
@brief 2 dimensional function plot
@@ -137,11 +147,11 @@ public:
graphModel( float _min,
float _max,
int _size,
:: Model * _parent,
Model * _parent,
bool _default_constructed = false,
float _step = 0.0 );
virtual ~graphModel() = default;
~graphModel() override = default;
// TODO: saveSettings, loadSettings?
@@ -187,7 +197,7 @@ public slots:
void setWaveToSaw();
void setWaveToSquare();
void setWaveToNoise();
QString setWaveToUser( );
QString setWaveToUser();
void smooth();
void smoothNonCyclic();
@@ -211,8 +221,11 @@ private:
float m_maxValue;
float m_step;
friend class Graph;
friend class gui::Graph;
};
} // namespace lmms
#endif

View File

@@ -34,15 +34,17 @@
class QPixmap;
namespace lmms::gui
{
class GroupBox : public QWidget, public BoolModelView
{
Q_OBJECT
public:
GroupBox( const QString & _caption, QWidget * _parent = NULL );
virtual ~GroupBox();
GroupBox( const QString & _caption, QWidget * _parent = nullptr );
~GroupBox() override;
virtual void modelChanged();
void modelChanged() override;
PixmapButton * ledButton()
{
@@ -56,8 +58,8 @@ public:
protected:
virtual void mousePressEvent( QMouseEvent * _me );
virtual void paintEvent( QPaintEvent * _pe );
void mousePressEvent( QMouseEvent * _me ) override;
void paintEvent( QPaintEvent * _pe ) override;
private:
@@ -70,6 +72,7 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -25,17 +25,22 @@
#ifndef GUIAPPLICATION_H
#define GUIAPPLICATION_H
#include <QtCore/QObject>
#include <QObject>
#include "lmms_export.h"
#include "lmmsconfig.h"
class QLabel;
namespace lmms::gui
{
class AutomationEditorWindow;
class BBEditor;
class ControllerRackView;
class FxMixerView;
class MixerView;
class MainWindow;
class MicrotunerConfig;
class PatternEditorWindow;
class PianoRollWindow;
class ProjectNotes;
class SongEditorWindow;
@@ -45,16 +50,20 @@ class LMMS_EXPORT GuiApplication : public QObject
Q_OBJECT;
public:
explicit GuiApplication();
~GuiApplication();
~GuiApplication() override;
static GuiApplication* instance();
#ifdef LMMS_BUILD_WIN32
static QFont getWin32SystemFont();
#endif
MainWindow* mainWindow() { return m_mainWindow; }
FxMixerView* fxMixerView() { return m_fxMixerView; }
MixerView* mixerView() { return m_mixerView; }
SongEditorWindow* songEditor() { return m_songEditor; }
BBEditor* getBBEditor() { return m_bbEditor; }
PatternEditorWindow* patternEditor() { return m_patternEditor; }
PianoRollWindow* pianoRoll() { return m_pianoRoll; }
ProjectNotes* getProjectNotes() { return m_projectNotes; }
MicrotunerConfig* getMicrotunerConfig() { return m_microtunerConfig; }
AutomationEditorWindow* automationEditor() { return m_automationEditor; }
ControllerRackView* getControllerRackView() { return m_controllerRackView; }
@@ -68,16 +77,20 @@ private:
static GuiApplication* s_instance;
MainWindow* m_mainWindow;
FxMixerView* m_fxMixerView;
MixerView* m_mixerView;
SongEditorWindow* m_songEditor;
AutomationEditorWindow* m_automationEditor;
BBEditor* m_bbEditor;
PatternEditorWindow* m_patternEditor;
PianoRollWindow* m_pianoRoll;
ProjectNotes* m_projectNotes;
MicrotunerConfig* m_microtunerConfig;
ControllerRackView* m_controllerRackView;
QLabel* m_loadingProgressLabel;
};
#define gui GuiApplication::instance()
// Short-hand function
LMMS_EXPORT GuiApplication* getGUI();
} // namespace lmms::gui
#endif // GUIAPPLICATION_H

View File

@@ -26,10 +26,13 @@
#ifndef IMPORT_FILTER_H
#define IMPORT_FILTER_H
#include <QtCore/QFile>
#include <QFile>
#include "Plugin.h"
namespace lmms
{
class TrackContainer;
@@ -39,7 +42,7 @@ class LMMS_EXPORT ImportFilter : public Plugin
public:
ImportFilter( const QString & _file_name,
const Descriptor * _descriptor );
virtual ~ImportFilter();
~ImportFilter() override = default;
// tries to import given file to given track-container by having all
@@ -89,15 +92,15 @@ protected:
m_file.ungetChar( _ch );
}
virtual void saveSettings( QDomDocument &, QDomElement & )
void saveSettings( QDomDocument &, QDomElement & ) override
{
}
virtual void loadSettings( const QDomElement & )
void loadSettings( const QDomElement & ) override
{
}
virtual QString nodeName() const
QString nodeName() const override
{
return "import_filter";
}
@@ -109,4 +112,6 @@ private:
} ;
} // namespace lmms
#endif

View File

@@ -25,9 +25,12 @@
#ifndef INLINE_AUTOMATION_H
#define INLINE_AUTOMATION_H
#include "AutomationPattern.h"
#include "AutomationNode.h"
#include "AutomationClip.h"
#include "shared_object.h"
namespace lmms
{
class InlineAutomation : public FloatModel, public sharedObject
{
@@ -35,15 +38,15 @@ public:
InlineAutomation() :
FloatModel(),
sharedObject(),
m_autoPattern( NULL )
m_autoClip( nullptr )
{
}
virtual ~InlineAutomation()
~InlineAutomation() override
{
if( m_autoPattern )
if( m_autoClip )
{
delete m_autoPattern;
delete m_autoClip;
}
}
@@ -51,14 +54,19 @@ public:
bool hasAutomation() const
{
if( m_autoPattern != NULL && m_autoPattern->getTimeMap().isEmpty() == false )
if( m_autoClip != nullptr && m_autoClip->getTimeMap().isEmpty() == false )
{
// prevent saving inline automation if there's just one value which equals value
// of model which is going to be saved anyways
if( isAtInitValue() &&
m_autoPattern->getTimeMap().size() == 1 &&
m_autoPattern->getTimeMap().keys().first() == 0 &&
m_autoPattern->getTimeMap().values().first() == value() )
// Prevent saving inline automation if there's just one node at the beginning of
// the clip, which has a InValue equal to the value of model (which is going
// to be saved anyways) and no offset between the InValue and OutValue
AutomationClip::timeMap::const_iterator firstNode =
m_autoClip->getTimeMap().begin();
if (isAtInitValue()
&& m_autoClip->getTimeMap().size() == 1
&& POS(firstNode) == 0
&& INVAL(firstNode) == value()
&& OFFSET(firstNode) == 0)
{
return false;
}
@@ -69,24 +77,26 @@ public:
return false;
}
AutomationPattern * automationPattern()
AutomationClip * automationClip()
{
if( m_autoPattern == NULL )
if( m_autoClip == nullptr )
{
m_autoPattern = new AutomationPattern( NULL );
m_autoPattern->addObject( this );
m_autoClip = new AutomationClip( nullptr );
m_autoClip->addObject( this );
}
return m_autoPattern;
return m_autoClip;
}
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
private:
AutomationPattern * m_autoPattern;
AutomationClip * m_autoClip;
} ;
} // namespace lmms
#endif

View File

@@ -30,9 +30,11 @@
#include "lmms_export.h"
#include "lmms_basics.h"
#include "MemoryManager.h"
#include "MidiTime.h"
#include "Plugin.h"
#include "TimePos.h"
namespace lmms
{
// forward-declarations
class InstrumentTrack;
@@ -58,7 +60,7 @@ public:
Instrument(InstrumentTrack * _instrument_track,
const Descriptor * _descriptor,
const Descriptor::SubPluginFeatures::Key * key = nullptr);
virtual ~Instrument() = default;
~Instrument() override = default;
// --------------------------------------------------------------------
// functions that can/should be re-implemented:
@@ -68,7 +70,7 @@ public:
// if the plugin doesn't play each note, it can create an instrument-
// play-handle and re-implement this method, so that it mixes its
// output buffer only once per mixer-period
// output buffer only once per audio engine period
virtual void play( sampleFrame * _working_buffer );
// to be implemented by actual plugin
@@ -105,12 +107,12 @@ 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;
}
virtual QString fullDisplayName() const;
QString fullDisplayName() const override;
// --------------------------------------------------------------------
// provided functions:
@@ -132,6 +134,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
@@ -143,6 +148,10 @@ private:
} ;
Q_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flags)
} // namespace lmms
#endif

View File

@@ -30,26 +30,31 @@
#include <QWidget>
class QLabel;
namespace lmms
{
class InstrumentFunctionArpeggio;
class InstrumentFunctionNoteStacking;
namespace gui
{
class ComboBox;
class GroupBox;
class Knob;
class TempoSyncKnob;
class InstrumentFunctionArpeggio;
class InstrumentFunctionNoteStacking;
class InstrumentFunctionNoteStackingView : public QWidget, public ModelView
{
Q_OBJECT
public:
InstrumentFunctionNoteStackingView( InstrumentFunctionNoteStacking* cc, QWidget* parent = NULL );
virtual ~InstrumentFunctionNoteStackingView();
InstrumentFunctionNoteStackingView( InstrumentFunctionNoteStacking* cc, QWidget* parent = nullptr );
~InstrumentFunctionNoteStackingView() override;
private:
virtual void modelChanged();
void modelChanged() override;
InstrumentFunctionNoteStacking * m_cc;
@@ -67,17 +72,18 @@ class InstrumentFunctionArpeggioView : public QWidget, public ModelView
{
Q_OBJECT
public:
InstrumentFunctionArpeggioView( InstrumentFunctionArpeggio* arp, QWidget* parent = NULL );
virtual ~InstrumentFunctionArpeggioView();
InstrumentFunctionArpeggioView( InstrumentFunctionArpeggio* arp, QWidget* parent = nullptr );
~InstrumentFunctionArpeggioView() override;
private:
virtual void modelChanged();
void modelChanged() override;
InstrumentFunctionArpeggio * m_a;
GroupBox * m_arpGroupBox;
ComboBox * m_arpComboBox;
Knob * m_arpRangeKnob;
Knob * m_arpRepeatsKnob;
Knob * m_arpCycleKnob;
Knob * m_arpSkipKnob;
Knob * m_arpMissKnob;
@@ -89,5 +95,8 @@ private:
} ;
} // namespace gui
} // namespace lmms
#endif

View File

@@ -31,10 +31,19 @@
#include "TempoSyncKnobModel.h"
#include "ComboBoxModel.h"
namespace lmms
{
class InstrumentTrack;
class NotePlayHandle;
namespace gui
{
class InstrumentFunctionNoteStackingView;
class InstrumentFunctionArpeggioView;
}
class InstrumentFunctionNoteStacking : public Model, public JournallingObject
@@ -45,19 +54,19 @@ public:
static const int MAX_CHORD_POLYPHONY = 13;
private:
typedef int8_t ChordSemiTones [MAX_CHORD_POLYPHONY];
using ChordSemiTones = std::array<int8_t, MAX_CHORD_POLYPHONY>;
public:
InstrumentFunctionNoteStacking( Model * _parent );
virtual ~InstrumentFunctionNoteStacking();
~InstrumentFunctionNoteStacking() override = default;
void processNote( NotePlayHandle* n );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
inline virtual QString nodeName() const
inline QString nodeName() const override
{
return "chordcreator";
}
@@ -149,7 +158,7 @@ private:
FloatModel m_chordRangeModel;
friend class InstrumentFunctionNoteStackingView;
friend class gui::InstrumentFunctionNoteStackingView;
} ;
@@ -171,15 +180,15 @@ public:
} ;
InstrumentFunctionArpeggio( Model * _parent );
virtual ~InstrumentFunctionArpeggio();
~InstrumentFunctionArpeggio() override = default;
void processNote( NotePlayHandle* n );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
inline virtual QString nodeName() const
inline QString nodeName() const override
{
return "arpeggiator";
}
@@ -196,6 +205,7 @@ private:
BoolModel m_arpEnabledModel;
ComboBoxModel m_arpModel;
FloatModel m_arpRangeModel;
FloatModel m_arpRepeatsModel;
FloatModel m_arpCycleModel;
FloatModel m_arpSkipModel;
FloatModel m_arpMissModel;
@@ -206,9 +216,11 @@ private:
friend class InstrumentTrack;
friend class InstrumentFunctionArpeggioView;
friend class gui::InstrumentFunctionArpeggioView;
} ;
} // namespace lmms
#endif

View File

@@ -30,12 +30,19 @@
#include "ModelView.h"
class QToolButton;
namespace lmms
{
class InstrumentTrack;
namespace gui
{
class GroupBox;
class LcdSpinBox;
class QToolButton;
class LedCheckBox;
class InstrumentTrack;
class InstrumentMidiIOView : public QWidget, public ModelView
@@ -43,11 +50,11 @@ class InstrumentMidiIOView : public QWidget, public ModelView
Q_OBJECT
public:
InstrumentMidiIOView( QWidget* parent );
virtual ~InstrumentMidiIOView();
~InstrumentMidiIOView() override = default;
private:
virtual void modelChanged();
void modelChanged() override;
GroupBox * m_midiInputGroupBox;
LcdSpinBox * m_inputChannelSpinBox;
@@ -65,22 +72,9 @@ private:
} ;
class InstrumentMiscView : public QWidget
{
Q_OBJECT
public:
InstrumentMiscView( InstrumentTrack *it, QWidget* parent );
~InstrumentMiscView();
GroupBox * pitchGroupBox()
{
return m_pitchGroupBox;
}
} // namespace gui
private:
GroupBox * m_pitchGroupBox;
};
} // namespace lmms
#endif

View File

@@ -0,0 +1,74 @@
/*
* InstrumentMiscView.h - widget in instrument-track-window for setting up
* miscellaneous options not covered by other tabs
*
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2020 Martin Pavelek <he29.HS/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 INSTRUMENT_MISC_VIEW_H
#define INSTRUMENT_MISC_VIEW_H
#include <QWidget>
namespace lmms
{
class InstrumentTrack;
namespace gui
{
class ComboBox;
class GroupBox;
class LedCheckBox;
class InstrumentMiscView : public QWidget
{
Q_OBJECT
public:
InstrumentMiscView(InstrumentTrack *it, QWidget *parent);
GroupBox *pitchGroupBox() {return m_pitchGroupBox;}
GroupBox *microtunerGroupBox() {return m_microtunerGroupBox;}
ComboBox *scaleCombo() {return m_scaleCombo;}
ComboBox *keymapCombo() {return m_keymapCombo;}
LedCheckBox *rangeImportCheckbox() {return m_rangeImportCheckbox;}
private:
GroupBox *m_pitchGroupBox;
GroupBox *m_microtunerGroupBox;
ComboBox *m_scaleCombo;
ComboBox *m_keymapCombo;
LedCheckBox *m_rangeImportCheckbox;
};
} // namespace gui
} // namespace lmms
#endif

View File

@@ -30,17 +30,18 @@
#include "NotePlayHandle.h"
#include "lmms_export.h"
namespace lmms
{
class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle
{
public:
InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack );
virtual ~InstrumentPlayHandle()
{
}
~InstrumentPlayHandle() override = default;
virtual void play( sampleFrame * _working_buffer )
void play( sampleFrame * _working_buffer ) override
{
// ensure that all our nph's have been processed first
ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true );
@@ -65,12 +66,12 @@ public:
m_instrument->play( _working_buffer );
}
virtual bool isFinished() const
bool isFinished() const override
{
return false;
}
virtual bool isFromTrack( const Track* _track ) const
bool isFromTrack( const Track* _track ) const override
{
return m_instrument->isFromTrack( _track );
}
@@ -81,4 +82,7 @@ private:
} ;
} // namespace lmms
#endif

View File

@@ -27,18 +27,26 @@
#include "ComboBoxModel.h"
namespace lmms
{
class InstrumentTrack;
class EnvelopeAndLfoParameters;
class NotePlayHandle;
namespace gui
{
class InstrumentSoundShapingView;
}
class InstrumentSoundShaping : public Model, public JournallingObject
{
Q_OBJECT
public:
InstrumentSoundShaping( InstrumentTrack * _instrument_track );
virtual ~InstrumentSoundShaping();
~InstrumentSoundShaping() override = default;
void processAudioBuffer( sampleFrame * _ab, const fpp_t _frames,
NotePlayHandle * _n );
@@ -57,9 +65,9 @@ public:
float volumeLevel( NotePlayHandle * _n, const f_cnt_t _frame );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
virtual void loadSettings( const QDomElement & _this );
inline virtual QString nodeName() const
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
void loadSettings( const QDomElement & _this ) override;
inline QString nodeName() const override
{
return "eldata";
}
@@ -74,12 +82,14 @@ 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;
friend class gui::InstrumentSoundShapingView;
} ;
} // namespace lmms
#endif

View File

@@ -32,6 +32,9 @@
class QLabel;
namespace lmms::gui
{
class EnvelopeAndLfoView;
class ComboBox;
class GroupBox;
@@ -44,13 +47,13 @@ class InstrumentSoundShapingView : public QWidget, public ModelView
Q_OBJECT
public:
InstrumentSoundShapingView( QWidget * _parent );
virtual ~InstrumentSoundShapingView();
~InstrumentSoundShapingView() override;
void setFunctionsHidden( bool hidden );
private:
virtual void modelChanged();
void modelChanged() override;
InstrumentSoundShaping * m_ss;
@@ -67,4 +70,7 @@ private:
} ;
} // namespace lmms::gui
#endif

View File

@@ -1,6 +1,6 @@
/*
* InstrumentTrack.h - declaration of class InstrumentTrack, a track + window
* which holds an instrument-plugin
* InstrumentTrack.h - declaration of class InstrumentTrack, a track which
* holds an instrument-plugin
*
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -27,42 +27,34 @@
#define INSTRUMENT_TRACK_H
#include "AudioPort.h"
#include "GroupBox.h"
#include "InstrumentFunctions.h"
#include "InstrumentSoundShaping.h"
#include "Microtuner.h"
#include "Midi.h"
#include "MidiEventProcessor.h"
#include "MidiPort.h"
#include "NotePlayHandle.h"
#include "Piano.h"
#include "PianoView.h"
#include "Pitch.h"
#include "Plugin.h"
#include "Track.h"
namespace lmms
{
class QLineEdit;
template<class T> class QQueue;
class InstrumentFunctionArpeggioView;
class InstrumentFunctionNoteStackingView;
class EffectRackView;
class InstrumentSoundShapingView;
class FadeButton;
class Instrument;
class InstrumentTrackWindow;
class InstrumentMidiIOView;
class InstrumentMiscView;
class Knob;
class FxLineLcdSpinBox;
class LcdSpinBox;
class LeftRightNav;
class midiPortMenu;
class DataFile;
class PluginView;
class TabWidget;
class TrackLabelButton;
class LedCheckBox;
class QLabel;
namespace gui
{
class InstrumentTrackView;
class InstrumentTrackWindow;
class InstrumentMiscView;
class MidiCCRackView;
} // namespace gui
class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor
@@ -72,7 +64,7 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor
mapPropertyFromModel(int,getVolume,setVolume,m_volumeModel);
public:
InstrumentTrack( TrackContainer* tc );
virtual ~InstrumentTrack();
~InstrumentTrack() override;
// used by instrument
void processAudioBuffer( sampleFrame * _buf, const fpp_t _frames,
@@ -80,8 +72,8 @@ public:
MidiEvent applyMasterKey( const MidiEvent& event );
virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 );
virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 );
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 );
@@ -111,7 +103,7 @@ public:
void deleteNotePluginData( NotePlayHandle * _n );
// name-stuff
virtual void setName( const QString & _new_name );
void setName( const QString & _new_name ) override;
// translate given key of a note-event to absolute key (i.e.
// add global master-pitch and base-note of this instrument track)
@@ -130,19 +122,19 @@ public:
}
// play everything in given frame-range - creates note-play-handles
virtual bool play( const MidiTime & _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _tco_num = -1 );
bool play( const TimePos & _start, const fpp_t _frames,
const f_cnt_t _frame_base, int _clip_num = -1 ) override;
// create new view for me
virtual TrackView * createView( TrackContainerView* tcv );
gui::TrackView* createView( gui::TrackContainerView* tcv ) override;
// create new track-content-object = pattern
virtual TrackContentObject * createTCO( const MidiTime & _pos );
// create new track-content-object = clip
Clip* createClip(const TimePos & pos) override;
// called by track
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void loadTrackSpecificSettings( const QDomElement & _this );
void saveTrackSpecificSettings( QDomDocument & _doc,
QDomElement & _parent ) override;
void loadTrackSpecificSettings( const QDomElement & _this ) override;
using Track::setJournalling;
@@ -172,13 +164,33 @@ public:
return &m_baseNoteModel;
}
IntModel *firstKeyModel()
{
return &m_firstKeyModel;
}
IntModel *lastKeyModel()
{
return &m_lastKeyModel;
}
bool keyRangeImport() const;
bool isKeyMapped(int key) const;
int firstKey() const;
int lastKey() const;
int baseNote() const;
float baseFreq() const;
Piano *pianoModel()
{
return &m_piano;
}
Microtuner *microtuner()
{
return &m_microtuner;
}
bool isArpeggioEnabled() const
{
return m_arpeggio.m_arpEnabledModel.value();
@@ -207,38 +219,50 @@ public:
return &m_pitchRangeModel;
}
IntModel * effectChannelModel()
IntModel * mixerChannelModel()
{
return &m_effectChannelModel;
return &m_mixerChannelModel;
}
void setPreviewMode( const bool );
bool isPreviewMode() const
{
return m_previewMode;
}
void replaceInstrument(DataFile dataFile);
void autoAssignMidiDevice( bool );
signals:
void instrumentChanged();
void midiNoteOn( const Note& );
void midiNoteOff( const Note& );
void midiNoteOn( const lmms::Note& );
void midiNoteOff( const lmms::Note& );
void nameChanged();
void newNote();
void endNote();
protected:
virtual QString nodeName() const
QString nodeName() const override
{
return "instrumenttrack";
}
// get the name of the instrument in the saved data
QString getSavedInstrumentName(const QDomElement & thisElement) const;
protected slots:
void updateBaseNote();
void updatePitch();
void updatePitchRange();
void updateEffectChannel();
void updateMixerChannel();
private:
void processCCEvent(int controller);
MidiPort m_midiPort;
NotePlayHandle* m_notes[NumKeys];
@@ -253,7 +277,12 @@ private:
bool m_previewMode;
IntModel m_baseNoteModel;
IntModel m_baseNoteModel; //!< The "A4" or "440 Hz" key (default 69)
IntModel m_firstKeyModel; //!< First key the instrument reacts to
IntModel m_lastKeyModel; //!< Last key the instrument reacts to
bool m_hasAutoMidiDev;
static InstrumentTrack *s_autoAssignedTrack;
NotePlayHandleList m_processHandles;
@@ -264,10 +293,9 @@ private:
FloatModel m_pitchModel;
IntModel m_pitchRangeModel;
IntModel m_effectChannelModel;
IntModel m_mixerChannelModel;
BoolModel m_useMasterPitchModel;
Instrument * m_instrument;
InstrumentSoundShaping m_soundShaping;
InstrumentFunctionArpeggio m_arpeggio;
@@ -275,201 +303,21 @@ private:
Piano m_piano;
Microtuner m_microtuner;
friend class InstrumentTrackView;
friend class InstrumentTrackWindow;
std::unique_ptr<BoolModel> m_midiCCEnable;
std::unique_ptr<FloatModel> m_midiCCModel[MidiControllerCount];
friend class gui::InstrumentTrackView;
friend class gui::InstrumentTrackWindow;
friend class NotePlayHandle;
friend class InstrumentMiscView;
friend class gui::InstrumentMiscView;
friend class gui::MidiCCRackView;
} ;
class InstrumentTrackView : public TrackView
{
Q_OBJECT
public:
InstrumentTrackView( InstrumentTrack * _it, TrackContainerView* tc );
virtual ~InstrumentTrackView();
InstrumentTrackWindow * getInstrumentTrackWindow();
InstrumentTrack * model()
{
return castModel<InstrumentTrack>();
}
const InstrumentTrack * model() const
{
return castModel<InstrumentTrack>();
}
static InstrumentTrackWindow * topLevelInstrumentTrackWindow();
QMenu * midiMenu()
{
return m_midiMenu;
}
void freeInstrumentTrackWindow();
static void cleanupWindowCache();
// Create a menu for assigning/creating channels for this track
QMenu * createFxMenu( QString title, QString newFxLabel );
protected:
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
private slots:
void toggleInstrumentWindow( bool _on );
void activityIndicatorPressed();
void activityIndicatorReleased();
void midiInSelected();
void midiOutSelected();
void midiConfigChanged();
void muteChanged();
void assignFxLine( int channelIndex );
void createFxLine();
private:
InstrumentTrackWindow * m_window;
static QQueue<InstrumentTrackWindow *> s_windowCache;
// widgets in track-settings-widget
TrackLabelButton * m_tlb;
Knob * m_volumeKnob;
Knob * m_panningKnob;
FadeButton * m_activityIndicator;
QMenu * m_midiMenu;
QAction * m_midiInputAction;
QAction * m_midiOutputAction;
QPoint m_lastPos;
friend class InstrumentTrackWindow;
} ;
class InstrumentTrackWindow : public QWidget, public ModelView,
public SerializingObjectHook
{
Q_OBJECT
public:
InstrumentTrackWindow( InstrumentTrackView * _tv );
virtual ~InstrumentTrackWindow();
// parent for all internal tab-widgets
TabWidget * tabWidgetParent()
{
return m_tabWidget;
}
InstrumentTrack * model()
{
return castModel<InstrumentTrack>();
}
const InstrumentTrack * model() const
{
return castModel<InstrumentTrack>();
}
void setInstrumentTrackView( InstrumentTrackView * _tv );
InstrumentTrackView *instrumentTrackView()
{
return m_itv;
}
PianoView * pianoView()
{
return m_pianoView;
}
static void dragEnterEventGeneric( QDragEnterEvent * _dee );
virtual void dragEnterEvent( QDragEnterEvent * _dee );
virtual void dropEvent( QDropEvent * _de );
public slots:
void textChanged( const QString & _new_name );
void toggleVisibility( bool _on );
void updateName();
void updateInstrumentView();
protected:
// capture close-events for toggling instrument-track-button
virtual void closeEvent( QCloseEvent * _ce );
virtual void focusInEvent( QFocusEvent * _fe );
virtual void saveSettings( QDomDocument & _doc, QDomElement & _this );
virtual void loadSettings( const QDomElement & _this );
protected slots:
void saveSettingsBtnClicked();
void viewNextInstrument();
void viewPrevInstrument();
private:
virtual void modelChanged();
void viewInstrumentInDirection(int d);
//! adjust size of any child widget of the main tab
//! required to keep the old look when using a variable sized tab widget
void adjustTabSize(QWidget *w);
InstrumentTrack * m_track;
InstrumentTrackView * m_itv;
// widgets on the top of an instrument-track-window
QLineEdit * m_nameLineEdit;
LeftRightNav * m_leftRightNav;
Knob * m_volumeKnob;
Knob * m_panningKnob;
Knob * m_pitchKnob;
QLabel * m_pitchLabel;
LcdSpinBox* m_pitchRangeSpinBox;
QLabel * m_pitchRangeLabel;
FxLineLcdSpinBox * m_effectChannelNumber;
// tab-widget with all children
TabWidget * m_tabWidget;
PluginView * m_instrumentView;
InstrumentSoundShapingView * m_ssView;
InstrumentFunctionNoteStackingView* m_noteStackingView;
InstrumentFunctionArpeggioView* m_arpeggioView;
InstrumentMidiIOView * m_midiView;
EffectRackView * m_effectView;
InstrumentMiscView *m_miscView;
// test-piano at the bottom of every instrument-settings-window
PianoView * m_pianoView;
friend class InstrumentView;
} ;
} // namespace lmms
#endif

View File

@@ -0,0 +1,124 @@
/*
* InstrumentTrackView.h - declaration of InstrumentTrackView 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 INSTRUMENT_TRACK_VIEW_H
#define INSTRUMENT_TRACK_VIEW_H
#include "TrackView.h"
#include "InstrumentTrack.h"
namespace lmms::gui
{
class InstrumentTrackWindow;
class Knob;
class MidiCCRackView;
class TrackContainerView;
class TrackLabelButton;
class InstrumentTrackView : public TrackView
{
Q_OBJECT
public:
InstrumentTrackView( InstrumentTrack * _it, TrackContainerView* tc );
~InstrumentTrackView() override;
InstrumentTrackWindow * getInstrumentTrackWindow();
InstrumentTrack * model()
{
return castModel<InstrumentTrack>();
}
const InstrumentTrack * model() const
{
return castModel<InstrumentTrack>();
}
static InstrumentTrackWindow * topLevelInstrumentTrackWindow();
QMenu * midiMenu()
{
return m_midiMenu;
}
// Create a menu for assigning/creating channels for this track
QMenu * createMixerMenu( QString title, QString newMixerLabel ) override;
protected:
void dragEnterEvent( QDragEnterEvent * _dee ) override;
void dropEvent( QDropEvent * _de ) override;
private slots:
void toggleInstrumentWindow( bool _on );
void toggleMidiCCRack();
void activityIndicatorPressed();
void activityIndicatorReleased();
void midiInSelected();
void midiOutSelected();
void midiConfigChanged();
void assignMixerLine( int channelIndex );
void createMixerLine();
void handleConfigChange(QString cls, QString attr, QString value);
private:
InstrumentTrackWindow * m_window;
// widgets in track-settings-widget
TrackLabelButton * m_tlb;
Knob * m_volumeKnob;
Knob * m_panningKnob;
FadeButton * m_activityIndicator;
QMenu * m_midiMenu;
QAction * m_midiInputAction;
QAction * m_midiOutputAction;
std::unique_ptr<MidiCCRackView> m_midiCCRackView;
QPoint m_lastPos;
FadeButton * getActivityIndicator() override
{
return m_activityIndicator;
}
friend class InstrumentTrackWindow;
} ;
} // namespace lmms::gui
#endif

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