Merge branch 'master' into groove
This commit is contained in:
@@ -66,12 +66,12 @@ public:
|
||||
typedef std::vector<DeviceInfo> DeviceInfoCollection;
|
||||
|
||||
public:
|
||||
AudioAlsa( bool & _success_ful, Mixer* mixer );
|
||||
AudioAlsa( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioAlsa();
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget",
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
|
||||
"ALSA (Advanced Linux Sound Architecture)" );
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
*
|
||||
@@ -31,15 +31,15 @@
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
class AudioEngine;
|
||||
class AudioPort;
|
||||
class Mixer;
|
||||
class QThread;
|
||||
|
||||
|
||||
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 +115,7 @@ protected:
|
||||
const fpp_t _frames );
|
||||
|
||||
// resample given buffer from samplerate _src_sr to samplerate _dst_sr
|
||||
void resample( const surroundSampleFrame * _src,
|
||||
fpp_t resample( const surroundSampleFrame * _src,
|
||||
const fpp_t _frames,
|
||||
surroundSampleFrame * _dst,
|
||||
const sample_rate_t _src_sr,
|
||||
@@ -126,9 +126,9 @@ protected:
|
||||
m_sampleRate = _new_sr;
|
||||
}
|
||||
|
||||
Mixer* mixer()
|
||||
AudioEngine* audioEngine()
|
||||
{
|
||||
return m_mixer;
|
||||
return m_audioEngine;
|
||||
}
|
||||
|
||||
bool hqAudio() const;
|
||||
@@ -143,7 +143,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;
|
||||
|
||||
@@ -27,16 +27,16 @@
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
#include "AudioEngine.h"
|
||||
#include "MicroTimer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget", "Dummy (no sound output)" );
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "Dummy (no sound output)" );
|
||||
}
|
||||
|
||||
|
||||
@@ -94,17 +94,17 @@ private:
|
||||
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 );
|
||||
|
||||
435
include/AudioEngine.h
Normal file
435
include/AudioEngine.h
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* 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 <QtCore/QMutex>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QWaitCondition>
|
||||
#include <samplerate.h>
|
||||
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "LocklessList.h"
|
||||
#include "Note.h"
|
||||
#include "FifoBuffer.h"
|
||||
#include "AudioEngineProfiler.h"
|
||||
#include "PlayHandle.h"
|
||||
|
||||
|
||||
class AudioDevice;
|
||||
class MidiClient;
|
||||
class AudioPort;
|
||||
|
||||
|
||||
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 AudioEngineWorkerThread;
|
||||
|
||||
|
||||
class LMMS_EXPORT AudioEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
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();
|
||||
|
||||
static bool isAudioDevNameValid(QString name);
|
||||
static bool isMidiDevNameValid(QString name);
|
||||
|
||||
|
||||
signals:
|
||||
void qualitySettingsChanged();
|
||||
void sampleRateChanged();
|
||||
void nextAudioBuffer( const surroundSampleFrame * buffer );
|
||||
|
||||
|
||||
private:
|
||||
typedef FifoBuffer<surroundSampleFrame *> Fifo;
|
||||
|
||||
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 );
|
||||
virtual ~AudioEngine();
|
||||
|
||||
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;
|
||||
QMutex m_doChangesMutex;
|
||||
QMutex m_waitChangesMutex;
|
||||
QWaitCondition m_changesAudioEngineCondition;
|
||||
QWaitCondition m_changesRequestCondition;
|
||||
|
||||
bool m_waitingForWrite;
|
||||
|
||||
friend class LmmsCore;
|
||||
friend class AudioEngineWorkerThread;
|
||||
friend class ProjectRenderer;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
@@ -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,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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
|
||||
class AudioEngineProfiler
|
||||
{
|
||||
public:
|
||||
MixerProfiler();
|
||||
~MixerProfiler();
|
||||
AudioEngineProfiler();
|
||||
~AudioEngineProfiler();
|
||||
|
||||
void startPeriod()
|
||||
{
|
||||
@@ -55,7 +55,6 @@ private:
|
||||
MicroTimer m_periodTimer;
|
||||
int m_cpuLoad;
|
||||
QFile m_outputFile;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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 <atomic>
|
||||
|
||||
class AudioEngine;
|
||||
class QWaitCondition;
|
||||
class Mixer;
|
||||
class ThreadableJob;
|
||||
|
||||
class MixerWorkerThread : public QThread
|
||||
class AudioEngineWorkerThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -47,7 +47,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 +70,11 @@ public:
|
||||
std::atomic_int m_writeIndex;
|
||||
std::atomic_int m_itemsDone;
|
||||
OperationMode m_opMode;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
MixerWorkerThread( Mixer* mixer );
|
||||
virtual ~MixerWorkerThread();
|
||||
AudioEngineWorkerThread( AudioEngine* audioEngine );
|
||||
virtual ~AudioEngineWorkerThread();
|
||||
|
||||
virtual void quit();
|
||||
|
||||
@@ -110,10 +110,9 @@ private:
|
||||
|
||||
static JobQueue globalJobQueue;
|
||||
static QWaitCondition * queueReadyWaitCond;
|
||||
static QList<MixerWorkerThread *> workerThreads;
|
||||
static QList<AudioEngineWorkerThread *> workerThreads;
|
||||
|
||||
volatile bool m_quit;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class AudioFileDevice : public AudioDevice
|
||||
public:
|
||||
AudioFileDevice(OutputSettings const & outputSettings,
|
||||
const ch_cnt_t _channels, const QString & _file,
|
||||
Mixer* mixer );
|
||||
AudioEngine* audioEngine );
|
||||
virtual ~AudioFileDevice();
|
||||
|
||||
QString outputFile() const
|
||||
@@ -71,7 +71,7 @@ typedef AudioFileDevice * ( * AudioFileDeviceInstantiaton )
|
||||
( const QString & outputFilename,
|
||||
OutputSettings const & outputSettings,
|
||||
const ch_cnt_t channels,
|
||||
Mixer* mixer,
|
||||
AudioEngine* audioEngine,
|
||||
bool & successful );
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
ch_cnt_t const channels,
|
||||
bool& successful,
|
||||
QString const& file,
|
||||
Mixer* mixer
|
||||
AudioEngine* audioEngine
|
||||
);
|
||||
|
||||
virtual ~AudioFileFlac();
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
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 +53,7 @@ public:
|
||||
channels,
|
||||
successful,
|
||||
outputFilename,
|
||||
mixer
|
||||
audioEngine
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,17 +42,17 @@ public:
|
||||
const ch_cnt_t _channels,
|
||||
bool & successful,
|
||||
const QString & _file,
|
||||
Mixer* mixer );
|
||||
AudioEngine* audioEngine );
|
||||
virtual ~AudioFileMP3();
|
||||
|
||||
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:
|
||||
|
||||
@@ -42,17 +42,16 @@ public:
|
||||
const ch_cnt_t _channels,
|
||||
bool & _success_ful,
|
||||
const QString & _file,
|
||||
Mixer* mixer );
|
||||
AudioEngine* audioEngine );
|
||||
virtual ~AudioFileOgg();
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,17 +39,17 @@ public:
|
||||
const ch_cnt_t channels,
|
||||
bool & successful,
|
||||
const QString & file,
|
||||
Mixer* mixer );
|
||||
AudioEngine* audioEngine );
|
||||
virtual ~AudioFileWave();
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "weak_libjack.h"
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
@@ -50,18 +51,19 @@ class AudioJack : public QObject, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioJack( bool & _success_ful, Mixer* mixer );
|
||||
AudioJack( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioJack();
|
||||
|
||||
// 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(void) { m_midiClient = nullptr; }
|
||||
jack_client_t * jackClient() {return m_client;};
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget",
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
|
||||
"JACK (JACK Audio Connection Kit)" );
|
||||
}
|
||||
|
||||
@@ -106,9 +108,9 @@ private:
|
||||
jack_client_t * m_client;
|
||||
|
||||
bool m_active;
|
||||
bool m_stopped;
|
||||
std::atomic<bool> m_stopped;
|
||||
|
||||
MidiJack *m_midiClient;
|
||||
std::atomic<MidiJack *> m_midiClient;
|
||||
QVector<jack_port_t *> m_outputPorts;
|
||||
jack_default_audio_sample_t * * m_tempOutBufs;
|
||||
surroundSampleFrame * m_outBuf;
|
||||
|
||||
@@ -43,12 +43,12 @@ class AudioOss : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioOss( bool & _success_ful, Mixer* mixer );
|
||||
AudioOss( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioOss();
|
||||
|
||||
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();
|
||||
|
||||
@@ -42,8 +42,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 +71,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 +83,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ private:
|
||||
QMutex m_portBufferLock;
|
||||
|
||||
bool m_extOutputEnabled;
|
||||
fx_ch_t m_nextFxChannel;
|
||||
mix_ch_t m_nextMixerChannel;
|
||||
|
||||
QString m_name;
|
||||
|
||||
@@ -129,8 +129,8 @@ private:
|
||||
FloatModel * m_panningModel;
|
||||
BoolModel * m_mutedModel;
|
||||
|
||||
friend class Mixer;
|
||||
friend class MixerWorkerThread;
|
||||
friend class AudioEngine;
|
||||
friend class AudioEngineWorkerThread;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -67,12 +67,12 @@ class LcdSpinBox;
|
||||
class AudioPortAudio : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioPortAudio( bool & _success_ful, Mixer* mixer );
|
||||
AudioPortAudio( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioPortAudio();
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget", "PortAudio" );
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PortAudio" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,12 +45,12 @@ class AudioPulseAudio : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioPulseAudio( bool & _success_ful, Mixer* mixer );
|
||||
AudioPulseAudio( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioPulseAudio();
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget", "PulseAudio" );
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PulseAudio" );
|
||||
}
|
||||
|
||||
static QString probeDevice();
|
||||
|
||||
@@ -37,8 +37,7 @@ class SampleBuffer;
|
||||
class AudioSampleRecorder : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful,
|
||||
Mixer* mixer );
|
||||
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioSampleRecorder();
|
||||
|
||||
f_cnt_t framesRecorded() const;
|
||||
|
||||
@@ -46,12 +46,12 @@ class QLineEdit;
|
||||
class AudioSdl : public AudioDevice
|
||||
{
|
||||
public:
|
||||
AudioSdl( bool & _success_ful, Mixer* mixer );
|
||||
AudioSdl( bool & _success_ful, AudioEngine* audioEngine );
|
||||
virtual ~AudioSdl();
|
||||
|
||||
inline static QString name()
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget",
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget",
|
||||
"SDL (Simple DirectMedia Layer)" );
|
||||
}
|
||||
|
||||
|
||||
@@ -44,12 +44,12 @@ class AudioSndio : public QThread, public AudioDevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioSndio( bool & _success_ful, Mixer * _mixer );
|
||||
AudioSndio( bool & _success_ful, AudioEngine * _audioEngine );
|
||||
virtual ~AudioSndio();
|
||||
|
||||
inline static QString name( void )
|
||||
{
|
||||
return QT_TRANSLATE_NOOP( "setupWidget", "sndio" );
|
||||
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "sndio" );
|
||||
}
|
||||
|
||||
class setupWidget : public AudioDeviceSetupWidget
|
||||
|
||||
@@ -56,12 +56,12 @@ 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
|
||||
@@ -110,6 +110,7 @@ private:
|
||||
fpp_t m_outBufFrameIndex;
|
||||
|
||||
bool m_stopped;
|
||||
bool m_outstreamStarted;
|
||||
|
||||
int m_disconnectErr;
|
||||
void onBackendDisconnect(int err);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "Model.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "ValueBuffer.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ModelVisitor.h"
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
bool isAutomated() const;
|
||||
bool isAutomatedOrControlled() const
|
||||
{
|
||||
return isAutomated() || m_controllerConnection != NULL;
|
||||
return isAutomated() || m_controllerConnection != nullptr;
|
||||
}
|
||||
|
||||
ControllerConnection* controllerConnection() const
|
||||
@@ -148,7 +148,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 +247,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 );
|
||||
|
||||
@@ -280,7 +292,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
float globalAutomationValueAt( const MidiTime& time );
|
||||
float globalAutomationValueAt( const TimePos& time );
|
||||
|
||||
void setStrictStepSize( const bool b )
|
||||
{
|
||||
@@ -297,9 +309,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 +326,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
|
||||
@@ -359,7 +377,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,6 +412,8 @@ 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 );
|
||||
@@ -437,7 +457,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 +475,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 +491,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 )
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
}
|
||||
|
||||
void setModel( Model* model, bool isOldModelValid = true ) override;
|
||||
void unsetModel() override;
|
||||
|
||||
template<typename T>
|
||||
inline T value() const
|
||||
@@ -69,12 +70,16 @@ public:
|
||||
|
||||
void addDefaultActions( QMenu* menu );
|
||||
|
||||
void setConversionFactor( float factor );
|
||||
float getConversionFactor();
|
||||
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent( QMouseEvent* event );
|
||||
|
||||
QString m_description;
|
||||
QString m_unit;
|
||||
float m_conversionFactor; // Factor to be applied when the m_model->value is displayed
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -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,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTOMATION_PATTERN_H
|
||||
#define AUTOMATION_PATTERN_H
|
||||
#ifndef AUTOMATION_CLIP_H
|
||||
#define AUTOMATION_CLIP_H
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include "Track.h"
|
||||
#include "AutomationNode.h"
|
||||
#include "Clip.h"
|
||||
|
||||
|
||||
class AutomationTrack;
|
||||
class MidiTime;
|
||||
class TimePos;
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT AutomationPattern : public TrackContentObject
|
||||
class LMMS_EXPORT AutomationClip : public Clip
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -49,12 +50,14 @@ public:
|
||||
CubicHermiteProgression
|
||||
} ;
|
||||
|
||||
typedef QMap<int, float> timeMap;
|
||||
typedef QVector<QPointer<AutomatableModel> > objectVector;
|
||||
typedef QMap<int, AutomationNode> timeMap;
|
||||
typedef QVector<QPointer<AutomatableModel>> objectVector;
|
||||
|
||||
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 );
|
||||
virtual ~AutomationClip() = default;
|
||||
|
||||
bool addObject( AutomatableModel * _obj, bool _search_dup = true );
|
||||
|
||||
@@ -74,19 +77,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 +125,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,8 +140,8 @@ public:
|
||||
return m_timeMap.isEmpty() == false;
|
||||
}
|
||||
|
||||
float valueAt( const MidiTime & _time ) const;
|
||||
float *valuesAfter( const MidiTime & _time ) const;
|
||||
float valueAt( const TimePos & _time ) const;
|
||||
float *valuesAfter( const TimePos & _time ) const;
|
||||
|
||||
const QString name() const;
|
||||
|
||||
@@ -146,12 +152,12 @@ public:
|
||||
static const QString classNodeName() { return "automationpattern"; }
|
||||
QString nodeName() const override { return classNodeName(); }
|
||||
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
ClipView * createView( 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; }
|
||||
@@ -170,21 +176,26 @@ 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
|
||||
mutable QMutex m_clipMutex;
|
||||
|
||||
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 +204,42 @@ private:
|
||||
static const float DEFAULT_MIN_VALUE;
|
||||
static const float DEFAULT_MAX_VALUE;
|
||||
|
||||
friend class AutomationPatternView;
|
||||
friend class 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();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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,27 +22,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
class AutomationPattern;
|
||||
#include "AutomationClip.h"
|
||||
#include "Song.h"
|
||||
#include "SongEditor.h"
|
||||
#include "ClipView.h"
|
||||
|
||||
|
||||
class AutomationPatternView : public TrackContentObjectView
|
||||
class AutomationClipView : public ClipView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
AutomationPatternView( AutomationPattern * _pat, TrackView * _parent );
|
||||
virtual ~AutomationPatternView();
|
||||
AutomationClipView( AutomationClip * _clip, TrackView * _parent );
|
||||
virtual ~AutomationClipView();
|
||||
|
||||
public slots:
|
||||
/// Opens this view's pattern in the global automation editor
|
||||
/// Opens this view's clip in the global automation editor
|
||||
void openInAutomationEditor();
|
||||
void update() override;
|
||||
|
||||
@@ -64,12 +65,12 @@ protected:
|
||||
|
||||
|
||||
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 );
|
||||
} ;
|
||||
@@ -26,7 +26,6 @@
|
||||
#ifndef AUTOMATION_EDITOR_H
|
||||
#define AUTOMATION_EDITOR_H
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QVector>
|
||||
#include <QWidget>
|
||||
|
||||
@@ -34,8 +33,8 @@
|
||||
|
||||
#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"
|
||||
|
||||
@@ -52,25 +51,26 @@ 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;
|
||||
}
|
||||
|
||||
void saveSettings(QDomDocument & doc, QDomElement & parent) override;
|
||||
@@ -80,43 +80,25 @@ public:
|
||||
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;
|
||||
typedef AutomationClip::timeMap timeMap;
|
||||
|
||||
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;
|
||||
@@ -126,13 +108,12 @@ protected:
|
||||
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 +125,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 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 +143,10 @@ private:
|
||||
{
|
||||
NONE,
|
||||
MOVE_VALUE,
|
||||
SELECT_VALUES,
|
||||
MOVE_SELECTION
|
||||
ERASE_VALUES,
|
||||
MOVE_OUTVALUE,
|
||||
RESET_OUTVALUES,
|
||||
DRAW_LINE
|
||||
} ;
|
||||
|
||||
// some constants...
|
||||
@@ -187,7 +165,7 @@ private:
|
||||
|
||||
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 +174,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,22 +186,16 @@ 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;
|
||||
@@ -234,12 +205,12 @@ private:
|
||||
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;
|
||||
@@ -253,7 +224,8 @@ private:
|
||||
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 +234,8 @@ private:
|
||||
|
||||
|
||||
signals:
|
||||
void currentPatternChanged();
|
||||
void positionChanged( const MidiTime & );
|
||||
void currentClipChanged();
|
||||
void positionChanged( const TimePos & );
|
||||
} ;
|
||||
|
||||
|
||||
@@ -279,23 +251,23 @@ public:
|
||||
AutomationEditorWindow();
|
||||
~AutomationEditorWindow();
|
||||
|
||||
void setCurrentPattern(AutomationPattern* pattern);
|
||||
const AutomationPattern* currentPattern();
|
||||
void setCurrentClip(AutomationClip* clip);
|
||||
const AutomationClip* currentClip();
|
||||
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
|
||||
void open(AutomationPattern* pattern);
|
||||
void open(AutomationClip* clip);
|
||||
|
||||
AutomationEditor* m_editor;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
public slots:
|
||||
void clearCurrentPattern();
|
||||
void clearCurrentClip();
|
||||
|
||||
signals:
|
||||
void currentPatternChanged();
|
||||
void currentClipChanged();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent * event) override;
|
||||
|
||||
155
include/AutomationNode.h
Normal file
155
include/AutomationNode.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -37,8 +37,8 @@ public:
|
||||
AutomationTrack( TrackContainer* tc, bool _hidden = false );
|
||||
virtual ~AutomationTrack() = default;
|
||||
|
||||
virtual bool play( const MidiTime & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 ) override;
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _clip_num = -1 ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
}
|
||||
|
||||
TrackView * createView( TrackContainerView* ) override;
|
||||
TrackContentObject * createTCO( const MidiTime & _pos ) override;
|
||||
Clip* createClip(const TimePos & pos) override;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent ) override;
|
||||
@@ -58,17 +58,4 @@ private:
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class AutomationTrackView : public TrackView
|
||||
{
|
||||
public:
|
||||
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
|
||||
virtual ~AutomationTrackView() = default;
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
44
include/AutomationTrackView.h
Normal file
44
include/AutomationTrackView.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 "AutomationTrack.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
|
||||
class AutomationTrackView : public TrackView
|
||||
{
|
||||
public:
|
||||
AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv );
|
||||
virtual ~AutomationTrackView() = default;
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* custom_events.h - custom event types list
|
||||
* BBClip.h
|
||||
*
|
||||
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -21,26 +21,35 @@
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BB_CLIP_H
|
||||
#define BB_CLIP_H
|
||||
|
||||
#include "ClipView.h"
|
||||
|
||||
|
||||
#ifndef CUSTOM_EVENTS_H
|
||||
#define CUSTOM_EVENTS_H
|
||||
|
||||
|
||||
#include <QtCore/QEvent>
|
||||
|
||||
|
||||
namespace customEvents
|
||||
class BBClip : public Clip
|
||||
{
|
||||
public:
|
||||
BBClip( Track * _track );
|
||||
virtual ~BBClip() = default;
|
||||
|
||||
enum Type
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
GUI_UPDATE = QEvent::User
|
||||
} ;
|
||||
return( "bbtco" );
|
||||
}
|
||||
|
||||
}
|
||||
int bbTrackIndex();
|
||||
|
||||
ClipView * createView( TrackView * _tv ) override;
|
||||
|
||||
private:
|
||||
friend class BBClipView;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
66
include/BBClipView.h
Normal file
66
include/BBClipView.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* BBClipView.h
|
||||
*
|
||||
* 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_CLIP_VIEW_H
|
||||
#define BB_CLIP_VIEW_H
|
||||
|
||||
#include "BBClip.h"
|
||||
|
||||
#include <QStaticText>
|
||||
|
||||
|
||||
class BBClipView : public ClipView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BBClipView( Clip * _clip, TrackView * _tv );
|
||||
virtual ~BBClipView() = default;
|
||||
|
||||
|
||||
public slots:
|
||||
void update() override;
|
||||
|
||||
protected slots:
|
||||
void openInBBEditor();
|
||||
void resetName();
|
||||
void changeName();
|
||||
|
||||
|
||||
protected:
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
|
||||
void constructContextMenu( QMenu * ) override;
|
||||
|
||||
|
||||
private:
|
||||
BBClip * m_bbClip;
|
||||
QPixmap m_paintPixmap;
|
||||
|
||||
QStaticText m_staticTextName;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef BB_EDITOR_H
|
||||
#define BB_EDITOR_H
|
||||
|
||||
|
||||
#include "Editor.h"
|
||||
#include "TrackContainerView.h"
|
||||
|
||||
@@ -70,7 +71,7 @@ class BBTrackContainerView : public TrackContainerView
|
||||
public:
|
||||
BBTrackContainerView(BBTrackContainer* tc);
|
||||
|
||||
bool fixedTCOs() const override
|
||||
bool fixedClips() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -86,6 +87,7 @@ public slots:
|
||||
void removeSteps();
|
||||
void addSampleTrack();
|
||||
void addAutomationTrack();
|
||||
void cloneClip();
|
||||
|
||||
protected slots:
|
||||
void dropEvent(QDropEvent * de ) override;
|
||||
|
||||
@@ -27,104 +27,16 @@
|
||||
#ifndef BB_TRACK_H
|
||||
#define BB_TRACK_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QStaticText>
|
||||
|
||||
#include <QtCore/QMap>
|
||||
|
||||
#include "BBClipView.h"
|
||||
#include "Track.h"
|
||||
|
||||
class TrackLabelButton;
|
||||
class TrackContainer;
|
||||
|
||||
|
||||
class BBTCO : public TrackContentObject
|
||||
{
|
||||
public:
|
||||
BBTCO( Track * _track );
|
||||
virtual ~BBTCO() = default;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return( "bbtco" );
|
||||
}
|
||||
|
||||
unsigned int color() const
|
||||
{
|
||||
return( m_color.rgb() );
|
||||
}
|
||||
|
||||
QColor colorObj() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void setColor( const QColor & c )
|
||||
{
|
||||
m_color = QColor( c );
|
||||
}
|
||||
|
||||
void setUseStyleColor( bool b )
|
||||
{
|
||||
m_useStyleColor = b;
|
||||
}
|
||||
|
||||
int bbTrackIndex();
|
||||
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
|
||||
private:
|
||||
QColor m_color;
|
||||
bool m_useStyleColor;
|
||||
|
||||
|
||||
friend class BBTCOView;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
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:
|
||||
void update() override;
|
||||
|
||||
protected slots:
|
||||
void openInBBEditor();
|
||||
void resetName();
|
||||
void changeName();
|
||||
void changeColor();
|
||||
void resetColor();
|
||||
|
||||
|
||||
protected:
|
||||
void paintEvent( QPaintEvent * pe ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
|
||||
void constructContextMenu( QMenu * ) override;
|
||||
|
||||
|
||||
private:
|
||||
BBTCO * m_bbTCO;
|
||||
QPixmap m_paintPixmap;
|
||||
|
||||
QStaticText m_staticTextName;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT BBTrack : public Track
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -132,10 +44,10 @@ 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 ) override;
|
||||
virtual bool play( const TimePos & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _clip_num = -1 ) override;
|
||||
TrackView * createView( TrackContainerView* tcv ) override;
|
||||
TrackContentObject * createTCO( const MidiTime & _pos ) override;
|
||||
Clip* createClip(const TimePos & pos) override;
|
||||
|
||||
virtual void saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent ) override;
|
||||
@@ -162,27 +74,6 @@ public:
|
||||
m_disabledTracks.removeAll( _track );
|
||||
}
|
||||
|
||||
static void setLastTCOColor( const QColor & c )
|
||||
{
|
||||
if( ! s_lastTCOColor )
|
||||
{
|
||||
s_lastTCOColor = new QColor( c );
|
||||
}
|
||||
else
|
||||
{
|
||||
*s_lastTCOColor = QColor( c );
|
||||
}
|
||||
}
|
||||
|
||||
static void clearLastTCOColor()
|
||||
{
|
||||
if( s_lastTCOColor )
|
||||
{
|
||||
delete s_lastTCOColor;
|
||||
}
|
||||
s_lastTCOColor = NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
@@ -196,37 +87,7 @@ private:
|
||||
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();
|
||||
|
||||
bool close() override;
|
||||
|
||||
const BBTrack * getBBTrack() const
|
||||
{
|
||||
return( m_bbTrack );
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void clickedTrackLabel();
|
||||
|
||||
|
||||
private:
|
||||
BBTrack * m_bbTrack;
|
||||
TrackLabelButton * m_trackLabel;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ public:
|
||||
BBTrackContainer();
|
||||
virtual ~BBTrackContainer();
|
||||
|
||||
virtual bool play( MidiTime _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, int _tco_num = -1 );
|
||||
virtual bool play(TimePos start, const fpp_t frames, const f_cnt_t frameBase, int clipNum = -1);
|
||||
|
||||
void updateAfterTrackAdd() override;
|
||||
|
||||
@@ -48,21 +47,21 @@ public:
|
||||
return "bbtrackcontainer";
|
||||
}
|
||||
|
||||
bar_t lengthOfBB( int _bb ) const;
|
||||
bar_t lengthOfBB(int bb) const;
|
||||
inline bar_t lengthOfCurrentBB()
|
||||
{
|
||||
return lengthOfBB( currentBB() );
|
||||
return lengthOfBB(currentBB());
|
||||
}
|
||||
int numOfBBs() const;
|
||||
void removeBB( int _bb );
|
||||
void removeBB(int bb);
|
||||
|
||||
void swapBB( int _bb1, int _bb2 );
|
||||
void swapBB(int bb1, int bb2);
|
||||
|
||||
void updateBBTrack( TrackContentObject * _tco );
|
||||
void updateBBTrack(Clip * clip);
|
||||
void fixIncorrectPositions();
|
||||
void createTCOsForBB( int _bb );
|
||||
void createClipsForBB(int bb);
|
||||
|
||||
AutomatedValueMap automatedValuesAt(MidiTime time, int tcoNum) const override;
|
||||
AutomatedValueMap automatedValuesAt(TimePos time, int clipNum) const override;
|
||||
|
||||
public slots:
|
||||
void play();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* update_event.h - signal GUI updates
|
||||
* BBTrackView.h
|
||||
*
|
||||
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -23,22 +23,39 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UPDATE_EVENT_H
|
||||
#define UPDATE_EVENT_H
|
||||
#ifndef BB_TRACK_VIEW_H
|
||||
#define BB_TRACK_VIEW_H
|
||||
|
||||
#include "custom_events.h"
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "BBTrack.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
|
||||
|
||||
class updateEvent : public QEvent
|
||||
class BBTrackView : public TrackView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
updateEvent() :
|
||||
QEvent( (QEvent::Type)customEvents::GUI_UPDATE )
|
||||
BBTrackView( BBTrack* bbt, TrackContainerView* tcv );
|
||||
virtual ~BBTrackView();
|
||||
|
||||
bool close() override;
|
||||
|
||||
const BBTrack * getBBTrack() const
|
||||
{
|
||||
return( m_bbTrack );
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void clickedTrackLabel();
|
||||
|
||||
|
||||
private:
|
||||
BBTrack * m_bbTrack;
|
||||
TrackLabelButton * m_trackLabel;
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -34,14 +34,14 @@ 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
|
||||
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,
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -273,7 +273,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 +286,7 @@ public:
|
||||
m_doubleFilter( false ),
|
||||
m_sampleRate( (float) _sample_rate ),
|
||||
m_sampleRatio( 1.0f / m_sampleRate ),
|
||||
m_subFilter( NULL )
|
||||
m_subFilter( nullptr )
|
||||
{
|
||||
clearHistory();
|
||||
}
|
||||
|
||||
181
include/Clip.h
Normal file
181
include/Clip.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
|
||||
class Track;
|
||||
class ClipView;
|
||||
class TrackContainer;
|
||||
class TrackView;
|
||||
|
||||
|
||||
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 );
|
||||
virtual ~Clip();
|
||||
|
||||
inline Track * getTrack() const
|
||||
{
|
||||
return m_track;
|
||||
}
|
||||
|
||||
inline const QString & name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
inline void setName( const QString & name )
|
||||
{
|
||||
m_name = name;
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return name();
|
||||
}
|
||||
|
||||
|
||||
inline const TimePos & startPosition() const
|
||||
{
|
||||
return m_startPosition;
|
||||
}
|
||||
|
||||
inline TimePos endPosition() const
|
||||
{
|
||||
const int sp = m_startPosition;
|
||||
return sp + m_length;
|
||||
}
|
||||
|
||||
inline const TimePos & length() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline void setAutoResize( const bool r )
|
||||
{
|
||||
m_autoResize = r;
|
||||
}
|
||||
|
||||
inline const bool getAutoResize() const
|
||||
{
|
||||
return m_autoResize;
|
||||
}
|
||||
|
||||
QColor color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void setColor( const QColor & c )
|
||||
{
|
||||
m_color = c;
|
||||
}
|
||||
|
||||
bool hasColor();
|
||||
|
||||
void useCustomClipColor( bool b );
|
||||
|
||||
bool usesCustomClipColor()
|
||||
{
|
||||
return m_useCustomClipColor;
|
||||
}
|
||||
|
||||
virtual void movePosition( const TimePos & pos );
|
||||
virtual void changeLength( const TimePos & length );
|
||||
|
||||
virtual ClipView * createView( TrackView * tv ) = 0;
|
||||
|
||||
inline void selectViewOnCreate( bool select )
|
||||
{
|
||||
m_selectViewOnCreate = select;
|
||||
}
|
||||
|
||||
inline bool getSelectViewOnCreate()
|
||||
{
|
||||
return m_selectViewOnCreate;
|
||||
}
|
||||
|
||||
/// Returns true if and only if a->startPosition() < b->startPosition()
|
||||
static bool comparePosition(const 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;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
242
include/ClipView.h
Normal file
242
include/ClipView.h
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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 <QtCore/QVector>
|
||||
|
||||
#include "ModelView.h"
|
||||
#include "Rubberband.h"
|
||||
#include "Clip.h"
|
||||
|
||||
|
||||
class QMenu;
|
||||
class QContextMenuEvent;
|
||||
|
||||
class DataFile;
|
||||
class TextFloat;
|
||||
class Clip;
|
||||
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 BBClipBackground READ BBClipBackground WRITE setBBClipBackground )
|
||||
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:
|
||||
ClipView( Clip * clip, TrackView * tv );
|
||||
virtual ~ClipView();
|
||||
|
||||
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 BBClipBackground() 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 setBBClipBackground( 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_BBClipBackground;
|
||||
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);
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -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>
|
||||
*
|
||||
@@ -28,26 +28,42 @@
|
||||
#include <QtCore/QMap>
|
||||
#include <QDomElement>
|
||||
|
||||
class QMimeData;
|
||||
|
||||
class JournallingObject;
|
||||
|
||||
class Clipboard
|
||||
namespace Clipboard
|
||||
{
|
||||
public:
|
||||
typedef QMap<QString, QDomElement> Map;
|
||||
|
||||
static void copy( JournallingObject * _object );
|
||||
static const QDomElement * getContent( const QString & _node_name );
|
||||
|
||||
static const char * mimeType()
|
||||
enum class MimeType
|
||||
{
|
||||
return( "application/x-lmms-clipboard" );
|
||||
StringPair,
|
||||
Default
|
||||
};
|
||||
|
||||
// Convenience Methods
|
||||
const QMimeData * getMimeData();
|
||||
bool hasFormat( MimeType mT );
|
||||
|
||||
// Helper methods for String data
|
||||
void copyString( const QString & str, MimeType mT );
|
||||
QString getString( MimeType mT );
|
||||
|
||||
// Helper methods for String Pair data
|
||||
void copyStringPair( const QString & key, const QString & value );
|
||||
QString decodeKey( const QMimeData * mimeData );
|
||||
QString decodeValue( const QMimeData * mimeData );
|
||||
|
||||
inline const char * mimeType( MimeType type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
case MimeType::StringPair:
|
||||
return "application/x-lmms-stringpair";
|
||||
break;
|
||||
case MimeType::Default:
|
||||
default:
|
||||
return "application/x-lmms-clipboard";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static Map content;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
59
include/ColorChooser.h
Normal file
59
include/ColorChooser.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QColorDialog>
|
||||
#include <QKeyEvent>
|
||||
#include <QVector>
|
||||
|
||||
class ColorChooser: public QColorDialog
|
||||
{
|
||||
public:
|
||||
ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {};
|
||||
ColorChooser(QWidget *parent): QColorDialog(parent) {};
|
||||
//! For getting a color without having to initialise a color dialog
|
||||
ColorChooser() {};
|
||||
enum class Palette {Default, Track, Mixer};
|
||||
//! Set global palette via array, checking bounds
|
||||
void setPalette (QVector<QColor>);
|
||||
//! Set global paletter via enum
|
||||
void setPalette (Palette);
|
||||
//! Set palette via enum, return self pointer for chaining
|
||||
ColorChooser* withPalette (Palette);
|
||||
//! Return a certain palette
|
||||
static QVector<QColor> getPalette (Palette);
|
||||
|
||||
protected:
|
||||
//! Forward key events to the parent to prevent stuck notes when the dialog gets focus
|
||||
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);
|
||||
};
|
||||
@@ -32,13 +32,11 @@
|
||||
#include "ComboBoxModel.h"
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
|
||||
|
||||
class LMMS_EXPORT ComboBox : public QWidget, public IntModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComboBox( QWidget* parent = NULL, const QString& name = QString() );
|
||||
ComboBox( QWidget* parent = nullptr, const QString& name = QString() );
|
||||
virtual ~ComboBox();
|
||||
|
||||
ComboBoxModel* model()
|
||||
@@ -51,6 +49,8 @@ public:
|
||||
return castModel<ComboBoxModel>();
|
||||
}
|
||||
|
||||
static constexpr int DEFAULT_HEIGHT = 22;
|
||||
|
||||
public slots:
|
||||
void selectNext();
|
||||
void selectPrevious();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef COMBOBOX_MODEL_H
|
||||
#define COMBOBOX_MODEL_H
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -38,7 +39,7 @@ 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 )
|
||||
@@ -52,6 +53,8 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
|
||||
class LmmsCore;
|
||||
|
||||
|
||||
const QString PROJECTS_PATH = "projects/";
|
||||
const QString TEMPLATE_PATH = "templates/";
|
||||
const QString PRESETS_PATH = "presets/";
|
||||
@@ -50,15 +49,18 @@ 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();
|
||||
}
|
||||
@@ -71,6 +73,12 @@ public:
|
||||
return m_workingDir;
|
||||
}
|
||||
|
||||
void initPortableWorkingDir();
|
||||
|
||||
void initInstalledWorkingDir();
|
||||
|
||||
void initDevelopmentWorkingDir();
|
||||
|
||||
const QString & dataDir() const
|
||||
{
|
||||
return m_dataDir;
|
||||
@@ -213,10 +221,14 @@ public:
|
||||
return m_version;
|
||||
}
|
||||
|
||||
// Used when the configversion attribute is not present in a configuration file.
|
||||
// Returns the appropriate config file version based on the LMMS version.
|
||||
unsigned int legacyConfigVersion();
|
||||
|
||||
QString defaultVersion() const;
|
||||
|
||||
|
||||
static QStringList availabeVstEmbedMethods();
|
||||
static QStringList availableVstEmbedMethods();
|
||||
QString vstEmbedMethod() const;
|
||||
|
||||
// Returns true if the working dir (e.g. ~/lmms) exists on disk.
|
||||
@@ -262,8 +274,12 @@ private:
|
||||
|
||||
void upgrade_1_1_90();
|
||||
void upgrade_1_1_91();
|
||||
void upgrade_1_2_2();
|
||||
void upgrade();
|
||||
|
||||
// List of all upgrade methods
|
||||
static const std::vector<UpgradeMethod> UPGRADE_METHODS;
|
||||
|
||||
QString m_workingDir;
|
||||
QString m_dataDir;
|
||||
QString m_vstDir;
|
||||
@@ -280,6 +296,7 @@ private:
|
||||
QString m_backgroundPicFile;
|
||||
QString m_lmmsRcFile;
|
||||
QString m_version;
|
||||
unsigned int m_configVersion;
|
||||
QStringList m_recentlyOpenedProjects;
|
||||
|
||||
typedef QVector<QPair<QString, QString> > stringPairVector;
|
||||
|
||||
136
include/ControlLayout.h
Normal file
136
include/ControlLayout.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
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;
|
||||
class QLineEdit* m_searchBar;
|
||||
//! name of search bar, must be ASCII sorted before any alpha numerics
|
||||
static constexpr const char* s_searchBarName = "!!searchBar!!";
|
||||
};
|
||||
|
||||
#endif // CONTROLLAYOUT_H
|
||||
@@ -166,7 +166,7 @@ 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;
|
||||
|
||||
@@ -47,7 +47,7 @@ class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObjec
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
ControllerConnection( Controller * _controller );
|
||||
ControllerConnection(Controller * _controller);
|
||||
ControllerConnection( int _controllerId );
|
||||
|
||||
virtual ~ControllerConnection();
|
||||
@@ -98,7 +98,6 @@ public:
|
||||
return classNodeName();
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void deleteConnection();
|
||||
|
||||
@@ -113,7 +112,7 @@ 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;
|
||||
|
||||
134
include/Controls.h
Normal file
134
include/Controls.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
// headers only required for covariance
|
||||
#include "AutomatableModel.h"
|
||||
#include "ComboBoxModel.h"
|
||||
|
||||
|
||||
class QString;
|
||||
class QWidget;
|
||||
class AutomatableModel;
|
||||
|
||||
|
||||
/**
|
||||
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 class AutomatableModelView* modelView() = 0;
|
||||
|
||||
virtual ~Control();
|
||||
};
|
||||
|
||||
|
||||
class KnobControl : public Control
|
||||
{
|
||||
class Knob* m_knob;
|
||||
|
||||
public:
|
||||
void setText(const QString& text) override;
|
||||
QWidget* topWidget() override;
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
FloatModel* model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
|
||||
KnobControl(QWidget* parent = nullptr);
|
||||
~KnobControl() override;
|
||||
};
|
||||
|
||||
|
||||
class ComboControl : public Control
|
||||
{
|
||||
QWidget* m_widget;
|
||||
class ComboBox* m_combo;
|
||||
class QLabel* m_label;
|
||||
|
||||
public:
|
||||
void setText(const QString& text) override;
|
||||
QWidget* topWidget() override { return m_widget; }
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
ComboBoxModel* model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
|
||||
ComboControl(QWidget* parent = nullptr);
|
||||
~ComboControl() override;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
class AutomatableModelView* modelView() override;
|
||||
|
||||
LcdControl(int numDigits, QWidget* parent = nullptr);
|
||||
~LcdControl() override;
|
||||
};
|
||||
|
||||
|
||||
class CheckControl : public Control
|
||||
{
|
||||
QWidget* m_widget;
|
||||
class LedCheckBox* m_checkBox;
|
||||
QLabel* m_label;
|
||||
|
||||
public:
|
||||
void setText(const QString& text) override;
|
||||
QWidget* topWidget() override;
|
||||
|
||||
void setModel(AutomatableModel* model) override;
|
||||
BoolModel *model() override;
|
||||
class AutomatableModelView* modelView() override;
|
||||
|
||||
CheckControl(QWidget* parent = nullptr);
|
||||
~CheckControl() override;
|
||||
};
|
||||
|
||||
|
||||
#endif // CONTROLS_H
|
||||
30
include/CustomTextKnob.h
Normal file
30
include/CustomTextKnob.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Text customizable knob */
|
||||
#ifndef CUSTOM_TEXT_KNOB_H
|
||||
#define CUSTOM_TEXT_KNOB_H
|
||||
|
||||
#include "Knob.h"
|
||||
|
||||
class LMMS_EXPORT CustomTextKnob : public Knob
|
||||
{
|
||||
protected:
|
||||
inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
|
||||
public:
|
||||
CustomTextKnob( knobTypes _knob_num, QWidget * _parent = 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:
|
||||
virtual QString displayValue() const;
|
||||
|
||||
protected:
|
||||
QString m_value_text;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
@@ -27,16 +27,21 @@
|
||||
#ifndef DATA_FILE_H
|
||||
#define DATA_FILE_H
|
||||
|
||||
#include <map>
|
||||
#include <QDomDocument>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ProjectVersion.h"
|
||||
|
||||
class QTextStream;
|
||||
|
||||
class LMMS_EXPORT DataFile : public QDomDocument
|
||||
{
|
||||
MM_OPERATORS
|
||||
|
||||
using UpgradeMethod = void(DataFile::*)();
|
||||
|
||||
public:
|
||||
enum Types
|
||||
{
|
||||
@@ -48,6 +53,7 @@ public:
|
||||
ClipboardData,
|
||||
JournalData,
|
||||
EffectSettings,
|
||||
MidiClip,
|
||||
TypeCount
|
||||
} ;
|
||||
typedef Types Type;
|
||||
@@ -67,7 +73,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 +92,8 @@ public:
|
||||
return m_type;
|
||||
}
|
||||
|
||||
unsigned int legacyFileVersion();
|
||||
|
||||
private:
|
||||
static Type type( const QString& typeName );
|
||||
static QString typeName( Type type );
|
||||
@@ -107,8 +117,21 @@ 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();
|
||||
|
||||
// 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)
|
||||
typedef std::map<QString, std::vector<QString>> ResourcesMap;
|
||||
static const ResourcesMap ELEMENTS_WITH_RESOURCES;
|
||||
|
||||
void upgrade();
|
||||
|
||||
@@ -122,17 +145,13 @@ 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 );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -72,7 +72,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 +85,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;
|
||||
@@ -143,7 +143,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 +156,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;
|
||||
@@ -214,7 +214,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 +227,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;
|
||||
@@ -295,7 +295,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 +308,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;
|
||||
|
||||
63
include/DeprecationHelper.h
Normal file
63
include/DeprecationHelper.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* DeprecationHelper.h - This file contains the declarations of helper functions
|
||||
* which helps centralize the #ifdefs preprocessors regarding deprecation based on Qt versions.
|
||||
* The functions are defined differently based on the callers' Qt versions.
|
||||
*
|
||||
* Copyright (c) 2020 Tien Dat Nguyen <ntd.bk.k56/at/gmail.com>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DEPRECATIONHELPER_H
|
||||
#define DEPRECATIONHELPER_H
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QWheelEvent>
|
||||
|
||||
/**
|
||||
* @brief horizontalAdvance is a backwards-compatible adapter for
|
||||
* QFontMetrics::horizontalAdvance and width functions.
|
||||
* @param metrics
|
||||
* @param text
|
||||
* @return text's horizontal advance based on metrics.
|
||||
*/
|
||||
inline int horizontalAdvance(const QFontMetrics& metrics, const QString& text)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||
return metrics.horizontalAdvance(text);
|
||||
#else
|
||||
return metrics.width(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief position is a backwards-compatible adapter for
|
||||
* QWheelEvent::position and pos functions.
|
||||
* @param wheelEvent
|
||||
* @return the position of wheelEvent
|
||||
*/
|
||||
inline QPoint position(QWheelEvent *wheelEvent)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
return wheelEvent->position().toPoint();
|
||||
#else
|
||||
return wheelEvent->pos();
|
||||
#endif
|
||||
}
|
||||
#endif // DEPRECATIONHELPER_H
|
||||
@@ -84,7 +84,7 @@ 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 )
|
||||
{
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Mixer.h"
|
||||
#include "AudioEngine.h"
|
||||
|
||||
|
||||
class DummyInstrument : public Instrument
|
||||
{
|
||||
public:
|
||||
DummyInstrument( InstrumentTrack * _instrument_track ) :
|
||||
Instrument( _instrument_track, NULL )
|
||||
Instrument( _instrument_track, nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
void playNote( NotePlayHandle *, sampleFrame * buffer ) override
|
||||
{
|
||||
memset( buffer, 0, sizeof( sampleFrame ) *
|
||||
Engine::mixer()->framesPerPeriod() );
|
||||
Engine::audioEngine()->framesPerPeriod() );
|
||||
}
|
||||
|
||||
void saveSettings( QDomDocument &, QDomElement & ) override
|
||||
|
||||
@@ -34,7 +34,7 @@ class DummyPlugin : public Plugin
|
||||
{
|
||||
public:
|
||||
DummyPlugin() :
|
||||
Plugin( NULL, NULL )
|
||||
Plugin( nullptr, nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@
|
||||
#include <QMainWindow>
|
||||
#include <QToolBar>
|
||||
|
||||
static const int Quantizations[] = {
|
||||
1, 2, 4, 8, 16, 32, 64,
|
||||
3, 6, 12, 24, 48, 96, 192
|
||||
};
|
||||
|
||||
|
||||
class QAction;
|
||||
|
||||
class DropToolBar;
|
||||
@@ -58,6 +64,11 @@ protected slots:
|
||||
private slots:
|
||||
/// Called by pressing the space key. Plays or stops.
|
||||
void togglePlayStop();
|
||||
|
||||
/// Called by pressing shift+space. Toggles pause state.
|
||||
void togglePause();
|
||||
|
||||
void toggleMaximize();
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "Engine.h"
|
||||
#include "Mixer.h"
|
||||
#include "AudioEngine.h"
|
||||
#include "AutomatableModel.h"
|
||||
#include "TempoSyncKnobModel.h"
|
||||
#include "MemoryManager.h"
|
||||
@@ -103,8 +103,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
|
||||
@@ -179,9 +179,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 +189,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();
|
||||
|
||||
|
||||
@@ -43,9 +43,10 @@ class EffectRackView : public QWidget, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EffectRackView( EffectChain* model, QWidget* parent = NULL );
|
||||
EffectRackView( EffectChain* model, QWidget* parent = nullptr );
|
||||
virtual ~EffectRackView();
|
||||
|
||||
static constexpr int DEFAULT_WIDTH = 245;
|
||||
|
||||
public slots:
|
||||
void clearViews();
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
return castModel<Effect>();
|
||||
}
|
||||
|
||||
static constexpr int DEFAULT_WIDTH = 215;
|
||||
|
||||
public slots:
|
||||
void editControls();
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
#include <QtCore/QObject>
|
||||
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class AudioEngine;
|
||||
class BBTrackContainer;
|
||||
class DummyTrackContainer;
|
||||
class FxMixer;
|
||||
class ProjectJournal;
|
||||
class Mixer;
|
||||
class ProjectJournal;
|
||||
class Song;
|
||||
class Ladspa2LMMS;
|
||||
|
||||
@@ -62,14 +62,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()
|
||||
@@ -87,16 +87,20 @@ public:
|
||||
return s_projectJournal;
|
||||
}
|
||||
|
||||
static bool ignorePluginBlacklist();
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
static class Lv2Manager * getLv2Manager()
|
||||
{
|
||||
return s_lv2Manager;
|
||||
}
|
||||
#endif
|
||||
|
||||
static Ladspa2LMMS * getLADSPAManager()
|
||||
{
|
||||
return s_ladspaManager;
|
||||
}
|
||||
|
||||
static DummyTrackContainer * dummyTrackContainer()
|
||||
{
|
||||
return s_dummyTC;
|
||||
}
|
||||
|
||||
static float framesPerTick()
|
||||
{
|
||||
return s_framesPerTick;
|
||||
@@ -108,7 +112,7 @@ public:
|
||||
|
||||
static inline LmmsCore * inst()
|
||||
{
|
||||
if( s_instanceOfMe == NULL )
|
||||
if( s_instanceOfMe == nullptr )
|
||||
{
|
||||
s_instanceOfMe = new LmmsCore();
|
||||
}
|
||||
@@ -129,20 +133,22 @@ private:
|
||||
static inline void deleteHelper( T * * ptr )
|
||||
{
|
||||
T * tmp = *ptr;
|
||||
*ptr = NULL;
|
||||
*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 ProjectJournal * s_projectJournal;
|
||||
static DummyTrackContainer * s_dummyTC;
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
static class Lv2Manager* s_lv2Manager;
|
||||
#endif
|
||||
static Ladspa2LMMS * s_ladspaManager;
|
||||
static void* s_dndPluginKey;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
class LMMS_EXPORT ExportFilter : public Plugin
|
||||
{
|
||||
public:
|
||||
ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, NULL ) {}
|
||||
ExportFilter( const Descriptor * _descriptor ) : Plugin( _descriptor, nullptr ) {}
|
||||
virtual ~ExportFilter() {}
|
||||
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
#ifndef FADE_BUTTON_H
|
||||
#define FADE_BUTTON_H
|
||||
|
||||
#include <QtCore/QTime>
|
||||
#include <QAbstractButton>
|
||||
#include <QColor>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
|
||||
class FadeButton : public QAbstractButton
|
||||
@@ -46,17 +46,17 @@ public:
|
||||
|
||||
public slots:
|
||||
void activate();
|
||||
void activateOnce();
|
||||
void noteEnd();
|
||||
|
||||
|
||||
protected:
|
||||
void customEvent( QEvent * ) override;
|
||||
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,8 +66,7 @@ private:
|
||||
QColor m_holdColor;
|
||||
int activeNotes;
|
||||
|
||||
void signalUpdate();
|
||||
QColor fadeToColor(QColor, QColor, QTime, float);
|
||||
QColor fadeToColor(QColor, QColor, QElapsedTimer, float);
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -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,9 +48,10 @@
|
||||
#ifndef FADER_H
|
||||
#define FADER_H
|
||||
|
||||
#include <QtCore/QTime>
|
||||
#include <QWidget>
|
||||
#include <QElapsedTimer>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
@@ -98,7 +99,7 @@ public:
|
||||
|
||||
void setDisplayConversion( bool b )
|
||||
{
|
||||
m_displayConversion = b;
|
||||
m_conversionFactor = b ? 100.0 : 1.0;
|
||||
}
|
||||
|
||||
inline void setHintText( const QString & _txt_before,
|
||||
@@ -130,7 +131,7 @@ private:
|
||||
return height() - ( ( height() - m_knob->height() ) * ( realVal / fRange ) );
|
||||
}
|
||||
|
||||
void setPeak( float fPeak, float &targetPeak, float &persistentPeak, QTime &lastPeakTime );
|
||||
void setPeak( float fPeak, float &targetPeak, float &persistentPeak, QElapsedTimer &lastPeakTimer );
|
||||
int calculateDisplayPeak( float fPeak );
|
||||
|
||||
void updateTextFloat();
|
||||
@@ -144,8 +145,8 @@ private:
|
||||
float m_fMinPeak;
|
||||
float m_fMaxPeak;
|
||||
|
||||
QTime m_lastPeakTime_L;
|
||||
QTime m_lastPeakTime_R;
|
||||
QElapsedTimer m_lastPeakTimer_L;
|
||||
QElapsedTimer m_lastPeakTimer_R;
|
||||
|
||||
static QPixmap * s_back;
|
||||
static QPixmap * s_leds;
|
||||
@@ -154,8 +155,7 @@ private:
|
||||
QPixmap * m_back;
|
||||
QPixmap * m_leds;
|
||||
QPixmap * m_knob;
|
||||
|
||||
bool m_displayConversion;
|
||||
|
||||
bool m_levelsDisplayedInDBFS;
|
||||
|
||||
int m_moveStartPoint;
|
||||
|
||||
@@ -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>
|
||||
*
|
||||
@@ -29,66 +29,63 @@
|
||||
|
||||
|
||||
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;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef FILE_BROWSER_H
|
||||
#define FILE_BROWSER_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QTreeWidget>
|
||||
@@ -48,16 +49,27 @@ 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 );
|
||||
QWidget * parent, bool dirs_as_items = false, bool recurse = false,
|
||||
const QString& userDir = "",
|
||||
const QString& factoryDir = "");
|
||||
|
||||
virtual ~FileBrowser() = default;
|
||||
|
||||
private slots:
|
||||
void reloadTree( void );
|
||||
void expandItems( QTreeWidgetItem * item=NULL, QList<QString> expandedDirs = QList<QString>() );
|
||||
void expandItems( QTreeWidgetItem * item=nullptr, QList<QString> expandedDirs = QList<QString>() );
|
||||
// call with item=NULL to filter the entire tree
|
||||
bool filterItems( const QString & filter, QTreeWidgetItem * item=NULL );
|
||||
bool filterItems( const QString & filter, QTreeWidgetItem * item=nullptr );
|
||||
void giveFocusToFilter();
|
||||
|
||||
private:
|
||||
@@ -69,12 +81,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;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -97,28 +114,39 @@ protected:
|
||||
void mousePressEvent( QMouseEvent * me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * me ) override;
|
||||
void keyPressEvent( QKeyEvent * ke ) override;
|
||||
void keyReleaseEvent( QKeyEvent * ke ) override;
|
||||
void hideEvent( QHideEvent * he ) override;
|
||||
void focusOutEvent( QFocusEvent * fe ) override;
|
||||
|
||||
|
||||
private:
|
||||
//! Start a preview of a file item
|
||||
void previewFileItem(FileItem* file);
|
||||
//! If a preview is playing, stop it.
|
||||
void stopPreview();
|
||||
|
||||
void handleFile( FileItem * fi, InstrumentTrack * it );
|
||||
void openInNewInstrumentTrack( TrackContainer* tc );
|
||||
void openInNewInstrumentTrack( TrackContainer* tc, FileItem* item );
|
||||
|
||||
|
||||
bool m_mousePressed;
|
||||
QPoint m_pressPos;
|
||||
|
||||
//! This should only be accessed or modified when m_pphMutex is held
|
||||
PlayHandle* m_previewPlayHandle;
|
||||
QMutex m_pphMutex;
|
||||
|
||||
FileItem * m_contextMenuItem;
|
||||
QList<QAction*> getContextActions(FileItem* item, bool songEditor);
|
||||
|
||||
|
||||
private slots:
|
||||
void activateListItem( QTreeWidgetItem * item, int column );
|
||||
void openInNewInstrumentTrackBBE( void );
|
||||
void openInNewInstrumentTrackSE( void );
|
||||
void sendToActiveInstrumentTrack( void );
|
||||
void openInNewInstrumentTrack( FileItem* item, bool songEditor );
|
||||
bool openInNewSampleTrack( FileItem* item );
|
||||
void sendToActiveInstrumentTrack( FileItem* item );
|
||||
void updateDirectory( QTreeWidgetItem * item );
|
||||
void openContainingFolder( FileItem* item );
|
||||
|
||||
} ;
|
||||
|
||||
@@ -163,7 +191,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;
|
||||
@@ -218,6 +253,11 @@ public:
|
||||
return( m_handling );
|
||||
}
|
||||
|
||||
inline bool isTrack( void ) const
|
||||
{
|
||||
return m_handling == LoadAsPreset || m_handling == LoadByPlugin;
|
||||
}
|
||||
|
||||
QString extension( void );
|
||||
static QString extension( const QString & file );
|
||||
|
||||
|
||||
@@ -46,8 +46,7 @@ public:
|
||||
const QString &caption = QString(),
|
||||
const QString &directory = QString(),
|
||||
const QString &filter = QString(),
|
||||
QString *selectedFilter = 0,
|
||||
QFileDialog::Options options = 0);
|
||||
QString *selectedFilter = 0);
|
||||
void clearSelection();
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
bool requiresProcessing() const override { return true; }
|
||||
void unmuteForSolo();
|
||||
|
||||
|
||||
std::atomic_int m_dependenciesMet;
|
||||
void incrementDeps();
|
||||
void processed();
|
||||
|
||||
private:
|
||||
void doProcessing() override;
|
||||
};
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
QString nodeName() const override
|
||||
{
|
||||
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
|
||||
@@ -30,9 +30,9 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "Note.h"
|
||||
#include "Pattern.h"
|
||||
#include "MidiClip.h"
|
||||
#include "SerializingObject.h"
|
||||
|
||||
class Groove : public QObject, public SerializingObject
|
||||
@@ -55,8 +55,8 @@ public:
|
||||
* returns 0 to play now on the tick, -1 to not play at all and the new offset
|
||||
* that the note should be shifted if it is to be played later in this tick.
|
||||
*/
|
||||
virtual int isInTick(MidiTime * curStart, fpp_t frames, f_cnt_t offset,
|
||||
Note * n, Pattern * p);
|
||||
virtual int isInTick(TimePos * curStart, fpp_t frames, f_cnt_t offset,
|
||||
Note * n, MidiClip* c);
|
||||
int amount() const {return m_amount;}
|
||||
|
||||
virtual void saveSettings(QDomDocument & doc, QDomElement & element);
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include "AutomatableSlider.h"
|
||||
#include "Groove.h"
|
||||
#include "lmms_basics.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "Note.h"
|
||||
#include "Pattern.h"
|
||||
#include "MidiClip.h"
|
||||
|
||||
/**
|
||||
* A groove thats new
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
|
||||
void init();
|
||||
|
||||
int isInTick(MidiTime * curStart, const fpp_t frames, const f_cnt_t offset, Note * n, Pattern * p);
|
||||
int isInTick(TimePos * curStart, const fpp_t frames, const f_cnt_t offset, Note * n, MidiClip* c);
|
||||
|
||||
inline virtual QString nodeName() const
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ class GroupBox : public QWidget, public BoolModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GroupBox( const QString & _caption, QWidget * _parent = NULL );
|
||||
GroupBox( const QString & _caption, QWidget * _parent = nullptr );
|
||||
virtual ~GroupBox();
|
||||
|
||||
void modelChanged() override;
|
||||
|
||||
@@ -28,15 +28,17 @@
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
class QLabel;
|
||||
|
||||
class AutomationEditorWindow;
|
||||
class BBEditor;
|
||||
class ControllerRackView;
|
||||
class FxMixerView;
|
||||
class GrooveView;
|
||||
class MixerView;
|
||||
class MainWindow;
|
||||
class MicrotunerConfig;
|
||||
class PianoRollWindow;
|
||||
class ProjectNotes;
|
||||
class SongEditorWindow;
|
||||
@@ -49,14 +51,18 @@ public:
|
||||
~GuiApplication();
|
||||
|
||||
static GuiApplication* instance();
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
static QFont getWin32SystemFont();
|
||||
#endif
|
||||
|
||||
MainWindow* mainWindow() { return m_mainWindow; }
|
||||
FxMixerView* fxMixerView() { return m_fxMixerView; }
|
||||
GrooveView* grooveView() { return m_grooveView; }
|
||||
MixerView* mixerView() { return m_mixerView; }
|
||||
SongEditorWindow* songEditor() { return m_songEditor; }
|
||||
BBEditor* getBBEditor() { return m_bbEditor; }
|
||||
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; }
|
||||
|
||||
@@ -70,17 +76,19 @@ private:
|
||||
static GuiApplication* s_instance;
|
||||
|
||||
MainWindow* m_mainWindow;
|
||||
FxMixerView* m_fxMixerView;
|
||||
GrooveView* m_grooveView;
|
||||
MixerView* m_mixerView;
|
||||
SongEditorWindow* m_songEditor;
|
||||
AutomationEditorWindow* m_automationEditor;
|
||||
BBEditor* m_bbEditor;
|
||||
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();
|
||||
|
||||
#endif // GUIAPPLICATION_H
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include "AutomatableSlider.h"
|
||||
#include "Groove.h"
|
||||
#include "lmms_basics.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "Note.h"
|
||||
#include "Pattern.h"
|
||||
#include "MidiClip.h"
|
||||
|
||||
/**
|
||||
* A groove thatjust latter half of the HydrogenSwing algo.
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
|
||||
void init();
|
||||
|
||||
int isInTick(MidiTime * curStart, const fpp_t frames, const f_cnt_t offset, Note * n, Pattern * p);
|
||||
int isInTick(TimePos * curStart, const fpp_t frames, const f_cnt_t offset, Note * n, MidiClip* c);
|
||||
|
||||
inline virtual QString nodeName() const
|
||||
{
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include "AutomatableSlider.h"
|
||||
#include "Groove.h"
|
||||
#include "lmms_basics.h"
|
||||
#include "MidiTime.h"
|
||||
#include "TimePos.h"
|
||||
#include "Note.h"
|
||||
#include "Pattern.h"
|
||||
#include "MidiClip.h"
|
||||
|
||||
/**
|
||||
* A groove that mimics Hydrogen drum machine's swing feature
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
|
||||
void init();
|
||||
|
||||
int isInTick(MidiTime * curStart, const fpp_t frames, const f_cnt_t offset, Note * n, Pattern * p);
|
||||
int isInTick(TimePos * curStart, const fpp_t frames, const f_cnt_t offset, Note * n, MidiClip* c);
|
||||
|
||||
inline virtual QString nodeName() const
|
||||
{
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#ifndef INLINE_AUTOMATION_H
|
||||
#define INLINE_AUTOMATION_H
|
||||
|
||||
#include "AutomationPattern.h"
|
||||
#include "AutomationNode.h"
|
||||
#include "AutomationClip.h"
|
||||
#include "shared_object.h"
|
||||
|
||||
|
||||
@@ -35,15 +36,15 @@ public:
|
||||
InlineAutomation() :
|
||||
FloatModel(),
|
||||
sharedObject(),
|
||||
m_autoPattern( NULL )
|
||||
m_autoClip( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~InlineAutomation()
|
||||
{
|
||||
if( m_autoPattern )
|
||||
if( m_autoClip )
|
||||
{
|
||||
delete m_autoPattern;
|
||||
delete m_autoClip;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,14 +52,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,14 +75,14 @@ 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;
|
||||
}
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
@@ -84,7 +90,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
AutomationPattern * m_autoPattern;
|
||||
AutomationClip * m_autoClip;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#include "lmms_export.h"
|
||||
#include "lmms_basics.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "MidiTime.h"
|
||||
#include "Plugin.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
|
||||
// forward-declarations
|
||||
@@ -68,7 +68,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,7 +105,7 @@ public:
|
||||
|
||||
// sub-classes can re-implement this for receiving all incoming
|
||||
// MIDI-events
|
||||
inline virtual bool handleMidiEvent( const MidiEvent&, const MidiTime& = MidiTime(), f_cnt_t offset = 0 )
|
||||
inline virtual bool handleMidiEvent( const MidiEvent&, const TimePos& = TimePos(), f_cnt_t offset = 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -132,6 +132,9 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
// fade in to prevent clicks
|
||||
void applyFadeIn(sampleFrame * buf, NotePlayHandle * n);
|
||||
|
||||
// instruments may use this to apply a soft fade out at the end of
|
||||
// notes - method does this only if really less or equal
|
||||
// desiredReleaseFrames() frames are left
|
||||
|
||||
@@ -44,7 +44,7 @@ class InstrumentFunctionNoteStackingView : public QWidget, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InstrumentFunctionNoteStackingView( InstrumentFunctionNoteStacking* cc, QWidget* parent = NULL );
|
||||
InstrumentFunctionNoteStackingView( InstrumentFunctionNoteStacking* cc, QWidget* parent = nullptr );
|
||||
virtual ~InstrumentFunctionNoteStackingView();
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class InstrumentFunctionArpeggioView : public QWidget, public ModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InstrumentFunctionArpeggioView( InstrumentFunctionArpeggio* arp, QWidget* parent = NULL );
|
||||
InstrumentFunctionArpeggioView( InstrumentFunctionArpeggio* arp, QWidget* parent = nullptr );
|
||||
virtual ~InstrumentFunctionArpeggioView();
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ private:
|
||||
GroupBox * m_arpGroupBox;
|
||||
ComboBox * m_arpComboBox;
|
||||
Knob * m_arpRangeKnob;
|
||||
Knob * m_arpRepeatsKnob;
|
||||
Knob * m_arpCycleKnob;
|
||||
Knob * m_arpSkipKnob;
|
||||
Knob * m_arpMissKnob;
|
||||
|
||||
@@ -196,6 +196,7 @@ private:
|
||||
BoolModel m_arpEnabledModel;
|
||||
ComboBoxModel m_arpModel;
|
||||
FloatModel m_arpRangeModel;
|
||||
FloatModel m_arpRepeatsModel;
|
||||
FloatModel m_arpCycleModel;
|
||||
FloatModel m_arpSkipModel;
|
||||
FloatModel m_arpMissModel;
|
||||
|
||||
@@ -64,26 +64,4 @@ private:
|
||||
LcdSpinBox* m_baseVelocitySpinBox;
|
||||
};
|
||||
|
||||
class InstrumentMiscView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InstrumentMiscView( InstrumentTrack *it, QWidget* parent );
|
||||
~InstrumentMiscView();
|
||||
|
||||
GroupBox * pitchGroupBox()
|
||||
{
|
||||
return m_pitchGroupBox;
|
||||
}
|
||||
|
||||
GroupBox * grooveGroupBox()
|
||||
{
|
||||
return m_grooveGroupBox;
|
||||
}
|
||||
|
||||
private:
|
||||
GroupBox * m_pitchGroupBox;
|
||||
GroupBox * m_grooveGroupBox;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
67
include/InstrumentMiscView.h
Normal file
67
include/InstrumentMiscView.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
class ComboBox;
|
||||
class GroupBox;
|
||||
class InstrumentTrack;
|
||||
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;}
|
||||
|
||||
GroupBox *grooveGroupBox() {return m_grooveGroupBox;}
|
||||
|
||||
private:
|
||||
GroupBox *m_pitchGroupBox;
|
||||
GroupBox *m_microtunerGroupBox;
|
||||
|
||||
ComboBox *m_scaleCombo;
|
||||
ComboBox *m_keymapCombo;
|
||||
|
||||
LedCheckBox *m_rangeImportCheckbox;
|
||||
|
||||
GroupBox * m_grooveGroupBox;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
FloatModel m_filterCutModel;
|
||||
FloatModel m_filterResModel;
|
||||
|
||||
static const QString targetNames[InstrumentSoundShaping::NumTargets][3];
|
||||
static const char *const targetNames[InstrumentSoundShaping::NumTargets][3];
|
||||
|
||||
|
||||
friend class InstrumentSoundShapingView;
|
||||
|
||||
@@ -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>
|
||||
*
|
||||
@@ -28,42 +28,22 @@
|
||||
|
||||
#include "AudioPort.h"
|
||||
#include "Groove.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"
|
||||
#include "TrackView.h"
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor
|
||||
@@ -81,8 +61,8 @@ public:
|
||||
|
||||
MidiEvent applyMasterKey( const MidiEvent& event );
|
||||
|
||||
void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override;
|
||||
void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) override;
|
||||
void processInEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 ) override;
|
||||
void processOutEvent( const MidiEvent& event, const TimePos& time = TimePos(), f_cnt_t offset = 0 ) override;
|
||||
// silence all running notes played by this track
|
||||
void silenceAllNotes( bool removeIPH = false );
|
||||
|
||||
@@ -133,13 +113,13 @@ 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 ) override;
|
||||
virtual 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
|
||||
TrackView * createView( TrackContainerView* tcv ) override;
|
||||
|
||||
// create new track-content-object = pattern
|
||||
TrackContentObject * createTCO( const MidiTime & _pos ) override;
|
||||
// create new track-content-object = clip
|
||||
Clip* createClip(const TimePos & pos) override;
|
||||
|
||||
|
||||
// called by track
|
||||
@@ -177,13 +157,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();
|
||||
@@ -212,13 +212,21 @@ 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();
|
||||
@@ -228,22 +236,26 @@ signals:
|
||||
void newNote();
|
||||
void endNote();
|
||||
|
||||
|
||||
protected:
|
||||
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];
|
||||
@@ -258,7 +270,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;
|
||||
|
||||
@@ -274,11 +291,10 @@ private:
|
||||
|
||||
FloatModel m_pitchModel;
|
||||
IntModel m_pitchRangeModel;
|
||||
IntModel m_effectChannelModel;
|
||||
IntModel m_mixerChannelModel;
|
||||
BoolModel m_useMasterPitchModel;
|
||||
BoolModel m_useGrooveModel;
|
||||
|
||||
|
||||
Instrument * m_instrument;
|
||||
InstrumentSoundShaping m_soundShaping;
|
||||
InstrumentFunctionArpeggio m_arpeggio;
|
||||
@@ -286,204 +302,20 @@ private:
|
||||
|
||||
Piano m_piano;
|
||||
|
||||
Microtuner m_microtuner;
|
||||
|
||||
std::unique_ptr<BoolModel> m_midiCCEnable;
|
||||
std::unique_ptr<FloatModel> m_midiCCModel[MidiControllerCount];
|
||||
|
||||
|
||||
friend class InstrumentTrackView;
|
||||
friend class InstrumentTrackWindow;
|
||||
friend class NotePlayHandle;
|
||||
friend class InstrumentMiscView;
|
||||
friend class MidiCCRackView;
|
||||
|
||||
private slots:
|
||||
void updateGroove();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
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 ) override;
|
||||
|
||||
|
||||
protected:
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
|
||||
|
||||
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
|
||||
void closeEvent( QCloseEvent * _ce ) override;
|
||||
void focusInEvent( QFocusEvent * _fe ) override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
|
||||
protected slots:
|
||||
void saveSettingsBtnClicked();
|
||||
void viewNextInstrument();
|
||||
void viewPrevInstrument();
|
||||
|
||||
private:
|
||||
void modelChanged() override;
|
||||
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;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
118
include/InstrumentTrackView.h
Normal file
118
include/InstrumentTrackView.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "MidiCCRackView.h"
|
||||
|
||||
|
||||
class InstrumentTrackWindow;
|
||||
class Knob;
|
||||
class TrackContainerView;
|
||||
class TrackLabelButton;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
161
include/InstrumentTrackWindow.h
Normal file
161
include/InstrumentTrackWindow.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* InstrumentTrackWindow.h - declaration of InstrumentTrackWindow 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_WINDOW_H
|
||||
#define INSTRUMENT_TRACK_WINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ModelView.h"
|
||||
#include "SerializingObject.h"
|
||||
|
||||
|
||||
class EffectRackView;
|
||||
class MixerLineLcdSpinBox;
|
||||
class InstrumentFunctionArpeggioView;
|
||||
class InstrumentFunctionNoteStackingView;
|
||||
class InstrumentMidiIOView;
|
||||
class InstrumentMiscView;
|
||||
class InstrumentSoundShapingView;
|
||||
class InstrumentTrack;
|
||||
class InstrumentTrackShapingView;
|
||||
class InstrumentTrackView;
|
||||
class Knob;
|
||||
class LcdSpinBox;
|
||||
class LeftRightNav;
|
||||
class PianoView;
|
||||
class PluginView;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QWidget;
|
||||
class TabWidget;
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
|
||||
|
||||
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
|
||||
void closeEvent( QCloseEvent * _ce ) override;
|
||||
void focusInEvent( QFocusEvent * _fe ) override;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _this ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
|
||||
protected slots:
|
||||
void saveSettingsBtnClicked();
|
||||
void viewNextInstrument();
|
||||
void viewPrevInstrument();
|
||||
|
||||
private:
|
||||
void modelChanged() override;
|
||||
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;
|
||||
MixerLineLcdSpinBox * m_mixerChannelNumber;
|
||||
|
||||
|
||||
|
||||
// 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;
|
||||
friend class InstrumentTrackView;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,18 +48,24 @@ std::wstring toWString(const std::string& s)
|
||||
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#include <io.h>
|
||||
#define F_OPEN_UTF8(a, b) _wfopen(toWString(a).data(), L##b)
|
||||
#else
|
||||
#ifdef LMMS_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#define F_OPEN_UTF8(a, b) fopen((a).data(), b)
|
||||
#endif
|
||||
|
||||
FILE* F_OPEN_UTF8(std::string const& fname, const char* mode){
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
return _wfopen(toWString(fname).data(), toWString(mode).data());
|
||||
#else
|
||||
return fopen(fname.data(), mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int fileToDescriptor(FILE* f, bool closeFile = true)
|
||||
{
|
||||
int fh;
|
||||
if (f == NULL) {return -1;}
|
||||
if (f == nullptr) {return -1;}
|
||||
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
fh = _dup(_fileno(f));
|
||||
|
||||
79
include/Keymap.h
Normal file
79
include/Keymap.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Keymap.h - holds information about a key mapping
|
||||
*
|
||||
* 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 KEYMAP_H
|
||||
#define KEYMAP_H
|
||||
|
||||
#include <vector>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "Note.h"
|
||||
#include "SerializingObject.h"
|
||||
|
||||
class Keymap : public QObject, public SerializingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Keymap();
|
||||
Keymap(
|
||||
QString description,
|
||||
std::vector<int> newMap,
|
||||
int newFirst,
|
||||
int newLast,
|
||||
int newMiddle,
|
||||
int newBaseKey,
|
||||
float newBaseFreq
|
||||
);
|
||||
|
||||
QString getDescription() const;
|
||||
void setDescription(QString description);
|
||||
|
||||
int getMiddleKey() const {return m_middleKey;}
|
||||
int getFirstKey() const {return m_firstKey;}
|
||||
int getLastKey() const {return m_lastKey;}
|
||||
int getBaseKey() const {return m_baseKey;}
|
||||
float getBaseFreq() const {return m_baseFreq;}
|
||||
|
||||
std::size_t getSize() const {return m_map.size();}
|
||||
int getDegree(int key) const;
|
||||
int getOctave(int key) const;
|
||||
const std::vector<int> &getMap() const {return m_map;}
|
||||
|
||||
void saveSettings(QDomDocument &doc, QDomElement &element) override;
|
||||
void loadSettings(const QDomElement &element) override;
|
||||
inline QString nodeName() const override {return "keymap";}
|
||||
|
||||
private:
|
||||
QString m_description; //!< name or description of the keymap
|
||||
|
||||
std::vector<int> m_map; //!< key to scale degree mapping
|
||||
int m_firstKey; //!< first key that will be mapped
|
||||
int m_lastKey; //!< last key that will be mapped
|
||||
int m_middleKey; //!< first line of the map refers to this key
|
||||
int m_baseKey; //!< key which is assigned the reference "base note"
|
||||
float m_baseFreq; //!< frequency of the base note (usually A4 @440 Hz)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -26,8 +26,11 @@
|
||||
#ifndef KNOB_H
|
||||
#define KNOB_H
|
||||
|
||||
#include <memory>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
@@ -41,6 +44,7 @@ enum knobTypes
|
||||
} ;
|
||||
|
||||
|
||||
void convertPixmapToGrayScale(QPixmap &pixMap);
|
||||
|
||||
class LMMS_EXPORT Knob : public QWidget, public FloatModelView
|
||||
{
|
||||
@@ -58,8 +62,12 @@ class LMMS_EXPORT Knob : public QWidget, public FloatModelView
|
||||
// Unfortunately, the gradient syntax doesn't create our gradient
|
||||
// correctly so we need to do this:
|
||||
Q_PROPERTY(QColor outerColor READ outerColor WRITE setOuterColor)
|
||||
Q_PROPERTY(QColor lineColor READ lineColor WRITE setlineColor)
|
||||
Q_PROPERTY(QColor arcColor READ arcColor WRITE setarcColor)
|
||||
|
||||
Q_PROPERTY(QColor lineActiveColor MEMBER m_lineActiveColor)
|
||||
Q_PROPERTY(QColor lineInactiveColor MEMBER m_lineInactiveColor)
|
||||
Q_PROPERTY(QColor arcActiveColor MEMBER m_arcActiveColor)
|
||||
Q_PROPERTY(QColor arcInactiveColor MEMBER m_arcInactiveColor)
|
||||
|
||||
mapPropertyFromModel(bool,isVolumeKnob,setVolumeKnob,m_volumeKnob);
|
||||
mapPropertyFromModel(float,volumeRatio,setVolumeRatio,m_volumeRatio);
|
||||
|
||||
@@ -71,10 +79,9 @@ class LMMS_EXPORT Knob : public QWidget, public FloatModelView
|
||||
void onKnobNumUpdated(); //!< to be called when you updated @a m_knobNum
|
||||
|
||||
public:
|
||||
Knob( knobTypes _knob_num, QWidget * _parent = NULL, const QString & _name = QString() );
|
||||
Knob( QWidget * _parent = NULL, const QString & _name = QString() ); //!< default ctor
|
||||
Knob( knobTypes _knob_num, QWidget * _parent = nullptr, const QString & _name = QString() );
|
||||
Knob( QWidget * _parent = nullptr, const QString & _name = QString() ); //!< default ctor
|
||||
Knob( const Knob& other ) = delete;
|
||||
virtual ~Knob();
|
||||
|
||||
// TODO: remove
|
||||
inline void setHintText( const QString & _txt_before,
|
||||
@@ -84,6 +91,7 @@ public:
|
||||
setUnit( _txt_after );
|
||||
}
|
||||
void setLabel( const QString & txt );
|
||||
void setHtmlLabel( const QString &htmltxt );
|
||||
|
||||
void setTotalAngle( float angle );
|
||||
|
||||
@@ -108,10 +116,6 @@ public:
|
||||
|
||||
QColor outerColor() const;
|
||||
void setOuterColor( const QColor & c );
|
||||
QColor lineColor() const;
|
||||
void setlineColor( const QColor & c );
|
||||
QColor arcColor() const;
|
||||
void setarcColor( const QColor & c );
|
||||
|
||||
QColor textColor() const;
|
||||
void setTextColor( const QColor & c );
|
||||
@@ -134,6 +138,7 @@ protected:
|
||||
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
|
||||
void paintEvent( QPaintEvent * _me ) override;
|
||||
void wheelEvent( QWheelEvent * _me ) override;
|
||||
void changeEvent(QEvent * ev) override;
|
||||
|
||||
virtual float getValue( const QPoint & _p );
|
||||
|
||||
@@ -143,7 +148,7 @@ private slots:
|
||||
void toggleScale();
|
||||
|
||||
private:
|
||||
QString displayValue() const;
|
||||
virtual QString displayValue() const;
|
||||
|
||||
void doConnections() override;
|
||||
|
||||
@@ -168,13 +173,14 @@ private:
|
||||
static TextFloat * s_textFloat;
|
||||
|
||||
QString m_label;
|
||||
bool m_isHtmlLabel;
|
||||
QTextDocument* m_tdRenderer;
|
||||
|
||||
QPixmap * m_knobPixmap;
|
||||
std::unique_ptr<QPixmap> m_knobPixmap;
|
||||
BoolModel m_volumeKnob;
|
||||
FloatModel m_volumeRatio;
|
||||
|
||||
QPoint m_mouseOffset;
|
||||
QPoint m_origMousePos;
|
||||
QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent
|
||||
float m_leftOver;
|
||||
bool m_buttonPressed;
|
||||
|
||||
@@ -188,8 +194,11 @@ private:
|
||||
float m_outerRadius;
|
||||
float m_lineWidth;
|
||||
QColor m_outerColor;
|
||||
QColor m_lineColor; //!< unused yet
|
||||
QColor m_arcColor; //!< unused yet
|
||||
|
||||
QColor m_lineActiveColor;
|
||||
QColor m_lineInactiveColor;
|
||||
QColor m_arcActiveColor;
|
||||
QColor m_arcInactiveColor;
|
||||
|
||||
QColor m_textColor;
|
||||
|
||||
|
||||
83
include/LcdFloatSpinBox.h
Normal file
83
include/LcdFloatSpinBox.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* LcdFloatSpinBox.h - class LcdFloatSpinBox (LcdSpinBox for floats)
|
||||
*
|
||||
* 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 LCD_FLOATSPINBOX_H
|
||||
#define LCD_FLOATSPINBOX_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "LcdWidget.h"
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
|
||||
class LMMS_EXPORT LcdFloatSpinBox : public QWidget, public FloatModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LcdFloatSpinBox(int numWhole, int numFrac, const QString& name = QString(), QWidget* parent = nullptr);
|
||||
LcdFloatSpinBox(int numWhole, int numFrac, const QString& style, const QString& name, QWidget* parent = nullptr);
|
||||
|
||||
void modelChanged() override
|
||||
{
|
||||
ModelView::modelChanged();
|
||||
update();
|
||||
}
|
||||
|
||||
void setLabel(const QString &label) { m_label = label; }
|
||||
|
||||
public slots:
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *me) override;
|
||||
void mousePressEvent(QMouseEvent *me) override;
|
||||
void mouseMoveEvent(QMouseEvent *me) override;
|
||||
void mouseReleaseEvent(QMouseEvent *me) override;
|
||||
void wheelEvent(QWheelEvent *we) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *me) override;
|
||||
void paintEvent(QPaintEvent *pe) override;
|
||||
|
||||
private:
|
||||
void layoutSetup(const QString &style = QString("19green"));
|
||||
void enterValue();
|
||||
float getStep() const;
|
||||
|
||||
LcdWidget m_wholeDisplay;
|
||||
LcdWidget m_fractionDisplay;
|
||||
bool m_mouseMoving;
|
||||
bool m_intStep;
|
||||
QPoint m_origMousePos;
|
||||
int m_displayOffset;
|
||||
QString m_label;
|
||||
|
||||
signals:
|
||||
void manualChange();
|
||||
|
||||
};
|
||||
|
||||
using LcdFloatSpinBoxModel = FloatModel;
|
||||
|
||||
#endif
|
||||
@@ -73,8 +73,9 @@ protected:
|
||||
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
|
||||
|
||||
private:
|
||||
float m_remainder; //!< floating offset of spinbox in [-0.5, 0.5]
|
||||
bool m_mouseMoving;
|
||||
QPoint m_origMousePos;
|
||||
QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent
|
||||
int m_displayOffset;
|
||||
void enterValue();
|
||||
|
||||
|
||||
@@ -40,9 +40,10 @@ class LMMS_EXPORT LcdWidget : public QWidget
|
||||
Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor )
|
||||
|
||||
public:
|
||||
LcdWidget( QWidget* parent, const QString& name = QString() );
|
||||
LcdWidget( int numDigits, QWidget* parent, const QString& name = QString() );
|
||||
LcdWidget( int numDigits, const QString& style, QWidget* parent, const QString& name = QString() );
|
||||
explicit LcdWidget(QWidget* parent, const QString& name = QString(), bool leadingZero = false);
|
||||
LcdWidget(int numDigits, QWidget* parent, const QString& name = QString(), bool leadingZero = false);
|
||||
LcdWidget(int numDigits, const QString& style, QWidget* parent, const QString& name = QString(),
|
||||
bool leadingZero = false);
|
||||
|
||||
virtual ~LcdWidget();
|
||||
|
||||
@@ -66,6 +67,15 @@ public:
|
||||
QColor textShadowColor() const;
|
||||
void setTextShadowColor( const QColor & c );
|
||||
|
||||
int cellHeight() const { return m_cellHeight; }
|
||||
|
||||
void setSeamless(bool left, bool right)
|
||||
{
|
||||
m_seamlessLeft = left;
|
||||
m_seamlessRight = right;
|
||||
updateSize();
|
||||
}
|
||||
|
||||
public slots:
|
||||
virtual void setMarginWidth( int width );
|
||||
|
||||
@@ -75,11 +85,6 @@ protected:
|
||||
|
||||
virtual void updateSize();
|
||||
|
||||
int cellHeight() const
|
||||
{
|
||||
return m_cellHeight;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -99,9 +104,12 @@ private:
|
||||
int m_cellHeight;
|
||||
int m_numDigits;
|
||||
int m_marginWidth;
|
||||
bool m_seamlessLeft;
|
||||
bool m_seamlessRight;
|
||||
bool m_leadingZero;
|
||||
|
||||
void initUi( const QString& name, const QString &style = QString("19green") ); //!< to be called by ctors
|
||||
void initUi( const QString& name, const QString &style ); //!< to be called by ctors
|
||||
|
||||
} ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ class LeftRightNav : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LeftRightNav(QWidget *parent=NULL);
|
||||
LeftRightNav(QWidget *parent=nullptr);
|
||||
PixmapButton* getLeftBtn();
|
||||
PixmapButton* getRightBtn();
|
||||
void setShortcuts(const QKeySequence &leftShortcut=Qt::Key_Minus, const QKeySequence &rightShortcut=Qt::Key_Plus);
|
||||
|
||||
107
include/LinkedModelGroupViews.h
Normal file
107
include/LinkedModelGroupViews.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* LinkedModelGroupViews.h - view for groups of linkable models
|
||||
*
|
||||
* 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 LINKEDMODELGROUPVIEWS_H
|
||||
#define LINKEDMODELGROUPVIEWS_H
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
/**
|
||||
@file LinkedModelGroupViews.h
|
||||
See Lv2ViewBase.h for example usage
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
View for a representative processor
|
||||
|
||||
Features:
|
||||
* Remove button for removable models
|
||||
* Simple handling of adding, removing and model changing
|
||||
|
||||
@note Neither this class, nor any inheriting classes, shall inherit
|
||||
ModelView. The "view" in the name is just for consistency
|
||||
with LinkedModelGroupsView.
|
||||
*/
|
||||
class LinkedModelGroupView : public QWidget
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@param colNum numbers of columns for the controls
|
||||
(link LEDs not counted)
|
||||
*/
|
||||
LinkedModelGroupView(QWidget *parent, class LinkedModelGroup* model,
|
||||
std::size_t colNum);
|
||||
~LinkedModelGroupView();
|
||||
|
||||
//! Reconnect models if model changed
|
||||
void modelChanged(class LinkedModelGroup *linkedModelGroup);
|
||||
|
||||
protected:
|
||||
//! Add a control to this widget
|
||||
//! @warning This widget will own this control, do not free it
|
||||
void addControl(class Control *ctrl, const std::string &id,
|
||||
const std::string& display, bool removable);
|
||||
|
||||
void removeControl(const QString &key);
|
||||
|
||||
void removeFocusFromSearchBar();
|
||||
|
||||
private:
|
||||
class LinkedModelGroup* m_model;
|
||||
|
||||
//! column number in surrounding grid in LinkedModelGroupsView
|
||||
std::size_t m_colNum;
|
||||
class ControlLayout* m_layout;
|
||||
std::map<std::string, std::unique_ptr<class Control>> m_widgets;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Container class for one LinkedModelGroupView
|
||||
|
||||
@note It's intended this class does not inherit from ModelView.
|
||||
Inheriting classes need to do that, see e.g. Lv2Instrument.h
|
||||
*/
|
||||
class LinkedModelGroupsView
|
||||
{
|
||||
protected:
|
||||
~LinkedModelGroupsView() = default;
|
||||
|
||||
//! Reconnect models if model changed; to be called by child virtuals
|
||||
void modelChanged(class LinkedModelGroups* ctrlBase);
|
||||
|
||||
private:
|
||||
//! The base class must return the addressed group view,
|
||||
//! which has the same value as "this"
|
||||
virtual LinkedModelGroupView* getGroupView() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // LINKEDMODELGROUPVIEWS_H
|
||||
175
include/LinkedModelGroups.h
Normal file
175
include/LinkedModelGroups.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* LinkedModelGroups.h - base classes for groups of linked models
|
||||
*
|
||||
* 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 LINKEDMODELGROUPS_H
|
||||
#define LINKEDMODELGROUPS_H
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
/**
|
||||
@file LinkedModelGroups.h
|
||||
See Lv2ControlBase.h and Lv2Proc.h for example usage
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Base class for a group of linked models
|
||||
|
||||
See the LinkedModelGroup class for explanations
|
||||
|
||||
Features:
|
||||
* Models are stored by their QObject::objectName
|
||||
* Models are linked automatically
|
||||
*/
|
||||
class LinkedModelGroup : public Model
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/*
|
||||
Initialization
|
||||
*/
|
||||
//! @param parent model of the LinkedModelGroups class
|
||||
LinkedModelGroup(Model* parent) : Model(parent) {}
|
||||
|
||||
/*
|
||||
Linking (initially only)
|
||||
*/
|
||||
void linkControls(LinkedModelGroup *other);
|
||||
|
||||
/*
|
||||
Models
|
||||
*/
|
||||
struct ModelInfo
|
||||
{
|
||||
QString m_name;
|
||||
class AutomatableModel* m_model;
|
||||
ModelInfo() { /* hopefully no one will use this */ } // TODO: remove?
|
||||
ModelInfo(const QString& name, AutomatableModel* model)
|
||||
: m_name(name), m_model(model) {}
|
||||
};
|
||||
|
||||
// TODO: refactor those 2
|
||||
template<class Functor>
|
||||
void foreach_model(const Functor& ftor)
|
||||
{
|
||||
for (auto itr = m_models.begin(); itr != m_models.end(); ++itr)
|
||||
{
|
||||
ftor(itr->first, itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Functor>
|
||||
void foreach_model(const Functor& ftor) const
|
||||
{
|
||||
for (auto itr = m_models.cbegin(); itr != m_models.cend(); ++itr)
|
||||
{
|
||||
ftor(itr->first, itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t modelNum() const { return m_models.size(); }
|
||||
bool containsModel(const QString& name) const;
|
||||
void removeControl(AutomatableModel *);
|
||||
|
||||
/*
|
||||
Load/Save
|
||||
*/
|
||||
void saveValues(class QDomDocument& doc, class QDomElement& that);
|
||||
void loadValues(const class QDomElement& that);
|
||||
|
||||
signals:
|
||||
// NOTE: when separating core from UI, this will need to be removed
|
||||
// (who would kno if the client is Qt, i.e. it may not have slots at all)
|
||||
// In this case you'd e.g. send the UI something like
|
||||
// "/added <model meta info>"
|
||||
void modelAdded(AutomatableModel* added);
|
||||
void modelRemoved(AutomatableModel* removed);
|
||||
|
||||
public:
|
||||
AutomatableModel* getModel(const std::string& s)
|
||||
{
|
||||
auto itr = m_models.find(s);
|
||||
return (itr == m_models.end()) ? nullptr : itr->second.m_model;
|
||||
}
|
||||
|
||||
//! Register a further model
|
||||
void addModel(class AutomatableModel* model, const QString& name);
|
||||
//! Unregister a model, return true if a model was erased
|
||||
bool eraseModel(const QString& name);
|
||||
|
||||
//! Remove all models
|
||||
void clearModels();
|
||||
|
||||
private:
|
||||
//! models for the controls
|
||||
std::map<std::string, ModelInfo> m_models;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Container for a group of linked models
|
||||
|
||||
Each group contains the same models and model types. The models are
|
||||
numbered, and equal numbered models are associated and always linked.
|
||||
|
||||
A typical application are two mono plugins making a stereo plugin.
|
||||
|
||||
@note Though this class can contain multiple model groups, a corresponding
|
||||
view ("LinkedModelGroupViews") will only display one group, as they all have
|
||||
the same values
|
||||
|
||||
@note Though called "container", this class does not contain, but only
|
||||
know the single groups. The inheriting classes are responsible for storage.
|
||||
*/
|
||||
class LinkedModelGroups
|
||||
{
|
||||
public:
|
||||
virtual ~LinkedModelGroups();
|
||||
|
||||
void linkAllModels();
|
||||
|
||||
/*
|
||||
Load/Save
|
||||
*/
|
||||
void saveSettings(class QDomDocument& doc, class QDomElement& that);
|
||||
void loadSettings(const class QDomElement& that);
|
||||
|
||||
/*
|
||||
General
|
||||
*/
|
||||
//! Derived classes must return the group with index @p idx,
|
||||
//! or nullptr if @p is out of range
|
||||
virtual LinkedModelGroup* getGroup(std::size_t idx) = 0;
|
||||
//! @see getGroup
|
||||
virtual const LinkedModelGroup* getGroup(std::size_t idx) const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // LINKEDMODELGROUPS_H
|
||||
86
include/LocklessRingBuffer.h
Normal file
86
include/LocklessRingBuffer.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* LocklessRingBuffer.h - LMMS wrapper for a lockless ringbuffer library
|
||||
*
|
||||
* Copyright (c) 2019 Martin Pavelek <he29/dot/HS/at/gmail/dot/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 LOCKLESSRINGBUFFER_H
|
||||
#define LOCKLESSRINGBUFFER_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h"
|
||||
|
||||
|
||||
//! A convenience layer for a realtime-safe and thread-safe multi-reader ringbuffer
|
||||
template <class T>
|
||||
class LocklessRingBuffer
|
||||
{
|
||||
template<class _T>
|
||||
friend class LocklessRingBufferReader;
|
||||
public:
|
||||
LocklessRingBuffer(std::size_t sz) : m_buffer(sz)
|
||||
{
|
||||
m_buffer.touch(); // reserve storage space before realtime operation starts
|
||||
}
|
||||
~LocklessRingBuffer() {};
|
||||
|
||||
std::size_t capacity() const {return m_buffer.maximum_eventual_write_space();}
|
||||
std::size_t free() const {return m_buffer.write_space();}
|
||||
void wakeAll() {m_notifier.wakeAll();}
|
||||
std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false)
|
||||
{
|
||||
std::size_t written = LocklessRingBuffer<T>::m_buffer.write(src, cnt);
|
||||
// Let all waiting readers know new data are available.
|
||||
if (notify) {LocklessRingBuffer<T>::m_notifier.wakeAll();}
|
||||
return written;
|
||||
}
|
||||
|
||||
protected:
|
||||
ringbuffer_t<T> m_buffer;
|
||||
QWaitCondition m_notifier;
|
||||
};
|
||||
|
||||
|
||||
//! Wrapper for lockless ringbuffer reader
|
||||
template <class T>
|
||||
class LocklessRingBufferReader : public ringbuffer_reader_t<T>
|
||||
{
|
||||
public:
|
||||
LocklessRingBufferReader(LocklessRingBuffer<T> &rb) :
|
||||
ringbuffer_reader_t<T>(rb.m_buffer),
|
||||
m_notifier(&rb.m_notifier) {};
|
||||
|
||||
bool empty() const {return !this->read_space();}
|
||||
void waitForData()
|
||||
{
|
||||
QMutex useless_lock;
|
||||
useless_lock.lock();
|
||||
m_notifier->wait(&useless_lock);
|
||||
useless_lock.unlock();
|
||||
}
|
||||
private:
|
||||
QWaitCondition *m_notifier;
|
||||
};
|
||||
|
||||
#endif //LOCKLESSRINGBUFFER_H
|
||||
67
include/Lv2Basics.h
Normal file
67
include/Lv2Basics.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Lv2Basics.h - basic Lv2 utils
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV2BASICS_H
|
||||
#define LV2BASICS_H
|
||||
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
#include <memory>
|
||||
#include <QString>
|
||||
#include <string>
|
||||
|
||||
struct LilvNodeDeleter
|
||||
{
|
||||
void operator()(LilvNode* n) { lilv_node_free(n); }
|
||||
};
|
||||
|
||||
struct LilvNodesDeleter
|
||||
{
|
||||
void operator()(LilvNodes* n) { lilv_nodes_free(n); }
|
||||
};
|
||||
|
||||
using AutoLilvNode = std::unique_ptr<LilvNode, LilvNodeDeleter>;
|
||||
using AutoLilvNodes = std::unique_ptr<LilvNodes, LilvNodesDeleter>;
|
||||
|
||||
/**
|
||||
Return QString from a plugin's node, everything will be freed automatically
|
||||
@param plug The plugin where the node is
|
||||
@param getFunc The function to return the node from the plugin
|
||||
*/
|
||||
QString qStringFromPluginNode(const LilvPlugin* plug,
|
||||
LilvNode * (*getFunc)(const LilvPlugin*));
|
||||
|
||||
//! Return port name as QString, everything will be freed automatically
|
||||
QString qStringFromPortName(const LilvPlugin* plug, const LilvPort* port);
|
||||
|
||||
//! Return port name as std::string, everything will be freed automatically
|
||||
std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port);
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
#endif // LV2BASICS_H
|
||||
158
include/Lv2ControlBase.h
Normal file
158
include/Lv2ControlBase.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Lv2ControlBase.h - Lv2 control base class
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV2_CONTROL_BASE_H
|
||||
#define LV2_CONTROL_BASE_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
#include "DataFile.h"
|
||||
#include "LinkedModelGroups.h"
|
||||
#include "lmms_export.h"
|
||||
#include "Plugin.h"
|
||||
|
||||
class Lv2Proc;
|
||||
class PluginIssue;
|
||||
|
||||
/**
|
||||
Common base class for Lv2 plugins
|
||||
|
||||
This class contains a vector of Lv2Proc, usually 1 (for stereo plugins) or
|
||||
2 (for mono plugins). Most of the logic is done there, this class primarily
|
||||
forwards work to the Lv2Proc and collects the results.
|
||||
|
||||
This class provides everything Lv2 plugins have in common. It's not
|
||||
named Lv2Plugin, because
|
||||
* it does not inherit Instrument
|
||||
* the Plugin subclass Effect does not inherit this class
|
||||
|
||||
This class would usually be a Model subclass. However, Qt doesn't allow
|
||||
this:
|
||||
* inheriting only from Model will cause diamond inheritance for QObject,
|
||||
which will cause errors with Q_OBJECT
|
||||
* making this a direct subclass of Instrument resp. EffectControls would
|
||||
require CRTP, which would make this class a template class, which would
|
||||
conflict with Q_OBJECT
|
||||
|
||||
The consequence is that this class can neither inherit QObject or Model, nor
|
||||
Instrument or EffectControls, which means in fact:
|
||||
* this class contains no signals or slots, but it offers stubs for slots
|
||||
that shall be called by child classes
|
||||
* this class can not override virtuals of Instrument or EffectControls, so
|
||||
it will offer functions that must be called by virtuals in its child class
|
||||
*/
|
||||
class LMMS_EXPORT Lv2ControlBase : public LinkedModelGroups
|
||||
{
|
||||
public:
|
||||
static Plugin::PluginTypes check(const LilvPlugin* m_plugin,
|
||||
std::vector<PluginIssue> &issues);
|
||||
|
||||
const LilvPlugin* getPlugin() const { return m_plugin; }
|
||||
|
||||
Lv2Proc *control(std::size_t idx) { return m_procs[idx].get(); }
|
||||
const Lv2Proc *control(std::size_t idx) const { return m_procs[idx].get(); }
|
||||
|
||||
bool hasGui() const { return m_hasGUI; }
|
||||
void setHasGui(bool val) { m_hasGUI = val; }
|
||||
|
||||
protected:
|
||||
/*
|
||||
ctor/dtor
|
||||
*/
|
||||
//! @param that the class inheriting this class and inheriting Model;
|
||||
//! this is the same pointer as this, but a different type
|
||||
//! @param uri the Lv2 URI telling this class what plugin to construct
|
||||
Lv2ControlBase(class Model *that, const QString& uri);
|
||||
Lv2ControlBase(const Lv2ControlBase&) = delete;
|
||||
~Lv2ControlBase() override;
|
||||
|
||||
Lv2ControlBase& operator=(const Lv2ControlBase&) = delete;
|
||||
|
||||
//! Must be checked after ctor or reload
|
||||
bool isValid() const { return m_valid; }
|
||||
|
||||
/*
|
||||
overrides
|
||||
*/
|
||||
LinkedModelGroup* getGroup(std::size_t idx) override;
|
||||
const LinkedModelGroup* getGroup(std::size_t idx) const override;
|
||||
|
||||
/*
|
||||
utils for the run thread
|
||||
*/
|
||||
//! Copy values from the LMMS core (connected models, MIDI events, ...) into
|
||||
//! the respective ports
|
||||
void copyModelsFromLmms();
|
||||
//! Bring values from all ports to the LMMS core
|
||||
void copyModelsToLmms() const;
|
||||
|
||||
//! Copy buffer passed by LMMS into our ports
|
||||
void copyBuffersFromLmms(const sampleFrame *buf, fpp_t frames);
|
||||
//! Copy our ports into buffers passed by LMMS
|
||||
void copyBuffersToLmms(sampleFrame *buf, fpp_t frames) const;
|
||||
//! Run the Lv2 plugin instance for @param frames frames
|
||||
void run(fpp_t frames);
|
||||
|
||||
/*
|
||||
load/save, must be called from virtuals
|
||||
*/
|
||||
void saveSettings(QDomDocument &doc, QDomElement &that);
|
||||
void loadSettings(const QDomElement &that);
|
||||
void loadFile(const QString &file);
|
||||
//! TODO: not implemented
|
||||
void reloadPlugin();
|
||||
|
||||
/*
|
||||
more functions that must be called from virtuals
|
||||
*/
|
||||
std::size_t controlCount() const;
|
||||
QString nodeName() const { return "lv2controls"; }
|
||||
bool hasNoteInput() const;
|
||||
void handleMidiInputEvent(const class MidiEvent &event,
|
||||
const class TimePos &time, f_cnt_t offset);
|
||||
|
||||
private:
|
||||
//! Return the DataFile settings type
|
||||
virtual DataFile::Types settingsType() = 0;
|
||||
//! Inform the plugin about a file name change
|
||||
virtual void setNameFromFile(const QString &fname) = 0;
|
||||
|
||||
//! Independent processors
|
||||
//! If this is a mono effect, the vector will have size 2 in order to
|
||||
//! fulfill LMMS' requirement of having stereo input and output
|
||||
std::vector<std::unique_ptr<Lv2Proc>> m_procs;
|
||||
|
||||
bool m_valid = true;
|
||||
bool m_hasGUI = false;
|
||||
unsigned m_channelsPerProc;
|
||||
|
||||
const LilvPlugin* m_plugin;
|
||||
};
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
#endif // LV2_CONTROL_BASE_H
|
||||
149
include/Lv2Evbuf.h
Normal file
149
include/Lv2Evbuf.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* lv2_evbuf.h - Lv2 event buffer definitions
|
||||
*
|
||||
* Copyright (c) 2019-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* The original code was written by David Robillard <http://drobilla.net>
|
||||
* Original version: 6f22ee0 from https://github.com/drobilla/jalv.git
|
||||
* Minor changes have been done, but no functional changes.
|
||||
* Considering this as an "external library", the identifiers do not need to
|
||||
* match the LMMS coding conventions.
|
||||
*/
|
||||
|
||||
#ifndef LV2_EVBUF_H
|
||||
#define LV2_EVBUF_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
An abstract/opaque LV2 event buffer.
|
||||
*/
|
||||
typedef struct LV2_Evbuf_Impl LV2_Evbuf;
|
||||
|
||||
/**
|
||||
An iterator over an LV2_Evbuf.
|
||||
*/
|
||||
typedef struct {
|
||||
LV2_Evbuf* evbuf;
|
||||
uint32_t offset;
|
||||
} LV2_Evbuf_Iterator;
|
||||
|
||||
/**
|
||||
Allocate a new, empty event buffer.
|
||||
URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM.
|
||||
*/
|
||||
LV2_Evbuf*
|
||||
lv2_evbuf_new(uint32_t capacity, uint32_t atom_Chunk, uint32_t atom_Sequence);
|
||||
|
||||
/**
|
||||
Free an event buffer allocated with lv2_evbuf_new.
|
||||
*/
|
||||
void
|
||||
lv2_evbuf_free(LV2_Evbuf* evbuf);
|
||||
|
||||
/**
|
||||
Clear and initialize an existing event buffer.
|
||||
The contents of buf are ignored entirely and overwritten, except capacity
|
||||
which is unmodified.
|
||||
If input is false and this is an atom buffer, the buffer will be prepared
|
||||
for writing by the plugin. This MUST be called before every run cycle.
|
||||
*/
|
||||
void
|
||||
lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input);
|
||||
|
||||
/**
|
||||
Return the total padded size of the events stored in the buffer.
|
||||
*/
|
||||
uint32_t
|
||||
lv2_evbuf_get_size(LV2_Evbuf* evbuf);
|
||||
|
||||
/**
|
||||
Return the actual buffer implementation.
|
||||
The format of the buffer returned depends on the buffer type.
|
||||
*/
|
||||
void*
|
||||
lv2_evbuf_get_buffer(LV2_Evbuf* evbuf);
|
||||
|
||||
/**
|
||||
Return an iterator to the start of `evbuf`.
|
||||
*/
|
||||
LV2_Evbuf_Iterator
|
||||
lv2_evbuf_begin(LV2_Evbuf* evbuf);
|
||||
|
||||
/**
|
||||
Return an iterator to the end of `evbuf`.
|
||||
*/
|
||||
LV2_Evbuf_Iterator
|
||||
lv2_evbuf_end(LV2_Evbuf* evbuf);
|
||||
|
||||
/**
|
||||
Check if `iter` is valid.
|
||||
@return True if `iter` is valid, otherwise false (past end of buffer)
|
||||
*/
|
||||
bool
|
||||
lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter);
|
||||
|
||||
/**
|
||||
Advance `iter` forward one event.
|
||||
`iter` must be valid.
|
||||
@return True if `iter` is valid, otherwise false (reached end of buffer)
|
||||
*/
|
||||
LV2_Evbuf_Iterator
|
||||
lv2_evbuf_next(LV2_Evbuf_Iterator iter);
|
||||
|
||||
/**
|
||||
Dereference an event iterator (i.e. get the event currently pointed to).
|
||||
`iter` must be valid.
|
||||
`type` Set to the type of the event.
|
||||
`size` Set to the size of the event.
|
||||
`data` Set to the contents of the event.
|
||||
@return True on success.
|
||||
*/
|
||||
bool
|
||||
lv2_evbuf_get( LV2_Evbuf_Iterator iter,
|
||||
uint32_t* frames,
|
||||
uint32_t* type,
|
||||
uint32_t* size,
|
||||
uint8_t** data);
|
||||
|
||||
/**
|
||||
Write an event at `iter`.
|
||||
The event (if any) pointed to by `iter` will be overwritten, and `iter`
|
||||
incremented to point to the following event (i.e. several calls to this
|
||||
function can be done in sequence without twiddling iter in-between).
|
||||
@return True if event was written, otherwise false (buffer is full).
|
||||
*/
|
||||
bool
|
||||
lv2_evbuf_write( LV2_Evbuf_Iterator* iter,
|
||||
uint32_t frames,
|
||||
uint32_t type,
|
||||
uint32_t size,
|
||||
const uint8_t* data);
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
|
||||
#endif // LV2_EVBUF_H
|
||||
81
include/Lv2Features.h
Normal file
81
include/Lv2Features.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Lv2Features.h - Lv2Features class
|
||||
*
|
||||
* Copyright (c) 2020-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV2FEATURES_H
|
||||
#define LV2FEATURES_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <lv2.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "Lv2Manager.h"
|
||||
|
||||
/**
|
||||
Feature container
|
||||
|
||||
References all available features for a plugin and maps them to their URIs.
|
||||
|
||||
The public member functions should be called in descending order:
|
||||
|
||||
1. initCommon: map plugin-common features
|
||||
2. operator[]: map plugin-specific features
|
||||
3. createFeatureVectors: create the feature vectors required for
|
||||
lilv_plugin_instantiate
|
||||
4. access the latter
|
||||
*/
|
||||
class Lv2Features
|
||||
{
|
||||
public:
|
||||
//! Return if a feature is supported by LMMS
|
||||
static bool isFeatureSupported(const char *featName);
|
||||
|
||||
Lv2Features();
|
||||
|
||||
//! Register only plugin-common features
|
||||
void initCommon();
|
||||
//! Return reference to feature data with given URI featName
|
||||
void*& operator[](const char* featName);
|
||||
//! Fill m_features and m_featurePointers with all features
|
||||
void createFeatureVectors();
|
||||
//! Return LV2_Feature pointer vector, suited for lilv_plugin_instantiate
|
||||
const LV2_Feature* const* featurePointers() const
|
||||
{
|
||||
return m_featurePointers.data();
|
||||
}
|
||||
|
||||
private:
|
||||
//! feature storage
|
||||
std::vector<LV2_Feature> m_features;
|
||||
//! pointers to m_features, required for lilv_plugin_instantiate
|
||||
std::vector<const LV2_Feature*> m_featurePointers;
|
||||
//! features + data, ordered by URI
|
||||
std::map<const char*, void*, Lv2Manager::CmpStr> m_featureByUri;
|
||||
};
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
|
||||
#endif // LV2FEATURES_H
|
||||
163
include/Lv2Manager.h
Normal file
163
include/Lv2Manager.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Lv2Manager.h - Implementation of Lv2Manager class
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV2MANAGER_H
|
||||
#define LV2MANAGER_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
#include "Lv2Basics.h"
|
||||
#include "Lv2UridCache.h"
|
||||
#include "Lv2UridMap.h"
|
||||
#include "Plugin.h"
|
||||
|
||||
|
||||
/*
|
||||
all Lv2 classes in relation (use our "4 spaces per tab rule" to view):
|
||||
|
||||
explanation:
|
||||
"x = {y z}" means class "x" consists of classes "y" and "z"
|
||||
(and probably other classes not mentioned)
|
||||
"x = {y*}" means class "x" references/uses class "y"
|
||||
|
||||
core:
|
||||
Lv2Proc = {LilvInstance}
|
||||
Lv2ControlBase = {Lv2Proc, Lv2Proc... (2 for mono, 1 for stereo)}
|
||||
Lv2Manager = {LilvPlugin*, LilvPlugin* ...}
|
||||
(creates Lv2ControlBase, Lv2ControlBase...)
|
||||
|
||||
Lv2FxControls = {Lv2ControlBase}
|
||||
Lv2Effect = {Effect + Lv2FxControls}
|
||||
(takes Lv2SubPluginFeatures in ctor)
|
||||
Lv2Instrument = {Instrument + Lv2ControlBase}
|
||||
(takes Lv2SubPluginFeatures in ctor)
|
||||
|
||||
gui:
|
||||
Lv2ViewProc = {Lv2Proc*}
|
||||
Lv2ViewBase = {Lv2ViewProc, Lv2ViewProc...
|
||||
(2 for mono, 1 for stereo)}
|
||||
Lv2FxControlDialog = {EffectControlDialog + Lv2ViewBase}
|
||||
Lv2InsView = {InstrumentView + Lv2ViewBase}
|
||||
|
||||
Lv2SubPluginFeatures:
|
||||
Lv2SubPluginFeatures = {Lv2Manager*}
|
||||
Lv2Effect::Descriptor = {Lv2SubPluginFeatures}
|
||||
Lv2Instrument::Descriptor = {Lv2SubPluginFeatures}
|
||||
*/
|
||||
|
||||
|
||||
//! Class to keep track of all LV2 plugins
|
||||
class Lv2Manager
|
||||
{
|
||||
public:
|
||||
void initPlugins();
|
||||
|
||||
Lv2Manager();
|
||||
~Lv2Manager();
|
||||
|
||||
|
||||
AutoLilvNode uri(const char* uriStr);
|
||||
|
||||
//! Class representing info for one plugin
|
||||
struct Lv2Info
|
||||
{
|
||||
public:
|
||||
//! use only for std::map internals
|
||||
Lv2Info() : m_plugin(nullptr) {}
|
||||
//! ctor used inside Lv2Manager
|
||||
Lv2Info(const LilvPlugin* plug, Plugin::PluginTypes type, bool valid) :
|
||||
m_plugin(plug), m_type(type), m_valid(valid) {}
|
||||
Lv2Info(Lv2Info&& other) = default;
|
||||
Lv2Info& operator=(Lv2Info&& other) = default;
|
||||
|
||||
const LilvPlugin* plugin() const { return m_plugin; }
|
||||
Plugin::PluginTypes type() const { return m_type; }
|
||||
bool isValid() const { return m_valid; }
|
||||
|
||||
private:
|
||||
const LilvPlugin* m_plugin;
|
||||
Plugin::PluginTypes m_type;
|
||||
bool m_valid = false;
|
||||
};
|
||||
|
||||
//! Return descriptor with URI @p uri or nullptr if none exists
|
||||
const LilvPlugin *getPlugin(const std::string &uri);
|
||||
//! Return descriptor with URI @p uri or nullptr if none exists
|
||||
const LilvPlugin *getPlugin(const QString& uri);
|
||||
|
||||
using Lv2InfoMap = std::map<std::string, Lv2Info>;
|
||||
using Iterator = Lv2InfoMap::iterator;
|
||||
Iterator begin() { return m_lv2InfoMap.begin(); }
|
||||
Iterator end() { return m_lv2InfoMap.end(); }
|
||||
|
||||
//! strcmp based key comparator for std::set and std::map
|
||||
struct CmpStr
|
||||
{
|
||||
bool operator()(char const *a, char const *b) const;
|
||||
};
|
||||
|
||||
UridMap& uridMap() { return m_uridMap; }
|
||||
const Lv2UridCache& uridCache() const { return m_uridCache; }
|
||||
const std::set<const char*, CmpStr>& supportedFeatureURIs() const
|
||||
{
|
||||
return m_supportedFeatureURIs;
|
||||
}
|
||||
bool isFeatureSupported(const char* featName) const;
|
||||
AutoLilvNodes findNodes(const LilvNode *subject,
|
||||
const LilvNode *predicate, const LilvNode *object);
|
||||
|
||||
static const std::set<const char*, Lv2Manager::CmpStr>& getPluginBlacklist()
|
||||
{
|
||||
return pluginBlacklist;
|
||||
}
|
||||
|
||||
private:
|
||||
// general data
|
||||
bool m_debug; //!< if set, debug output will be printed
|
||||
LilvWorld* m_world;
|
||||
Lv2InfoMap m_lv2InfoMap;
|
||||
std::set<const char*, CmpStr> m_supportedFeatureURIs;
|
||||
|
||||
// feature data that are common for all Lv2Proc
|
||||
UridMap m_uridMap;
|
||||
|
||||
// URID cache for fast URID access
|
||||
Lv2UridCache m_uridCache;
|
||||
|
||||
// static
|
||||
static const std::set<const char*, Lv2Manager::CmpStr> pluginBlacklist;
|
||||
|
||||
// functions
|
||||
bool isSubclassOf(const LilvPluginClass *clvss, const char *uriStr);
|
||||
};
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
|
||||
#endif // LV2MANAGER_H
|
||||
104
include/Lv2Options.h
Normal file
104
include/Lv2Options.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Lv2Options.h - Lv2Options class
|
||||
*
|
||||
* Copyright (c) 2020-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV2OPTIONS_H
|
||||
#define LV2OPTIONS_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <cstdint>
|
||||
#include <lv2/lv2plug.in/ns/ext/options/options.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "Engine.h"
|
||||
#include "Lv2Manager.h"
|
||||
#include "Lv2UridCache.h"
|
||||
|
||||
/**
|
||||
Option container
|
||||
|
||||
References all available options for a plugin and maps them to their URIDs.
|
||||
This class is used per Lv2 processor (justification in Lv2Proc::initMOptions())
|
||||
|
||||
The public member functions should be called in descending order:
|
||||
|
||||
1. supportOption: set all supported option URIDs
|
||||
2. initOption: initialize options with values
|
||||
3. createOptionVectors: create the option vectors required for
|
||||
the feature
|
||||
4. access the latter using feature()
|
||||
*/
|
||||
class Lv2Options
|
||||
{
|
||||
public:
|
||||
//! Return if an option is supported by LMMS
|
||||
static bool isOptionSupported(LV2_URID key);
|
||||
//! Mark option as supported
|
||||
static void supportOption(LV2_URID key);
|
||||
|
||||
//! Initialize an option
|
||||
template<typename Opt, typename Arg>
|
||||
void initOption(Lv2UridCache::Id key, Arg&& value,
|
||||
LV2_Options_Context context = LV2_OPTIONS_INSTANCE,
|
||||
std::uint32_t subject = 0)
|
||||
{
|
||||
const Lv2UridCache& cache = Engine::getLv2Manager()->uridCache();
|
||||
initOption(cache[key], sizeof(Opt), cache[Lv2UridCache::IdForType<Opt>::value],
|
||||
std::make_shared<Opt>(std::forward<Arg>(value)), context, subject);
|
||||
}
|
||||
//! Fill m_options and m_optionPointers with all options
|
||||
void createOptionVectors();
|
||||
//! Return the feature
|
||||
const LV2_Options_Option* feature() const
|
||||
{
|
||||
return m_options.data();
|
||||
}
|
||||
|
||||
private:
|
||||
//! Initialize an option internally
|
||||
void initOption(LV2_URID key,
|
||||
uint32_t size,
|
||||
LV2_URID type,
|
||||
std::shared_ptr<void> value,
|
||||
LV2_Options_Context context = LV2_OPTIONS_INSTANCE,
|
||||
uint32_t subject = 0);
|
||||
//! options that are supported by every processor
|
||||
static std::set<LV2_URID> s_supportedOptions;
|
||||
//! options + data, ordered by URID
|
||||
std::map<LV2_URID, LV2_Options_Option> m_optionByUrid;
|
||||
//! option storage
|
||||
std::vector<LV2_Options_Option> m_options;
|
||||
//! option value storage
|
||||
std::map<LV2_URID, std::shared_ptr<void>> m_optionValues;
|
||||
};
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
|
||||
#endif // LV2OPTIONS_H
|
||||
265
include/Lv2Ports.h
Normal file
265
include/Lv2Ports.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Lv2Ports.h - Lv2 port classes definitions
|
||||
*
|
||||
* Copyright (c) 2019-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV2PORTS_H
|
||||
#define LV2PORTS_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "PluginIssue.h"
|
||||
|
||||
struct ConnectPortVisitor;
|
||||
typedef struct LV2_Evbuf_Impl LV2_Evbuf;
|
||||
|
||||
namespace Lv2Ports {
|
||||
|
||||
/*
|
||||
port structs
|
||||
*/
|
||||
enum class Flow {
|
||||
Unknown,
|
||||
Input,
|
||||
Output
|
||||
};
|
||||
|
||||
enum class Type {
|
||||
Unknown,
|
||||
Control,
|
||||
Audio,
|
||||
AtomSeq,
|
||||
Cv //!< TODO: unused, describe
|
||||
};
|
||||
|
||||
//! Port visualization
|
||||
//! @note All Lv2 audio ports are float, this is only the visualisation
|
||||
enum class Vis {
|
||||
Generic, //!< nothing specific, a generic knob or slider shall be used
|
||||
Integer, //!< counter
|
||||
Enumeration, //!< selection from enumerated values
|
||||
Toggled //!< boolean widget
|
||||
};
|
||||
|
||||
const char* toStr(Lv2Ports::Flow pf);
|
||||
const char* toStr(Lv2Ports::Type pt);
|
||||
const char* toStr(Lv2Ports::Vis pv);
|
||||
|
||||
struct ControlPortBase;
|
||||
struct Control;
|
||||
struct Audio;
|
||||
struct Cv;
|
||||
struct AtomSeq;
|
||||
struct Unknown;
|
||||
|
||||
struct ConstVisitor
|
||||
{
|
||||
virtual void visit(const Lv2Ports::ControlPortBase& ) {}
|
||||
virtual void visit(const Lv2Ports::Control& ) {}
|
||||
virtual void visit(const Lv2Ports::Audio& ) {}
|
||||
virtual void visit(const Lv2Ports::Cv& ) {}
|
||||
virtual void visit(const Lv2Ports::AtomSeq& ) {}
|
||||
virtual void visit(const Lv2Ports::Unknown& ) {}
|
||||
|
||||
virtual ~ConstVisitor();
|
||||
};
|
||||
|
||||
struct Visitor
|
||||
{
|
||||
virtual void visit(Lv2Ports::ControlPortBase& ) {}
|
||||
virtual void visit(Lv2Ports::Control& ) {}
|
||||
virtual void visit(Lv2Ports::Audio& ) {}
|
||||
virtual void visit(Lv2Ports::Cv& ) {}
|
||||
virtual void visit(Lv2Ports::AtomSeq& ) {}
|
||||
virtual void visit(Lv2Ports::Unknown& ) {}
|
||||
|
||||
virtual ~Visitor();
|
||||
};
|
||||
|
||||
struct Meta
|
||||
{
|
||||
Type m_type = Type::Unknown;
|
||||
Flow m_flow = Flow::Unknown;
|
||||
Vis m_vis = Vis::Generic;
|
||||
|
||||
bool m_logarithmic = false;
|
||||
|
||||
bool m_optional = false;
|
||||
bool m_used = true;
|
||||
|
||||
std::vector<PluginIssue> get(const LilvPlugin* plugin, std::size_t portNum);
|
||||
|
||||
float def() const { return m_def; }
|
||||
float min(sample_rate_t sr) const { return m_sampleRate ? sr * m_min : m_min; }
|
||||
float max(sample_rate_t sr) const { return m_sampleRate ? sr * m_max : m_max; }
|
||||
private:
|
||||
float m_def = .0f, m_min = .0f, m_max = .0f;
|
||||
bool m_sampleRate = false;
|
||||
};
|
||||
|
||||
struct PortBase : public Meta
|
||||
{
|
||||
const LilvPort* m_port = nullptr;
|
||||
const LilvPlugin* m_plugin = nullptr;
|
||||
|
||||
virtual void accept(Visitor& v) = 0;
|
||||
virtual void accept(ConstVisitor& v) const = 0;
|
||||
|
||||
QString name() const;
|
||||
QString uri() const;
|
||||
|
||||
virtual ~PortBase();
|
||||
};
|
||||
|
||||
template<typename Derived, typename Base>
|
||||
struct VisitablePort : public Base
|
||||
{
|
||||
void accept(Visitor& v) override { v.visit(static_cast<Derived&>(*this)); }
|
||||
void accept(ConstVisitor& v) const override { v.visit(static_cast<const Derived&>(*this)); }
|
||||
};
|
||||
|
||||
struct ControlPortBase : public VisitablePort<ControlPortBase, PortBase>
|
||||
{
|
||||
//! LMMS models
|
||||
//! Always up-to-date, except during runs
|
||||
std::unique_ptr<class AutomatableModel> m_connectedModel;
|
||||
|
||||
//! Enumerate float values
|
||||
//! lv2 defines scale points as
|
||||
//! "single float Points (for control inputs)"
|
||||
std::vector<float> m_scalePointMap;
|
||||
};
|
||||
|
||||
struct Control : public VisitablePort<Control, ControlPortBase>
|
||||
{
|
||||
//! Data location which Lv2 plugins see
|
||||
//! Model values are being copied here every run
|
||||
//! Between runs, this data is not up-to-date
|
||||
float m_val;
|
||||
};
|
||||
|
||||
struct Cv : public VisitablePort<Cv, ControlPortBase>
|
||||
{
|
||||
//! Data location which Lv2 plugins see
|
||||
//! Model values are being copied here every run
|
||||
//! Between runs, this data is not up-to-date
|
||||
std::vector<float> m_buffer;
|
||||
};
|
||||
|
||||
struct Audio : public VisitablePort<Audio, PortBase>
|
||||
{
|
||||
Audio(std::size_t bufferSize, bool isSidechain);
|
||||
|
||||
//! Copy buffer passed by LMMS into our ports
|
||||
//! @param channel channel index into each sample frame
|
||||
void copyBuffersFromCore(const sampleFrame *lmmsBuf,
|
||||
unsigned channel, fpp_t frames);
|
||||
//! Add buffer passed by LMMS into our ports, and halve the result
|
||||
//! @param channel channel index into each sample frame
|
||||
void averageWithBuffersFromCore(const sampleFrame *lmmsBuf,
|
||||
unsigned channel, fpp_t frames);
|
||||
//! Copy our ports into buffers passed by LMMS
|
||||
//! @param channel channel index into each sample frame
|
||||
void copyBuffersToCore(sampleFrame *lmmsBuf,
|
||||
unsigned channel, fpp_t frames) const;
|
||||
|
||||
bool isSideChain() const { return m_sidechain; }
|
||||
bool isOptional() const { return m_optional; }
|
||||
bool mustBeUsed() const { return !isSideChain() && !isOptional(); }
|
||||
std::size_t bufferSize() const { return m_buffer.size(); }
|
||||
|
||||
private:
|
||||
//! the buffer where Lv2 reads/writes the data from/to
|
||||
std::vector<float> m_buffer;
|
||||
bool m_sidechain;
|
||||
|
||||
// the only case when data of m_buffer may be referenced:
|
||||
friend struct ::ConnectPortVisitor;
|
||||
};
|
||||
|
||||
struct AtomSeq : public VisitablePort<AtomSeq, PortBase>
|
||||
{
|
||||
enum FlagType
|
||||
{
|
||||
None = 0,
|
||||
Midi = 1
|
||||
};
|
||||
unsigned flags = FlagType::None;
|
||||
|
||||
struct Lv2EvbufDeleter
|
||||
{
|
||||
void operator()(LV2_Evbuf* n);
|
||||
};
|
||||
using AutoLv2Evbuf = std::unique_ptr<LV2_Evbuf, Lv2EvbufDeleter>;
|
||||
AutoLv2Evbuf m_buf;
|
||||
};
|
||||
|
||||
struct Unknown : public VisitablePort<Unknown, PortBase>
|
||||
{
|
||||
};
|
||||
|
||||
/*
|
||||
port casts
|
||||
*/
|
||||
template<class Target>
|
||||
struct DCastVisitor : public Visitor
|
||||
{
|
||||
Target* m_result = nullptr;
|
||||
void visit(Target& tar) { m_result = &tar; }
|
||||
};
|
||||
|
||||
template<class Target>
|
||||
struct ConstDCastVisitor : public ConstVisitor
|
||||
{
|
||||
const Target* m_result = nullptr;
|
||||
void visit(const Target& tar) { m_result = &tar; }
|
||||
};
|
||||
|
||||
//! If you don't want to use a whole visitor, you can use dcast
|
||||
template<class Target>
|
||||
Target* dcast(PortBase* base)
|
||||
{
|
||||
DCastVisitor<Target> vis;
|
||||
base->accept(vis);
|
||||
return vis.m_result;
|
||||
}
|
||||
|
||||
//! const overload
|
||||
template<class Target>
|
||||
const Target* dcast(const PortBase* base)
|
||||
{
|
||||
ConstDCastVisitor<Target> vis;
|
||||
base->accept(vis);
|
||||
return vis.m_result;
|
||||
}
|
||||
|
||||
} // namespace Lv2Ports
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
#endif // LV2PORTS_H
|
||||
217
include/Lv2Proc.h
Normal file
217
include/Lv2Proc.h
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Lv2Proc.h - Lv2 processor class
|
||||
*
|
||||
* Copyright (c) 2019-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV2PROC_H
|
||||
#define LV2PROC_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
#ifdef LMMS_HAVE_LV2
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
#include <memory>
|
||||
#include <QObject>
|
||||
|
||||
#include "Lv2Basics.h"
|
||||
#include "Lv2Features.h"
|
||||
#include "Lv2Options.h"
|
||||
#include "LinkedModelGroups.h"
|
||||
#include "MidiEvent.h"
|
||||
#include "Plugin.h"
|
||||
#include "PluginIssue.h"
|
||||
#include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h"
|
||||
#include "TimePos.h"
|
||||
|
||||
// forward declare port structs/enums
|
||||
namespace Lv2Ports
|
||||
{
|
||||
struct Audio;
|
||||
struct PortBase;
|
||||
struct AtomSeq;
|
||||
|
||||
enum class Type;
|
||||
enum class Flow;
|
||||
enum class Vis;
|
||||
}
|
||||
|
||||
|
||||
//! Class representing one Lv2 processor, i.e. one Lv2 handle
|
||||
//! For Mono effects, 1 Lv2ControlBase references 2 Lv2Proc
|
||||
class Lv2Proc : public LinkedModelGroup
|
||||
{
|
||||
public:
|
||||
static Plugin::PluginTypes check(const LilvPlugin* plugin,
|
||||
std::vector<PluginIssue> &issues);
|
||||
|
||||
/*
|
||||
ctor/dtor
|
||||
*/
|
||||
Lv2Proc(const LilvPlugin* plugin, Model *parent);
|
||||
~Lv2Proc() override;
|
||||
//! Must be checked after ctor or reload
|
||||
bool isValid() const { return m_valid; }
|
||||
|
||||
/*
|
||||
port access
|
||||
*/
|
||||
struct StereoPortRef
|
||||
{
|
||||
//! mono port or left port in case of stereo
|
||||
Lv2Ports::Audio* m_left = nullptr;
|
||||
//! unused, or right port in case of stereo
|
||||
Lv2Ports::Audio* m_right = nullptr;
|
||||
};
|
||||
|
||||
StereoPortRef& inPorts() { return m_inPorts; }
|
||||
const StereoPortRef& inPorts() const { return m_inPorts; }
|
||||
StereoPortRef& outPorts() { return m_outPorts; }
|
||||
const StereoPortRef& outPorts() const { return m_outPorts; }
|
||||
template<class Functor>
|
||||
void foreach_port(const Functor& ftor)
|
||||
{
|
||||
for (std::unique_ptr<Lv2Ports::PortBase>& port : m_ports)
|
||||
{
|
||||
ftor(port.get());
|
||||
}
|
||||
}
|
||||
template<class Functor>
|
||||
void foreach_port(const Functor& ftor) const
|
||||
{
|
||||
for (const std::unique_ptr<Lv2Ports::PortBase>& port : m_ports)
|
||||
{
|
||||
ftor(port.get());
|
||||
}
|
||||
}
|
||||
|
||||
//! Debug function to print ports to stdout
|
||||
void dumpPorts();
|
||||
|
||||
/*
|
||||
utils for the run thread
|
||||
*/
|
||||
//! Copy values from the LMMS core (connected models, MIDI events, ...) into
|
||||
//! the respective ports
|
||||
void copyModelsFromCore();
|
||||
//! Bring values from all ports to the LMMS core
|
||||
void copyModelsToCore();
|
||||
/**
|
||||
* Copy buffer passed by the core into our ports
|
||||
* @param buf buffer of sample frames, each sample frame is something like
|
||||
* a `float[<number-of-procs> * <channels per proc>]` array.
|
||||
* @param firstChan The offset for @p buf where we have to read our
|
||||
* first channel.
|
||||
* This marks the first sample in each sample frame where we read from.
|
||||
* If we are the 2nd of 2 mono procs, this can be greater than 0.
|
||||
* @param num Number of channels we must read from @param buf (starting at
|
||||
* @p offset)
|
||||
*/
|
||||
void copyBuffersFromCore(const sampleFrame *buf,
|
||||
unsigned firstChan, unsigned num, fpp_t frames);
|
||||
/**
|
||||
* Copy our ports into buffers passed by the core
|
||||
* @param buf buffer of sample frames, each sample frame is something like
|
||||
* a `float[<number-of-procs> * <channels per proc>]` array.
|
||||
* @param firstChan The offset for @p buf where we have to write our
|
||||
* first channel.
|
||||
* This marks the first sample in each sample frame where we write to.
|
||||
* If we are the 2nd of 2 mono procs, this can be greater than 0.
|
||||
* @param num Number of channels we must write to @param buf (starting at
|
||||
* @p offset)
|
||||
*/
|
||||
void copyBuffersToCore(sampleFrame *buf, unsigned firstChan, unsigned num,
|
||||
fpp_t frames) const;
|
||||
//! Run the Lv2 plugin instance for @param frames frames
|
||||
void run(fpp_t frames);
|
||||
|
||||
void handleMidiInputEvent(const class MidiEvent &event,
|
||||
const TimePos &time, f_cnt_t offset);
|
||||
|
||||
/*
|
||||
misc
|
||||
*/
|
||||
class AutomatableModel *modelAtPort(const QString &uri); // unused currently
|
||||
std::size_t controlCount() const { return LinkedModelGroup::modelNum(); }
|
||||
bool hasNoteInput() const;
|
||||
|
||||
protected:
|
||||
/*
|
||||
load and save
|
||||
*/
|
||||
//! Create ports and instance, connect ports, activate plugin
|
||||
void initPlugin();
|
||||
//! Deactivate instance
|
||||
void shutdownPlugin();
|
||||
|
||||
private:
|
||||
bool m_valid = true;
|
||||
|
||||
const LilvPlugin* m_plugin;
|
||||
LilvInstance* m_instance;
|
||||
Lv2Features m_features;
|
||||
Lv2Options m_options;
|
||||
|
||||
// full list of ports
|
||||
std::vector<std::unique_ptr<Lv2Ports::PortBase>> m_ports;
|
||||
// quick reference to specific, unique ports
|
||||
StereoPortRef m_inPorts, m_outPorts;
|
||||
Lv2Ports::AtomSeq *m_midiIn = nullptr, *m_midiOut = nullptr;
|
||||
|
||||
// MIDI
|
||||
// many things here may be moved into the `Instrument` class
|
||||
constexpr const static std::size_t m_maxMidiInputEvents = 1024;
|
||||
//! spinlock for the MIDI ringbuffer (for MIDI events going to the plugin)
|
||||
std::atomic_flag m_ringLock = ATOMIC_FLAG_INIT;
|
||||
|
||||
//! MIDI ringbuffer (for MIDI events going to the plugin)
|
||||
ringbuffer_t<struct MidiInputEvent> m_midiInputBuf;
|
||||
//! MIDI ringbuffer reader
|
||||
ringbuffer_reader_t<struct MidiInputEvent> m_midiInputReader;
|
||||
|
||||
// other
|
||||
static int32_t defaultEvbufSize() { return 1 << 15; /* ardour uses this*/ }
|
||||
|
||||
//! models for the controls, sorted by port symbols
|
||||
std::map<std::string, AutomatableModel *> m_connectedModels;
|
||||
|
||||
void initMOptions(); //!< initialize m_options
|
||||
void initPluginSpecificFeatures();
|
||||
|
||||
//! load a file in the plugin, but don't do anything in LMMS
|
||||
void loadFileInternal(const QString &file);
|
||||
//! allocate m_ports, fill all with metadata, and assign meaning of ports
|
||||
void createPorts();
|
||||
//! fill m_ports[portNum] with metadata
|
||||
void createPort(std::size_t portNum);
|
||||
//! connect m_ports[portNum] with Lv2
|
||||
void connectPort(std::size_t num);
|
||||
|
||||
void dumpPort(std::size_t num);
|
||||
|
||||
static bool portIsSideChain(const LilvPlugin* plugin, const LilvPort *port);
|
||||
static bool portIsOptional(const LilvPlugin* plugin, const LilvPort *port);
|
||||
static AutoLilvNode uri(const char* uriStr);
|
||||
};
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
#endif // LV2PROC_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user