Merge branch 'master' into dynamic-effect-dialog
This commit is contained in:
1
src/3rdparty/CMakeLists.txt
vendored
1
src/3rdparty/CMakeLists.txt
vendored
@@ -3,6 +3,7 @@ IF(LMMS_BUILD_LINUX AND WANT_VST)
|
||||
add_subdirectory(qt5-x11embed)
|
||||
ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY(hiir)
|
||||
ADD_SUBDIRECTORY(rpmalloc)
|
||||
ADD_SUBDIRECTORY(weakjack)
|
||||
|
||||
|
||||
3
src/3rdparty/hiir/CMakeLists.txt
vendored
Normal file
3
src/3rdparty/hiir/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
add_library(hiir INTERFACE)
|
||||
target_include_directories(hiir INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_features(hiir INTERFACE cxx_std_17)
|
||||
1
src/3rdparty/hiir/hiir
vendored
Submodule
1
src/3rdparty/hiir/hiir
vendored
Submodule
Submodule src/3rdparty/hiir/hiir added at 4a9a1e67fa
@@ -857,7 +857,7 @@ void AutomationClip::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
const QString AutomationClip::name() const
|
||||
QString AutomationClip::name() const
|
||||
{
|
||||
QMutexLocker m(&m_clipMutex);
|
||||
|
||||
@@ -1173,4 +1173,4 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lmms
|
||||
} // namespace lmms
|
||||
|
||||
@@ -89,19 +89,27 @@ const std::vector<ProjectVersion> DataFile::UPGRADE_VERSIONS = {
|
||||
"1.2.0-rc3" , "1.3.0"
|
||||
};
|
||||
|
||||
DataFile::typeDescStruct
|
||||
DataFile::s_types[DataFile::TypeCount] =
|
||||
namespace
|
||||
{
|
||||
{ DataFile::UnknownType, "unknown" },
|
||||
{ DataFile::SongProject, "song" },
|
||||
{ DataFile::SongProjectTemplate, "songtemplate" },
|
||||
{ DataFile::InstrumentTrackSettings, "instrumenttracksettings" },
|
||||
{ DataFile::DragNDropData, "dnddata" },
|
||||
{ DataFile::ClipboardData, "clipboard-data" },
|
||||
{ DataFile::JournalData, "journaldata" },
|
||||
{ DataFile::EffectSettings, "effectsettings" },
|
||||
{ DataFile::MidiClip, "midiclip" }
|
||||
} ;
|
||||
struct TypeDescStruct
|
||||
{
|
||||
DataFile::Type m_type;
|
||||
QString m_name;
|
||||
};
|
||||
|
||||
const auto s_types = std::array<TypeDescStruct, DataFile::TypeCount>
|
||||
{
|
||||
TypeDescStruct{ DataFile::UnknownType, "unknown" },
|
||||
TypeDescStruct{ DataFile::SongProject, "song" },
|
||||
TypeDescStruct{ DataFile::SongProjectTemplate, "songtemplate" },
|
||||
TypeDescStruct{ DataFile::InstrumentTrackSettings, "instrumenttracksettings" },
|
||||
TypeDescStruct{ DataFile::DragNDropData, "dnddata" },
|
||||
TypeDescStruct{ DataFile::ClipboardData, "clipboard-data" },
|
||||
TypeDescStruct{ DataFile::JournalData, "journaldata" },
|
||||
TypeDescStruct{ DataFile::EffectSettings, "effectsettings" },
|
||||
TypeDescStruct{ DataFile::MidiClip, "midiclip" }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1314,44 +1322,32 @@ void DataFile::upgrade_1_3_0()
|
||||
// Effect name changes
|
||||
|
||||
QDomElement attribute = attributes.item( k ).toElement();
|
||||
if( attribute.attribute( "name" ) == "file" &&
|
||||
( attribute.attribute( "value" ) == "calf" ||
|
||||
attribute.attribute( "value" ) == "calf.so" ) )
|
||||
const QString attrName = attribute.attribute("name");
|
||||
const QString attrVal = attribute.attribute("value");
|
||||
const QString plugin = attrName == "plugin" ? attrVal : "";
|
||||
|
||||
static const std::map<QString, QString> pluginNames = {
|
||||
{"Sidechaincompressor", "SidechainCompressor"},
|
||||
{"Sidechaingate", "SidechainGate"},
|
||||
{"Multibandcompressor", "MultibandCompressor"},
|
||||
{"Multibandgate", "MultibandGate"},
|
||||
{"Multibandlimiter", "MultibandLimiter"},
|
||||
};
|
||||
|
||||
if (attrName == "file" && (attrVal == "calf" || attrVal == "calf.so" ))
|
||||
{
|
||||
attribute.setAttribute( "value", "veal" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Sidechaincompressor" )
|
||||
|
||||
const auto newName = pluginNames.find(plugin);
|
||||
if (newName != pluginNames.end())
|
||||
{
|
||||
attribute.setAttribute( "value", "SidechainCompressor" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Sidechaingate" )
|
||||
{
|
||||
attribute.setAttribute( "value", "SidechainGate" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Multibandcompressor" )
|
||||
{
|
||||
attribute.setAttribute( "value", "MultibandCompressor" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Multibandgate" )
|
||||
{
|
||||
attribute.setAttribute( "value", "MultibandGate" );
|
||||
}
|
||||
else if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Multibandlimiter" )
|
||||
{
|
||||
attribute.setAttribute( "value", "MultibandLimiter" );
|
||||
attribute.setAttribute("value", newName->second);
|
||||
}
|
||||
|
||||
// Handle port changes
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( attribute.attribute( "value" ) == "MultibandLimiter" ||
|
||||
attribute.attribute( "value" ) == "MultibandCompressor" ||
|
||||
attribute.attribute( "value" ) == "MultibandGate" ) )
|
||||
if (plugin == "MultibandLimiter" || plugin == "MultibandCompressor" || plugin == "MultibandGate")
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& removeList)
|
||||
{
|
||||
@@ -1372,8 +1368,7 @@ void DataFile::upgrade_1_3_0()
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( attribute.attribute( "value" ) == "Pulsator" ) )
|
||||
else if (plugin == "Pulsator")
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>& addList, QList<QDomElement>& removeList)
|
||||
{
|
||||
@@ -1416,9 +1411,7 @@ void DataFile::upgrade_1_3_0()
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( attribute.attribute( "value" ) == "VintageDelay" ) )
|
||||
else if (plugin == "VintageDelay")
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>& addList, QList<QDomElement>& )
|
||||
{
|
||||
@@ -1455,23 +1448,20 @@ void DataFile::upgrade_1_3_0()
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
( ( attribute.attribute( "value" ) == "Equalizer5Band" )
|
||||
|| ( attribute.attribute( "value" ) == "Equalizer8Band" )
|
||||
|| ( attribute.attribute( "value" ) == "Equalizer12Band" ) ) )
|
||||
else if (plugin == "Equalizer5Band" || plugin == "Equalizer8Band" || plugin == "Equalizer12Band")
|
||||
{
|
||||
// NBand equalizers got 4 q nobs inserted. We need to shift everything else...
|
||||
// HOWEVER: 5 band eq has only 2 q nobs inserted (no LS/HS filters)
|
||||
bool band5 = ( attribute.attribute( "value" ) == "Equalizer5Band" );
|
||||
bool band5 = plugin == "Equalizer5Band";
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>& addList, QList<QDomElement>& )
|
||||
{
|
||||
if(num == 4)
|
||||
{
|
||||
// don't modify port 4, but some other ones:
|
||||
int zoom_port;
|
||||
if(attribute.attribute( "value" ) == "Equalizer5Band")
|
||||
if (plugin == "Equalizer5Band")
|
||||
zoom_port = 36;
|
||||
else if(attribute.attribute( "value" ) == "Equalizer8Band")
|
||||
else if (plugin == "Equalizer8Band")
|
||||
zoom_port = 48;
|
||||
else // 12 band
|
||||
zoom_port = 64;
|
||||
@@ -1552,8 +1542,7 @@ void DataFile::upgrade_1_3_0()
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "Saturator" )
|
||||
else if (plugin == "Saturator")
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& )
|
||||
{
|
||||
@@ -1580,8 +1569,7 @@ void DataFile::upgrade_1_3_0()
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
if( attribute.attribute( "name" ) == "plugin" &&
|
||||
attribute.attribute( "value" ) == "StereoTools" )
|
||||
else if (plugin == "StereoTools")
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& )
|
||||
{
|
||||
@@ -1597,6 +1585,29 @@ void DataFile::upgrade_1_3_0()
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
|
||||
else if (plugin == "amPitchshift")
|
||||
{
|
||||
auto fn = [&](QDomElement& port, int num, QList<QDomElement>&, QList<QDomElement>& removeList)
|
||||
{
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
port.setTagName("port01");
|
||||
break;
|
||||
case 1:
|
||||
port.setTagName("port03");
|
||||
break;
|
||||
case 10:
|
||||
port.setTagName("port11");
|
||||
break;
|
||||
case 11:
|
||||
port.setTagName("port13");
|
||||
break;
|
||||
}
|
||||
};
|
||||
iterate_ladspa_ports(effect, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ bool Instrument::isFromTrack( const Track * _track ) const
|
||||
static int countZeroCrossings(sampleFrame *buf, fpp_t start, fpp_t frames)
|
||||
{
|
||||
// zero point crossing counts of all channels
|
||||
int zeroCrossings[DEFAULT_CHANNELS] = {0};
|
||||
auto zeroCrossings = std::array<int, DEFAULT_CHANNELS>{};
|
||||
// maximum zero point crossing of all channels
|
||||
int maxZeroCrossings = 0;
|
||||
|
||||
|
||||
@@ -34,9 +34,10 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking::ChordTable::s_initTable[] =
|
||||
{
|
||||
std::array<InstrumentFunctionNoteStacking::ChordTable::Init, InstrumentFunctionNoteStacking::NUM_CHORD_TABLES>
|
||||
InstrumentFunctionNoteStacking::ChordTable::s_initTable =
|
||||
std::array<InstrumentFunctionNoteStacking::ChordTable::Init, NUM_CHORD_TABLES>
|
||||
{{
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "octave" ), { 0, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Major" ), { 0, 4, 7, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Majb5" ), { 0, 4, 6, -1 } },
|
||||
@@ -139,7 +140,7 @@ InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking:
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "5" ), { 0, 7, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Phrygian dominant" ), { 0, 1, 4, 5, 7, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "Persian" ), { 0, 1, 4, 5, 6, 8, 11, -1 } }
|
||||
} ;
|
||||
}};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ struct AddMultipliedStereoOp
|
||||
dst[1] += src[1] * m_coeffs[1];
|
||||
}
|
||||
|
||||
float m_coeffs[2];
|
||||
std::array<float, 2> m_coeffs;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -309,7 +309,7 @@ struct MultiplyAndAddMultipliedOp
|
||||
dst[1] = dst[1]*m_coeffs[0] + src[1]*m_coeffs[1];
|
||||
}
|
||||
|
||||
float m_coeffs[2];
|
||||
std::array<float, 2> m_coeffs;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -190,11 +190,11 @@ void MixerChannel::doProcessing()
|
||||
Mixer::Mixer() :
|
||||
Model( nullptr ),
|
||||
JournallingObject(),
|
||||
m_mixerChannels()
|
||||
m_mixerChannels(),
|
||||
m_lastSoloed(-1)
|
||||
{
|
||||
// create master channel
|
||||
createChannel();
|
||||
m_lastSoloed = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -224,6 +224,13 @@ int Mixer::createChannel()
|
||||
// reset channel state
|
||||
clearChannel( index );
|
||||
|
||||
// if there is a soloed channel, mute the new track
|
||||
if (m_lastSoloed != -1 && m_mixerChannels[m_lastSoloed]->m_soloModel.value())
|
||||
{
|
||||
m_mixerChannels[index]->m_muteBeforeSolo = m_mixerChannels[index]->m_muteModel.value();
|
||||
m_mixerChannels[index]->m_muteModel.setValue(true);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -825,5 +832,41 @@ void Mixer::validateChannelName( int index, int oldIndex )
|
||||
}
|
||||
}
|
||||
|
||||
bool Mixer::isChannelInUse(int index)
|
||||
{
|
||||
// check if the index mixer channel receives audio from any other channel
|
||||
if (!m_mixerChannels[index]->m_receives.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if the destination mixer channel on any instrument or sample track is the index mixer channel
|
||||
TrackContainer::TrackList tracks;
|
||||
tracks += Engine::getSong()->tracks();
|
||||
tracks += Engine::patternStore()->tracks();
|
||||
|
||||
for (const auto t : tracks)
|
||||
{
|
||||
if (t->type() == Track::InstrumentTrack)
|
||||
{
|
||||
auto inst = dynamic_cast<InstrumentTrack*>(t);
|
||||
if (inst->mixerChannelModel()->value() == index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (t->type() == Track::SampleTrack)
|
||||
{
|
||||
auto strack = dynamic_cast<SampleTrack*>(t);
|
||||
if (strack->mixerChannelModel()->value() == index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
@@ -27,22 +27,47 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
Model::Model(Model* parent, QString displayName, bool defaultConstructed) :
|
||||
QObject(parent),
|
||||
m_displayName(displayName),
|
||||
m_defaultConstructed(defaultConstructed)
|
||||
{
|
||||
}
|
||||
|
||||
bool Model::isDefaultConstructed() const
|
||||
{
|
||||
return m_defaultConstructed;
|
||||
}
|
||||
|
||||
Model* Model::parentModel() const
|
||||
{
|
||||
return dynamic_cast<Model*>(parent());
|
||||
}
|
||||
|
||||
QString Model::displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
void Model::setDisplayName(const QString& displayName)
|
||||
{
|
||||
m_displayName = displayName;
|
||||
}
|
||||
|
||||
QString Model::fullDisplayName() const
|
||||
{
|
||||
const QString & n = displayName();
|
||||
if( parentModel() )
|
||||
const QString n = displayName();
|
||||
|
||||
if (parentModel())
|
||||
{
|
||||
const QString p = parentModel()->fullDisplayName();
|
||||
if( n.isEmpty() && p.isEmpty() )
|
||||
|
||||
if (!p.isEmpty())
|
||||
{
|
||||
return QString();
|
||||
return p + ">" + n;
|
||||
}
|
||||
else if( p.isEmpty() )
|
||||
{
|
||||
return n;
|
||||
}
|
||||
return p + ">" + n;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ void Oscillator::generateFromFFT(int bands, sample_t* table)
|
||||
//ifft
|
||||
fftwf_execute(s_ifftPlan);
|
||||
//normalize and copy to result buffer
|
||||
normalize(s_sampleBuffer, table, OscillatorConstants::WAVETABLE_LENGTH, 2*OscillatorConstants::WAVETABLE_LENGTH + 1);
|
||||
normalize(s_sampleBuffer.data(), table, OscillatorConstants::WAVETABLE_LENGTH, 2*OscillatorConstants::WAVETABLE_LENGTH + 1);
|
||||
}
|
||||
|
||||
void Oscillator::generateAntiAliasUserWaveTable(SampleBuffer *sampleBuffer)
|
||||
@@ -205,15 +205,15 @@ sample_t Oscillator::s_waveTables
|
||||
fftwf_plan Oscillator::s_fftPlan;
|
||||
fftwf_plan Oscillator::s_ifftPlan;
|
||||
fftwf_complex * Oscillator::s_specBuf;
|
||||
float Oscillator::s_sampleBuffer[OscillatorConstants::WAVETABLE_LENGTH];
|
||||
std::array<float, OscillatorConstants::WAVETABLE_LENGTH> Oscillator::s_sampleBuffer;
|
||||
|
||||
|
||||
|
||||
void Oscillator::createFFTPlans()
|
||||
{
|
||||
Oscillator::s_specBuf = ( fftwf_complex * ) fftwf_malloc( ( OscillatorConstants::WAVETABLE_LENGTH * 2 + 1 ) * sizeof( fftwf_complex ) );
|
||||
Oscillator::s_fftPlan = fftwf_plan_dft_r2c_1d(OscillatorConstants::WAVETABLE_LENGTH, s_sampleBuffer, s_specBuf, FFTW_MEASURE );
|
||||
Oscillator::s_ifftPlan = fftwf_plan_dft_c2r_1d(OscillatorConstants::WAVETABLE_LENGTH, s_specBuf, s_sampleBuffer, FFTW_MEASURE);
|
||||
Oscillator::s_fftPlan = fftwf_plan_dft_r2c_1d(OscillatorConstants::WAVETABLE_LENGTH, s_sampleBuffer.data(), s_specBuf, FFTW_MEASURE );
|
||||
Oscillator::s_ifftPlan = fftwf_plan_dft_c2r_1d(OscillatorConstants::WAVETABLE_LENGTH, s_specBuf, s_sampleBuffer.data(), FFTW_MEASURE);
|
||||
// initialize s_specBuf content to zero, since the values are used in a condition inside generateFromFFT()
|
||||
for (int i = 0; i < OscillatorConstants::WAVETABLE_LENGTH * 2 + 1; i++)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace lmms::PathUtil
|
||||
{
|
||||
Base relativeBases[] = { Base::ProjectDir, Base::FactorySample, Base::UserSample, Base::UserVST, Base::Preset,
|
||||
auto relativeBases = std::array{ Base::ProjectDir, Base::FactorySample, Base::UserSample, Base::UserVST, Base::Preset,
|
||||
Base::UserLADSPA, Base::DefaultLADSPA, Base::UserSoundfont, Base::DefaultSoundfont, Base::UserGIG, Base::DefaultGIG,
|
||||
Base::LocalDir };
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace lmms::PathUtil
|
||||
//Check if it's a factory sample
|
||||
QString factoryPath = baseLocation(Base::FactorySample) + input;
|
||||
QFileInfo factoryInfo(factoryPath);
|
||||
if (factoryInfo.exists()) { assumedBase = Base::FactorySample; }
|
||||
if (factoryInfo.exists()) { assumedBase = Base::FactorySample; }
|
||||
|
||||
//Check if it's a VST
|
||||
QString vstPath = baseLocation(Base::UserVST) + input;
|
||||
|
||||
@@ -60,6 +60,7 @@ void PatternClip::saveSettings(QDomDocument& doc, QDomElement& element)
|
||||
element.setAttribute( "pos", startPosition() );
|
||||
}
|
||||
element.setAttribute( "len", length() );
|
||||
element.setAttribute("off", startTimeOffset());
|
||||
element.setAttribute( "muted", isMuted() );
|
||||
if( usesCustomClipColor() )
|
||||
{
|
||||
@@ -78,7 +79,8 @@ void PatternClip::loadSettings(const QDomElement& element)
|
||||
movePosition( element.attribute( "pos" ).toInt() );
|
||||
}
|
||||
changeLength( element.attribute( "len" ).toInt() );
|
||||
if( element.attribute( "muted" ).toInt() != isMuted() )
|
||||
setStartTimeOffset(element.attribute("off").toInt());
|
||||
if (static_cast<bool>(element.attribute("muted").toInt()) != isMuted())
|
||||
{
|
||||
toggleMute();
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace lmms
|
||||
|
||||
/*! The black / white order of keys as they appear on the keyboard.
|
||||
*/
|
||||
static const Piano::KeyTypes KEY_ORDER[] =
|
||||
static const auto KEY_ORDER = std::array
|
||||
{
|
||||
// C CIS D DIS
|
||||
Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey,
|
||||
@@ -62,10 +62,10 @@ static const Piano::KeyTypes KEY_ORDER[] =
|
||||
*
|
||||
* \param _it the InstrumentTrack window to attach to
|
||||
*/
|
||||
Piano::Piano( InstrumentTrack* track ) :
|
||||
Model( nullptr ), /*!< base class ctor */
|
||||
m_instrumentTrack( track ),
|
||||
m_midiEvProc( track ) /*!< the InstrumentTrack Model */
|
||||
Piano::Piano(InstrumentTrack* track) :
|
||||
Model(nullptr), /*!< base class ctor */
|
||||
m_instrumentTrack(track),
|
||||
m_midiEvProc(track) /*!< the InstrumentTrack Model */
|
||||
{
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ Piano::Piano( InstrumentTrack* track ) :
|
||||
* \param key the key number to change
|
||||
* \param state the state to set the key to
|
||||
*/
|
||||
void Piano::setKeyState( int key, bool state )
|
||||
void Piano::setKeyState(int key, bool state)
|
||||
{
|
||||
if( isValidKey( key ) )
|
||||
if (isValidKey(key))
|
||||
{
|
||||
m_pressedKeys[key] = state;
|
||||
|
||||
@@ -91,15 +91,15 @@ void Piano::setKeyState( int key, bool state )
|
||||
*
|
||||
* \param key the key being pressed
|
||||
*/
|
||||
void Piano::handleKeyPress( int key, int midiVelocity )
|
||||
void Piano::handleKeyPress(int key, int midiVelocity)
|
||||
{
|
||||
if( midiVelocity == -1 )
|
||||
if (midiVelocity == -1)
|
||||
{
|
||||
midiVelocity = m_instrumentTrack->midiPort()->baseVelocity();
|
||||
}
|
||||
if( isValidKey( key ) )
|
||||
if (isValidKey(key))
|
||||
{
|
||||
m_midiEvProc->processInEvent( MidiEvent( MidiNoteOn, -1, key, midiVelocity ) );
|
||||
m_midiEvProc->processInEvent(MidiEvent(MidiNoteOn, -1, key, midiVelocity));
|
||||
m_pressedKeys[key] = true;
|
||||
}
|
||||
}
|
||||
@@ -112,18 +112,18 @@ void Piano::handleKeyPress( int key, int midiVelocity )
|
||||
*
|
||||
* \param key the key being releassed
|
||||
*/
|
||||
void Piano::handleKeyRelease( int key )
|
||||
void Piano::handleKeyRelease(int key)
|
||||
{
|
||||
if( isValidKey( key ) )
|
||||
if (isValidKey(key))
|
||||
{
|
||||
m_midiEvProc->processInEvent( MidiEvent( MidiNoteOff, -1, key, 0 ) );
|
||||
m_midiEvProc->processInEvent(MidiEvent(MidiNoteOff, -1, key, 0));
|
||||
m_pressedKeys[key] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Piano::isBlackKey( int key )
|
||||
bool Piano::isBlackKey(int key)
|
||||
{
|
||||
int keyCode = key % KeysPerOctave;
|
||||
|
||||
@@ -131,9 +131,9 @@ bool Piano::isBlackKey( int key )
|
||||
}
|
||||
|
||||
|
||||
bool Piano::isWhiteKey( int key )
|
||||
bool Piano::isWhiteKey(int key)
|
||||
{
|
||||
return !isBlackKey( key );
|
||||
return !isBlackKey(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -105,12 +105,12 @@ PluginFactory* getPluginFactory()
|
||||
return PluginFactory::instance();
|
||||
}
|
||||
|
||||
const Plugin::DescriptorList PluginFactory::descriptors() const
|
||||
Plugin::DescriptorList PluginFactory::descriptors() const
|
||||
{
|
||||
return m_descriptors.values();
|
||||
}
|
||||
|
||||
const Plugin::DescriptorList PluginFactory::descriptors(Plugin::PluginTypes type) const
|
||||
Plugin::DescriptorList PluginFactory::descriptors(Plugin::PluginTypes type) const
|
||||
{
|
||||
return m_descriptors.values(type);
|
||||
}
|
||||
@@ -120,12 +120,12 @@ const PluginFactory::PluginInfoList& PluginFactory::pluginInfos() const
|
||||
return m_pluginInfos;
|
||||
}
|
||||
|
||||
const PluginFactory::PluginInfoAndKey PluginFactory::pluginSupportingExtension(const QString& ext)
|
||||
PluginFactory::PluginInfoAndKey PluginFactory::pluginSupportingExtension(const QString& ext)
|
||||
{
|
||||
return m_pluginByExt.value(ext, PluginInfoAndKey());
|
||||
}
|
||||
|
||||
const PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const
|
||||
PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const
|
||||
{
|
||||
for (const PluginInfo& info : m_pluginInfos)
|
||||
{
|
||||
@@ -248,7 +248,7 @@ void PluginFactory::discoverPlugins()
|
||||
|
||||
|
||||
|
||||
const QString PluginFactory::PluginInfo::name() const
|
||||
QString PluginFactory::PluginInfo::name() const
|
||||
{
|
||||
return descriptor ? descriptor->name : QString();
|
||||
}
|
||||
|
||||
@@ -39,18 +39,18 @@ namespace lmms
|
||||
{
|
||||
|
||||
|
||||
const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
const std::array<ProjectRenderer::FileEncodeDevice, 5> ProjectRenderer::fileEncodeDevices
|
||||
{
|
||||
|
||||
{ ProjectRenderer::WaveFile,
|
||||
FileEncodeDevice{ ProjectRenderer::WaveFile,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "WAV (*.wav)" ),
|
||||
".wav", &AudioFileWave::getInst },
|
||||
{ ProjectRenderer::FlacFile,
|
||||
FileEncodeDevice{ ProjectRenderer::FlacFile,
|
||||
QT_TRANSLATE_NOOP("ProjectRenderer", "FLAC (*.flac)"),
|
||||
".flac",
|
||||
&AudioFileFlac::getInst
|
||||
},
|
||||
{ ProjectRenderer::OggFile,
|
||||
FileEncodeDevice{ ProjectRenderer::OggFile,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "OGG (*.ogg)" ),
|
||||
".ogg",
|
||||
#ifdef LMMS_HAVE_OGGVORBIS
|
||||
@@ -59,7 +59,7 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
nullptr
|
||||
#endif
|
||||
},
|
||||
{ ProjectRenderer::MP3File,
|
||||
FileEncodeDevice{ ProjectRenderer::MP3File,
|
||||
QT_TRANSLATE_NOOP( "ProjectRenderer", "MP3 (*.mp3)" ),
|
||||
".mp3",
|
||||
#ifdef LMMS_HAVE_MP3LAME
|
||||
@@ -71,7 +71,7 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
|
||||
// Insert your own file-encoder infos here.
|
||||
// Maybe one day the user can add own encoders inside the program.
|
||||
|
||||
{ ProjectRenderer::NumFileFormats, nullptr, nullptr, nullptr }
|
||||
FileEncodeDevice{ ProjectRenderer::NumFileFormats, nullptr, nullptr, nullptr }
|
||||
|
||||
} ;
|
||||
|
||||
@@ -224,8 +224,8 @@ void ProjectRenderer::updateConsoleProgress()
|
||||
{
|
||||
const int cols = 50;
|
||||
static int rot = 0;
|
||||
char buf[80];
|
||||
char prog[cols+1];
|
||||
auto buf = std::array<char, 80>{};
|
||||
auto prog = std::array<char, cols + 1>{};
|
||||
|
||||
for( int i = 0; i < cols; ++i )
|
||||
{
|
||||
@@ -234,12 +234,12 @@ void ProjectRenderer::updateConsoleProgress()
|
||||
prog[cols] = 0;
|
||||
|
||||
const auto activity = (const char*)"|/-\\";
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
sprintf( buf, "\r|%s| %3d%% %c ", prog, m_progress,
|
||||
std::fill(buf.begin(), buf.end(), 0);
|
||||
sprintf(buf.data(), "\r|%s| %3d%% %c ", prog.data(), m_progress,
|
||||
activity[rot] );
|
||||
rot = ( rot+1 ) % 4;
|
||||
|
||||
fprintf( stderr, "%s", buf );
|
||||
fprintf( stderr, "%s", buf.data() );
|
||||
fflush( stderr );
|
||||
}
|
||||
|
||||
|
||||
@@ -1067,7 +1067,7 @@ void SampleBuffer::visualize(
|
||||
float maxData = -1;
|
||||
float minData = 1;
|
||||
|
||||
float rmsData[2] = {0, 0};
|
||||
auto rmsData = std::array<float, 2>{};
|
||||
|
||||
// Find maximum and minimum samples within range
|
||||
for (int i = 0; i < fpp && frame + i <= last; ++i)
|
||||
|
||||
@@ -292,15 +292,15 @@ void SampleClip::loadSettings( const QDomElement & _this )
|
||||
if( sampleFile().isEmpty() && _this.hasAttribute( "data" ) )
|
||||
{
|
||||
m_sampleBuffer->loadFromBase64( _this.attribute( "data" ) );
|
||||
if (_this.hasAttribute("sample_rate"))
|
||||
{
|
||||
m_sampleBuffer->setSampleRate(_this.attribute("sample_rate").toInt());
|
||||
}
|
||||
}
|
||||
changeLength( _this.attribute( "len" ).toInt() );
|
||||
setMuted( _this.attribute( "muted" ).toInt() );
|
||||
setStartTimeOffset( _this.attribute( "off" ).toInt() );
|
||||
|
||||
if ( _this.hasAttribute( "sample_rate" ) ) {
|
||||
m_sampleBuffer->setSampleRate( _this.attribute( "sample_rate" ).toInt() );
|
||||
}
|
||||
|
||||
if( _this.hasAttribute( "color" ) )
|
||||
{
|
||||
useCustomClipColor( true );
|
||||
|
||||
@@ -116,7 +116,7 @@ Song::Song() :
|
||||
/* connect( &m_masterPitchModel, SIGNAL(dataChanged()),
|
||||
this, SLOT(masterPitchChanged()));*/
|
||||
|
||||
qRegisterMetaType<Note>( "Note" );
|
||||
qRegisterMetaType<lmms::Note>( "lmms::Note" );
|
||||
setType( SongContainer );
|
||||
|
||||
for (auto& scale : m_scales) {scale = std::make_shared<Scale>();}
|
||||
@@ -620,6 +620,7 @@ void Song::togglePause()
|
||||
{
|
||||
m_playing = false;
|
||||
m_paused = true;
|
||||
Engine::audioEngine()->clear();
|
||||
}
|
||||
|
||||
m_vstSyncController.setPlaybackState( m_playing );
|
||||
@@ -837,14 +838,6 @@ bpm_t Song::getTempo()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AutomationClip * Song::tempoAutomationClip()
|
||||
{
|
||||
return AutomationClip::globalAutomationClip( &m_tempoModel );
|
||||
}
|
||||
|
||||
|
||||
AutomatedValueMap Song::automatedValuesAt(TimePos time, int clipNum) const
|
||||
{
|
||||
return TrackContainer::automatedValuesFromTracks(TrackList{m_globalAutomationTrack} << tracks(), time, clipNum);
|
||||
@@ -1051,7 +1044,12 @@ void Song::loadProject( const QString & fileName )
|
||||
else
|
||||
{
|
||||
QTextStream(stderr) << tr("Can't load project: "
|
||||
"Project file contains local paths to plugins.") << endl;
|
||||
"Project file contains local paths to plugins.")
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5,15,0))
|
||||
<< Qt::endl;
|
||||
#else
|
||||
<< endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram
|
||||
|
||||
if (depth == OutputSettings::Depth_24Bit || depth == OutputSettings::Depth_32Bit) // Float encoding
|
||||
{
|
||||
std::unique_ptr<sample_t[]> buf{ new sample_t[frames*channels()] };
|
||||
auto buf = std::vector<sample_t>(frames * channels());
|
||||
for(fpp_t frame = 0; frame < frames; ++frame)
|
||||
{
|
||||
for(ch_cnt_t channel=0; channel<channels(); ++channel)
|
||||
@@ -107,13 +107,13 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram
|
||||
buf[frame*channels() + channel] = qMax( clipvalue, _ab[frame][channel] * master_gain );
|
||||
}
|
||||
}
|
||||
sf_writef_float(m_sf,static_cast<float*>(buf.get()),frames);
|
||||
sf_writef_float(m_sf, static_cast<float*>(buf.data()), frames);
|
||||
}
|
||||
else // integer PCM encoding
|
||||
{
|
||||
std::unique_ptr<int_sample_t[]> buf{ new int_sample_t[frames*channels()] };
|
||||
convertToS16(_ab, frames, master_gain, buf.get(), !isLittleEndian());
|
||||
sf_writef_short(m_sf, static_cast<short*>(buf.get()), frames);
|
||||
auto buf = std::vector<int_sample_t>(frames * channels());
|
||||
convertToS16(_ab, frames, master_gain, buf.data(), !isLittleEndian());
|
||||
sf_writef_short(m_sf, static_cast<short*>(buf.data()), frames);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Lv2ControlBase.cpp - Lv2 control base class
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -54,30 +54,7 @@ Lv2ControlBase::Lv2ControlBase(Model* that, const QString &uri) :
|
||||
{
|
||||
if (m_plugin)
|
||||
{
|
||||
int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo
|
||||
while (channelsLeft > 0)
|
||||
{
|
||||
std::unique_ptr<Lv2Proc> newOne = std::make_unique<Lv2Proc>(m_plugin, that);
|
||||
if (newOne->isValid())
|
||||
{
|
||||
channelsLeft -= std::max(
|
||||
1 + static_cast<bool>(newOne->inPorts().m_right),
|
||||
1 + static_cast<bool>(newOne->outPorts().m_right));
|
||||
Q_ASSERT(channelsLeft >= 0);
|
||||
m_procs.push_back(std::move(newOne));
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Failed instantiating LV2 processor";
|
||||
m_valid = false;
|
||||
channelsLeft = 0;
|
||||
}
|
||||
}
|
||||
if (m_valid)
|
||||
{
|
||||
m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size();
|
||||
linkAllModels();
|
||||
}
|
||||
init(that);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -94,6 +71,53 @@ Lv2ControlBase::~Lv2ControlBase() = default;
|
||||
|
||||
|
||||
|
||||
void Lv2ControlBase::init(Model* meAsModel)
|
||||
{
|
||||
int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo
|
||||
while (channelsLeft > 0)
|
||||
{
|
||||
std::unique_ptr<Lv2Proc> newOne = std::make_unique<Lv2Proc>(m_plugin, meAsModel);
|
||||
if (newOne->isValid())
|
||||
{
|
||||
channelsLeft -= std::max(
|
||||
1 + static_cast<bool>(newOne->inPorts().m_right),
|
||||
1 + static_cast<bool>(newOne->outPorts().m_right));
|
||||
Q_ASSERT(channelsLeft >= 0);
|
||||
m_procs.push_back(std::move(newOne));
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Failed instantiating LV2 processor";
|
||||
m_valid = false;
|
||||
channelsLeft = 0;
|
||||
}
|
||||
}
|
||||
if (m_valid)
|
||||
{
|
||||
m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size();
|
||||
linkAllModels();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Lv2ControlBase::shutdown()
|
||||
{
|
||||
// currently nothing to do here
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Lv2ControlBase::reload()
|
||||
{
|
||||
for (const auto& c : m_procs) { c->reload(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LinkedModelGroup *Lv2ControlBase::getGroup(std::size_t idx)
|
||||
{
|
||||
return (m_procs.size() > idx) ? m_procs[idx].get() : nullptr;
|
||||
@@ -183,14 +207,6 @@ void Lv2ControlBase::loadFile(const QString &file)
|
||||
|
||||
|
||||
|
||||
void Lv2ControlBase::reloadPlugin()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::size_t Lv2ControlBase::controlCount() const {
|
||||
std::size_t res = 0;
|
||||
for (const auto& c : m_procs) { res += c->controlCount(); }
|
||||
|
||||
@@ -105,6 +105,14 @@ void *&Lv2Features::operator[](const char *featName)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Lv2Features::clear()
|
||||
{
|
||||
m_featureByUri.clear();
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_HAVE_LV2
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Lv2Manager.cpp - Implementation of Lv2Manager class
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -60,6 +60,12 @@ const std::set<const char*, Lv2Manager::CmpStr> Lv2Manager::pluginBlacklist =
|
||||
"http://calf.sourceforge.net/plugins/TransientDesigner",
|
||||
"http://calf.sourceforge.net/plugins/Vinyl",
|
||||
|
||||
// https://gitlab.com/drobilla/blop-lv2/-/issues/3
|
||||
"http://drobilla.net/plugins/blop/pulse",
|
||||
"http://drobilla.net/plugins/blop/sawtooth",
|
||||
"http://drobilla.net/plugins/blop/square",
|
||||
"http://drobilla.net/plugins/blop/triangle",
|
||||
|
||||
// Visualization, meters, and scopes etc., won't work until we have gui support
|
||||
"http://distrho.sf.net/plugins/ProM",
|
||||
"http://distrho.sf.net/plugins/glBars",
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/resize-port/resize-port.h>
|
||||
#include <QDebug>
|
||||
#include <QDomDocument>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "AudioEngine.h"
|
||||
@@ -65,8 +66,8 @@ Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin,
|
||||
{
|
||||
unsigned maxPorts = lilv_plugin_get_num_ports(plugin);
|
||||
enum { inCount, outCount, maxCount };
|
||||
unsigned audioChannels[maxCount] = { 0, 0 }; // audio input and output count
|
||||
unsigned midiChannels[maxCount] = { 0, 0 }; // MIDI input and output count
|
||||
auto audioChannels = std::array<unsigned, maxCount>{}; // audio input and output count
|
||||
auto midiChannels = std::array<unsigned, maxCount>{}; // MIDI input and output count
|
||||
|
||||
const char* pluginUri = lilv_node_as_uri(lilv_plugin_get_uri(plugin));
|
||||
//qDebug() << "Checking plugin" << pluginUri << "...";
|
||||
@@ -175,6 +176,26 @@ Lv2Proc::~Lv2Proc() { shutdownPlugin(); }
|
||||
|
||||
|
||||
|
||||
void Lv2Proc::reload()
|
||||
{
|
||||
// save controls, which we want to keep
|
||||
QDomDocument doc;
|
||||
QDomElement controls = doc.createElement("controls");
|
||||
saveValues(doc, controls);
|
||||
// backup construction variables
|
||||
const LilvPlugin* plugin = m_plugin;
|
||||
Model* parent = Model::parentModel();
|
||||
// destroy everything using RAII ...
|
||||
this->~Lv2Proc();
|
||||
// ... and reuse it ("placement new")
|
||||
new (this) Lv2Proc(plugin, parent);
|
||||
// reload the controls
|
||||
loadValues(controls);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Lv2Proc::dumpPorts()
|
||||
{
|
||||
std::size_t num = 0;
|
||||
@@ -247,11 +268,11 @@ void Lv2Proc::copyModelsFromCore()
|
||||
ev.time.frames(Engine::framesPerTick()) + ev.offset;
|
||||
uint32_t type = Engine::getLv2Manager()->
|
||||
uridCache()[Lv2UridCache::Id::midi_MidiEvent];
|
||||
uint8_t buf[4];
|
||||
std::size_t bufsize = writeToByteSeq(ev.ev, buf, sizeof(buf));
|
||||
auto buf = std::array<uint8_t, 4>{};
|
||||
std::size_t bufsize = writeToByteSeq(ev.ev, buf.data(), buf.size());
|
||||
if(bufsize)
|
||||
{
|
||||
lv2_evbuf_write(&iter, atomStamp, type, bufsize, buf);
|
||||
lv2_evbuf_write(&iter, atomStamp, type, bufsize, buf.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,7 +445,10 @@ void Lv2Proc::shutdownPlugin()
|
||||
lilv_instance_deactivate(m_instance);
|
||||
lilv_instance_free(m_instance);
|
||||
m_instance = nullptr;
|
||||
|
||||
m_features.clear();
|
||||
}
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Plugin::Descriptor::SubPluginFeatures for
|
||||
* hosting LV2 plugins
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
@@ -81,7 +81,7 @@ void Lv2SubPluginFeatures::fillDescriptionWidget(QWidget *parent,
|
||||
|
||||
auto maker = new QWidget(parent);
|
||||
auto l = new QHBoxLayout(maker);
|
||||
l->setMargin(0);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
|
||||
auto maker_label = new QLabel(maker);
|
||||
@@ -98,7 +98,7 @@ void Lv2SubPluginFeatures::fillDescriptionWidget(QWidget *parent,
|
||||
|
||||
auto copyright = new QWidget(parent);
|
||||
l = new QHBoxLayout(copyright);
|
||||
l->setMargin(0);
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->setSpacing(0);
|
||||
copyright->setMinimumWidth(parent->minimumWidth());
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ void MidiAlsaRaw::sendByte( unsigned char c )
|
||||
|
||||
void MidiAlsaRaw::run()
|
||||
{
|
||||
unsigned char buf[128];
|
||||
auto buf = std::array<unsigned char, 128>{};
|
||||
//int cnt = 0;
|
||||
while( m_quit == false )
|
||||
{
|
||||
@@ -149,7 +149,7 @@ void MidiAlsaRaw::run()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
err = snd_rawmidi_read( m_input, buf, sizeof( buf ) );
|
||||
err = snd_rawmidi_read(m_input, buf.data(), buf.size());
|
||||
if( err == -EAGAIN )
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -241,7 +241,7 @@ void MidiAlsaSeq::applyPortMode( MidiPort * _port )
|
||||
m_seqMutex.lock();
|
||||
|
||||
// determine port-capabilities
|
||||
unsigned int caps[2] = { 0, 0 };
|
||||
auto caps = std::array<unsigned int, 2>{};
|
||||
|
||||
switch( _port->mode() )
|
||||
{
|
||||
|
||||
@@ -105,10 +105,10 @@ void MidiClientRaw::parseData( const unsigned char c )
|
||||
/* 'Process' system real-time messages */
|
||||
/*********************************************************************/
|
||||
/* There are not too many real-time messages that are of interest here.
|
||||
* They can occur anywhere, even in the middle of a noteon message!
|
||||
* They can occur anywhere, even in the middle of a noteon message!
|
||||
* Real-time range: 0xF8 .. 0xFF
|
||||
* Note: Real-time does not affect (running) status.
|
||||
*/
|
||||
*/
|
||||
if( c >= 0xF8 )
|
||||
{
|
||||
if( c == MidiSystemReset )
|
||||
@@ -124,13 +124,13 @@ void MidiClientRaw::parseData( const unsigned char c )
|
||||
/* 'Process' system common messages (again, just skip them) */
|
||||
/*********************************************************************/
|
||||
/* There are no system common messages that are of interest here.
|
||||
* System common range: 0xF0 .. 0xF7
|
||||
* System common range: 0xF0 .. 0xF7
|
||||
*/
|
||||
if( c > 0xF0 )
|
||||
{
|
||||
/* MIDI spec say: To ignore a non-real-time message, just discard all
|
||||
* data up to the next status byte. And our parser will ignore data
|
||||
* that is received without a valid status.
|
||||
* that is received without a valid status.
|
||||
* Note: system common cancels running status. */
|
||||
m_midiParseData.m_status = 0;
|
||||
return;
|
||||
@@ -186,14 +186,14 @@ void MidiClientRaw::parseData( const unsigned char c )
|
||||
/*********************************************************************/
|
||||
/* Send the event */
|
||||
/*********************************************************************/
|
||||
/* The event is ready-to-go. About 'running status':
|
||||
*
|
||||
/* The event is ready-to-go. About 'running status':
|
||||
*
|
||||
* The MIDI protocol has a built-in compression mechanism. If several
|
||||
* similar events are sent in-a-row, for example note-ons, then the
|
||||
* event type is only sent once. For this case, the last event type
|
||||
* (status) is remembered.
|
||||
* We simply keep the status as it is, just reset the parameter counter.
|
||||
* If another status byte comes in, it will overwrite the status.
|
||||
* If another status byte comes in, it will overwrite the status.
|
||||
*/
|
||||
m_midiParseData.m_midiEvent.setType(static_cast<MidiEventTypes>(m_midiParseData.m_status));
|
||||
m_midiParseData.m_midiEvent.setChannel(m_midiParseData.m_channel);
|
||||
@@ -224,7 +224,7 @@ void MidiClientRaw::parseData( const unsigned char c )
|
||||
m_midiParseData.m_midiEvent.setPitchBend((m_midiParseData.m_buffer[1] * 128) | m_midiParseData.m_buffer[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
// Unlikely
|
||||
return;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ void MidiClientRaw::processOutEvent(const MidiEvent& event, const TimePos&, cons
|
||||
|
||||
|
||||
// Taken from Nagano Daisuke's USB-MIDI driver
|
||||
static const unsigned char REMAINS_F0F6[] =
|
||||
static const auto REMAINS_F0F6 = std::array<unsigned char, 7>
|
||||
{
|
||||
0, /* 0xF0 */
|
||||
2, /* 0XF1 */
|
||||
@@ -282,7 +282,7 @@ static const unsigned char REMAINS_F0F6[] =
|
||||
1 /* 0XF6 */
|
||||
} ;
|
||||
|
||||
static const unsigned char REMAINS_80E0[] =
|
||||
static const auto REMAINS_80E0 = std::array<unsigned char, 7>
|
||||
{
|
||||
3, /* 0x8X Note Off */
|
||||
3, /* 0x9X Note On */
|
||||
|
||||
@@ -169,6 +169,12 @@ void MidiPort::processOutEvent( const MidiEvent& event, const TimePos& time )
|
||||
outEvent.setVelocity( fixedOutputVelocity() );
|
||||
}
|
||||
|
||||
if( fixedOutputNote() >= 0 &&
|
||||
( event.type() == MidiNoteOn || event.type() == MidiNoteOff || event.type() == MidiKeyPressure ) )
|
||||
{
|
||||
outEvent.setKey( fixedOutputNote() );
|
||||
}
|
||||
|
||||
m_midiClient->processOutEvent( outEvent, time, this );
|
||||
}
|
||||
}
|
||||
@@ -238,6 +244,7 @@ void MidiPort::loadSettings( const QDomElement& thisElement )
|
||||
m_outputControllerModel.loadSettings( thisElement, "outputcontroller" );
|
||||
m_fixedInputVelocityModel.loadSettings( thisElement, "fixedinputvelocity" );
|
||||
m_fixedOutputVelocityModel.loadSettings( thisElement, "fixedoutputvelocity" );
|
||||
m_fixedOutputNoteModel.loadSettings( thisElement, "fixedoutputnote" );
|
||||
m_outputProgramModel.loadSettings( thisElement, "outputprogram" );
|
||||
m_baseVelocityModel.loadSettings( thisElement, "basevelocity" );
|
||||
m_readableModel.loadSettings( thisElement, "readable" );
|
||||
|
||||
@@ -176,7 +176,7 @@ void AutomatableModelView::mousePressEvent( QMouseEvent* event )
|
||||
new gui::StringPairDrag( "automatable_model", QString::number( modelUntyped()->id() ), QPixmap(), widget() );
|
||||
event->accept();
|
||||
}
|
||||
else if( event->button() == Qt::MidButton )
|
||||
else if( event->button() == Qt::MiddleButton )
|
||||
{
|
||||
modelUntyped()->reset();
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ SET(LMMS_SRCS
|
||||
gui/widgets/NStateButton.cpp
|
||||
gui/widgets/Oscilloscope.cpp
|
||||
gui/widgets/PixmapButton.cpp
|
||||
gui/widgets/SimpleTextFloat.cpp
|
||||
gui/widgets/TabBar.cpp
|
||||
gui/widgets/TabWidget.cpp
|
||||
gui/widgets/TempoSyncKnob.cpp
|
||||
|
||||
@@ -42,7 +42,7 @@ EffectRackView::EffectRackView( EffectChain* model, QWidget* parent ) :
|
||||
ModelView( nullptr, this )
|
||||
{
|
||||
auto mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->setMargin( 5 );
|
||||
mainLayout->setContentsMargins(5, 5, 5, 5);
|
||||
|
||||
m_effectsGroupBox = new GroupBox( tr( "EFFECTS CHAIN" ) );
|
||||
mainLayout->addWidget( m_effectsGroupBox );
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QPainter>
|
||||
#include <QLayout>
|
||||
|
||||
#include "EffectView.h"
|
||||
#include "DummyEffect.h"
|
||||
@@ -47,9 +49,10 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
|
||||
PluginView( _model, _parent ),
|
||||
m_bg( embed::getIconPixmap( "effect_plugin" ) ),
|
||||
m_subWindow( nullptr ),
|
||||
m_controlView( nullptr )
|
||||
m_controlView(nullptr),
|
||||
m_dragging(false)
|
||||
{
|
||||
setFixedSize( EffectView::DEFAULT_WIDTH, 60 );
|
||||
setFixedSize(EffectView::DEFAULT_WIDTH, EffectView::DEFAULT_HEIGHT);
|
||||
|
||||
// Disable effects that are of type "DummyEffect"
|
||||
bool isEnabled = !dynamic_cast<DummyEffect *>( effect() );
|
||||
@@ -116,7 +119,10 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
|
||||
m_subWindow->hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_opacityEffect = new QGraphicsOpacityEffect(this);
|
||||
m_opacityEffect->setOpacity(1);
|
||||
setGraphicsEffect(m_opacityEffect);
|
||||
|
||||
//move above vst effect view creation
|
||||
//setModel( _model );
|
||||
@@ -208,6 +214,43 @@ void EffectView::contextMenuEvent( QContextMenuEvent * )
|
||||
|
||||
|
||||
|
||||
void EffectView::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
m_dragging = true;
|
||||
m_opacityEffect->setOpacity(0.3);
|
||||
QCursor c(Qt::SizeVerCursor);
|
||||
QApplication::setOverrideCursor(c);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectView::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
m_dragging = false;
|
||||
m_opacityEffect->setOpacity(1);
|
||||
QApplication::restoreOverrideCursor();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectView::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!m_dragging) { return; }
|
||||
if (event->pos().y() < 0)
|
||||
{
|
||||
moveUp();
|
||||
}
|
||||
else if (event->pos().y() > EffectView::DEFAULT_HEIGHT)
|
||||
{
|
||||
moveDown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EffectView::paintEvent( QPaintEvent * )
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ void FileBrowser::addContentCheckBox()
|
||||
auto filterWidget = new QWidget(contentParent());
|
||||
filterWidget->setFixedHeight(15);
|
||||
auto filterWidgetLayout = new QHBoxLayout(filterWidget);
|
||||
filterWidgetLayout->setMargin(0);
|
||||
filterWidgetLayout->setContentsMargins(0, 0, 0, 0);
|
||||
filterWidgetLayout->setSpacing(0);
|
||||
|
||||
auto configCheckBox = [this, &filterWidgetLayout](QCheckBox* box)
|
||||
@@ -119,7 +119,7 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter,
|
||||
searchWidget->setFixedHeight( 24 );
|
||||
|
||||
auto searchWidgetLayout = new QHBoxLayout(searchWidget);
|
||||
searchWidgetLayout->setMargin( 0 );
|
||||
searchWidgetLayout->setContentsMargins(0, 0, 0, 0);
|
||||
searchWidgetLayout->setSpacing( 0 );
|
||||
|
||||
m_filterEdit = new QLineEdit( searchWidget );
|
||||
@@ -229,26 +229,22 @@ void FileBrowser::reloadTree()
|
||||
|
||||
|
||||
|
||||
void FileBrowser::expandItems( QTreeWidgetItem * item, QList<QString> expandedDirs )
|
||||
void FileBrowser::expandItems(QTreeWidgetItem* item, QList<QString> expandedDirs)
|
||||
{
|
||||
int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount();
|
||||
for (int i = 0; i < numChildren; ++i)
|
||||
{
|
||||
QTreeWidgetItem * it = item ? item->child( i ) : m_fileBrowserTreeWidget->topLevelItem(i);
|
||||
if ( m_recurse )
|
||||
{
|
||||
it->setExpanded( true );
|
||||
}
|
||||
auto it = item ? item->child(i) : m_fileBrowserTreeWidget->topLevelItem(i);
|
||||
auto d = dynamic_cast<Directory*>(it);
|
||||
if (d)
|
||||
{
|
||||
d->update();
|
||||
bool expand = expandedDirs.contains( d->fullName() );
|
||||
d->setExpanded( expand );
|
||||
}
|
||||
if (m_recurse && it->childCount())
|
||||
{
|
||||
expandItems(it, expandedDirs);
|
||||
// Expanding is required when recursive to load in its contents, even if it's collapsed right afterward
|
||||
if (m_recurse) { d->setExpanded(true); }
|
||||
d->setExpanded(expandedDirs.contains(d->fullName()));
|
||||
if (m_recurse && it->childCount())
|
||||
{
|
||||
expandItems(it, expandedDirs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1006,88 +1002,34 @@ void Directory::update()
|
||||
|
||||
|
||||
|
||||
bool Directory::addItems(const QString & path )
|
||||
bool Directory::addItems(const QString& path)
|
||||
{
|
||||
QDir thisDir( path );
|
||||
if( !thisDir.isReadable() )
|
||||
QDir thisDir(path);
|
||||
if (!thisDir.isReadable()) { return false; }
|
||||
|
||||
treeWidget()->setUpdatesEnabled(false);
|
||||
|
||||
QFileInfoList entries = thisDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst | QDir::Name);
|
||||
for (auto& entry : entries)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
treeWidget()->setUpdatesEnabled( false );
|
||||
|
||||
bool added_something = false;
|
||||
|
||||
// try to add all directories from file system alphabetically into the tree
|
||||
QStringList files = thisDir.entryList( QDir::Dirs, QDir::Name );
|
||||
for( QStringList::const_iterator it = files.constBegin();
|
||||
it != files.constEnd(); ++it )
|
||||
{
|
||||
QString cur_file = *it;
|
||||
if( cur_file[0] != '.' )
|
||||
QString fileName = entry.fileName();
|
||||
if (entry.isDir())
|
||||
{
|
||||
bool orphan = true;
|
||||
for( int i = 0; i < childCount(); ++i )
|
||||
{
|
||||
auto d = dynamic_cast<Directory*>(child(i));
|
||||
if( d == nullptr || cur_file < d->text( 0 ) )
|
||||
{
|
||||
// insert before item, we're done
|
||||
insertChild( i, new Directory( cur_file,
|
||||
path, m_filter ) );
|
||||
orphan = false;
|
||||
m_dirCount++;
|
||||
break;
|
||||
}
|
||||
else if( cur_file == d->text( 0 ) )
|
||||
{
|
||||
// imagine we have top-level subdirs named "TripleOscillator" in
|
||||
// two directories from FileBrowser::m_directories
|
||||
// and imagine both have a sub folder named "xyz"
|
||||
// then only add one tree widget for both
|
||||
// so we don't add a new Directory - we just
|
||||
// add the path to the current directory
|
||||
d->addDirectory( path );
|
||||
orphan = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( orphan )
|
||||
{
|
||||
// it has not yet been added yet, so it's (lexically)
|
||||
// larger than all other dirs => append it at the bottom
|
||||
addChild( new Directory( cur_file, path,
|
||||
m_filter ) );
|
||||
m_dirCount++;
|
||||
}
|
||||
|
||||
added_something = true;
|
||||
auto dir = new Directory(fileName, path, m_filter);
|
||||
addChild(dir);
|
||||
m_dirCount++;
|
||||
}
|
||||
else if (entry.isFile() && thisDir.match(m_filter, fileName.toLower()))
|
||||
{
|
||||
auto fileItem = new FileItem(fileName, path);
|
||||
addChild(fileItem);
|
||||
}
|
||||
}
|
||||
|
||||
// sorts the path alphabetically instead of just appending to the bottom (see "orphans")
|
||||
if (added_something)
|
||||
sortChildren(0, Qt::AscendingOrder);
|
||||
|
||||
QList<QTreeWidgetItem*> items;
|
||||
files = thisDir.entryList( QDir::Files, QDir::Name );
|
||||
files.sort(Qt::CaseInsensitive);
|
||||
for( QStringList::const_iterator it = files.constBegin();
|
||||
it != files.constEnd(); ++it )
|
||||
{
|
||||
QString cur_file = *it;
|
||||
if( cur_file[0] != '.' &&
|
||||
thisDir.match( m_filter, cur_file.toLower() ) )
|
||||
{
|
||||
items << new FileItem( cur_file, path );
|
||||
added_something = true;
|
||||
}
|
||||
}
|
||||
addChildren( items );
|
||||
|
||||
treeWidget()->setUpdatesEnabled( true );
|
||||
|
||||
return added_something;
|
||||
|
||||
treeWidget()->setUpdatesEnabled(true);
|
||||
|
||||
// return true if we added any child items
|
||||
return childCount() > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1282,4 +1224,4 @@ QString FileItem::extension(const QString & file )
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
} // namespace lmms::gui
|
||||
|
||||
@@ -43,7 +43,7 @@ LadspaControlView::LadspaControlView( QWidget * _parent,
|
||||
m_ctl( _ctl )
|
||||
{
|
||||
auto layout = new QHBoxLayout(this);
|
||||
layout->setMargin( 0 );
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing( 0 );
|
||||
|
||||
LedCheckBox * link = nullptr;
|
||||
|
||||
@@ -167,31 +167,22 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent
|
||||
m_waveBtnGrp->addButton( m_userWaveBtn );
|
||||
|
||||
auto x1 = new PixmapButton(this, nullptr);
|
||||
x1->move( CD_LFO_MULTIPLIER_X, CD_LFO_SHAPES_Y +7);
|
||||
x1->setActiveGraphic( embed::getIconPixmap(
|
||||
"lfo_x1_active" ) );
|
||||
x1->setInactiveGraphic( embed::getIconPixmap(
|
||||
"lfo_x1_inactive" ) );
|
||||
x1->setToolTip(
|
||||
tr( "Mutliply modulation frequency by 1" ));
|
||||
x1->move(CD_LFO_MULTIPLIER_X, CD_LFO_SHAPES_Y + 7);
|
||||
x1->setActiveGraphic(embed::getIconPixmap("lfo_x1_active"));
|
||||
x1->setInactiveGraphic(embed::getIconPixmap("lfo_x1_inactive"));
|
||||
x1->setToolTip(tr("Multiply modulation frequency by 1"));
|
||||
|
||||
auto x100 = new PixmapButton(this, nullptr);
|
||||
x100->move( CD_LFO_MULTIPLIER_X, CD_LFO_SHAPES_Y - 8 );
|
||||
x100->setActiveGraphic( embed::getIconPixmap(
|
||||
"lfo_x100_active" ) );
|
||||
x100->setInactiveGraphic( embed::getIconPixmap(
|
||||
"lfo_x100_inactive" ) );
|
||||
x100->setToolTip(
|
||||
tr( "Mutliply modulation frequency by 100" ));
|
||||
x100->move(CD_LFO_MULTIPLIER_X, CD_LFO_SHAPES_Y - 8);
|
||||
x100->setActiveGraphic(embed::getIconPixmap("lfo_x100_active"));
|
||||
x100->setInactiveGraphic(embed::getIconPixmap("lfo_x100_inactive"));
|
||||
x100->setToolTip(tr("Multiply modulation frequency by 100"));
|
||||
|
||||
auto d100 = new PixmapButton(this, nullptr);
|
||||
d100->move( CD_LFO_MULTIPLIER_X, CD_LFO_SHAPES_Y + 22 );
|
||||
d100->setActiveGraphic( embed::getIconPixmap(
|
||||
"lfo_d100_active" ) );
|
||||
d100->setInactiveGraphic( embed::getIconPixmap(
|
||||
"lfo_d100_inactive" ) );
|
||||
d100->setToolTip(
|
||||
tr( "Divide modulation frequency by 100" ));
|
||||
d100->move(CD_LFO_MULTIPLIER_X, CD_LFO_SHAPES_Y + 22);
|
||||
d100->setActiveGraphic(embed::getIconPixmap("lfo_d100_active"));
|
||||
d100->setInactiveGraphic(embed::getIconPixmap("lfo_d100_inactive"));
|
||||
d100->setToolTip(tr("Divide modulation frequency by 100"));
|
||||
|
||||
m_multiplierBtnGrp = new automatableButtonGroup( this );
|
||||
m_multiplierBtnGrp->addButton( x1 );
|
||||
|
||||
@@ -75,7 +75,7 @@ QPalette LmmsPalette::palette() const
|
||||
{
|
||||
QPalette pal = QApplication::style()->standardPalette();
|
||||
|
||||
pal.setColor( QPalette::Background, background() );
|
||||
pal.setColor( QPalette::Window, background() );
|
||||
pal.setColor( QPalette::WindowText, windowText() );
|
||||
pal.setColor( QPalette::Base, base() );
|
||||
pal.setColor( QPalette::ButtonText, buttonText() );
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
@@ -71,7 +72,7 @@ QLinearGradient getGradient( const QColor & _col, const QRectF & _rect )
|
||||
QLinearGradient darken( const QLinearGradient & _gradient )
|
||||
{
|
||||
QGradientStops stops = _gradient.stops();
|
||||
for (auto& stop : stops)
|
||||
for (auto& stop : stops)
|
||||
{
|
||||
QColor color = stop.second;
|
||||
stop.second = color.lighter(133);
|
||||
@@ -188,7 +189,7 @@ void LmmsStyle::drawComplexControl( ComplexControl control,
|
||||
/* else if( control == CC_ScrollBar )
|
||||
{
|
||||
painter->fillRect( option->rect, QApplication::palette().color( QPalette::Active,
|
||||
QPalette::Background ) );
|
||||
QPalette::Window ) );
|
||||
|
||||
}*/
|
||||
QProxyStyle::drawComplexControl( control, option, painter, widget );
|
||||
@@ -216,8 +217,8 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
int a50 = static_cast<int>( a100 * .6 );
|
||||
int a25 = static_cast<int>( a100 * .33 );
|
||||
|
||||
QLine lines[4];
|
||||
QPoint points[4];
|
||||
auto lines = std::array<QLine, 4>{};
|
||||
auto points = std::array<QPoint, 4>{};
|
||||
|
||||
// black inside lines
|
||||
// 50%
|
||||
@@ -231,7 +232,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
rect.left() + 1, rect.bottom() - 2);
|
||||
lines[3] = QLine(rect.right() - 1, rect.top() + 2,
|
||||
rect.right() - 1, rect.bottom() - 2);
|
||||
painter->drawLines(lines, 4);
|
||||
painter->drawLines(lines.data(), 4);
|
||||
|
||||
// black inside dots
|
||||
black.setAlpha(a50);
|
||||
@@ -240,7 +241,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
points[1] = QPoint(rect.left() + 2, rect.bottom() - 2);
|
||||
points[2] = QPoint(rect.right() - 2, rect.top() + 2);
|
||||
points[3] = QPoint(rect.right() - 2, rect.bottom() - 2);
|
||||
painter->drawPoints(points, 4);
|
||||
painter->drawPoints(points.data(), 4);
|
||||
|
||||
|
||||
// outside lines - shadow
|
||||
@@ -251,7 +252,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
rect.right() - 2, rect.top());
|
||||
lines[1] = QLine(rect.left(), rect.top() + 2,
|
||||
rect.left(), rect.bottom() - 2);
|
||||
painter->drawLines(lines, 2);
|
||||
painter->drawLines(lines.data(), 2);
|
||||
|
||||
// outside corner dots - shadow
|
||||
// 75%
|
||||
@@ -259,7 +260,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
painter->setPen(QPen(shadow, 0));
|
||||
points[0] = QPoint(rect.left() + 1, rect.top() + 1);
|
||||
points[1] = QPoint(rect.right() - 1, rect.top() + 1);
|
||||
painter->drawPoints(points, 2);
|
||||
painter->drawPoints(points.data(), 2);
|
||||
|
||||
// outside end dots - shadow
|
||||
// 50%
|
||||
@@ -269,7 +270,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
points[1] = QPoint(rect.left(), rect.top() + 1);
|
||||
points[2] = QPoint(rect.right() - 1, rect.top());
|
||||
points[3] = QPoint(rect.left(), rect.bottom() - 1);
|
||||
painter->drawPoints(points, 4);
|
||||
painter->drawPoints(points.data(), 4);
|
||||
|
||||
|
||||
// outside lines - highlight
|
||||
@@ -280,7 +281,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
rect.right() - 2, rect.bottom());
|
||||
lines[1] = QLine(rect.right(), rect.top() + 2,
|
||||
rect.right(), rect.bottom() - 2);
|
||||
painter->drawLines(lines, 2);
|
||||
painter->drawLines(lines.data(), 2);
|
||||
|
||||
// outside corner dots - highlight
|
||||
// 75%
|
||||
@@ -288,7 +289,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
painter->setPen(QPen(highlight, 0));
|
||||
points[0] = QPoint(rect.left() + 1, rect.bottom() - 1);
|
||||
points[1] = QPoint(rect.right() - 1, rect.bottom() - 1);
|
||||
painter->drawPoints(points, 2);
|
||||
painter->drawPoints(points.data(), 2);
|
||||
|
||||
// outside end dots - highlight
|
||||
// 50%
|
||||
@@ -298,7 +299,7 @@ void LmmsStyle::drawPrimitive( PrimitiveElement element,
|
||||
points[1] = QPoint(rect.right(), rect.bottom() - 1);
|
||||
points[2] = QPoint(rect.left() + 1, rect.bottom());
|
||||
points[3] = QPoint(rect.right(), rect.top() + 1);
|
||||
painter->drawPoints(points, 4);
|
||||
painter->drawPoints(points.data(), 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Lv2ViewBase.cpp - base class for Lv2 plugin views
|
||||
*
|
||||
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
* Copyright (c) 2018-2023 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
|
||||
@@ -39,6 +39,19 @@ MainApplication::MainApplication(int& argc, char** argv) :
|
||||
QApplication(argc, argv),
|
||||
m_queuedFile()
|
||||
{
|
||||
#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU)
|
||||
// Work around a bug of KXmlGui < 5.55
|
||||
// which breaks the recent files menu
|
||||
// https://bugs.kde.org/show_bug.cgi?id=337491
|
||||
for (auto child : children())
|
||||
{
|
||||
if (child->inherits("KCheckAcceleratorsInitializer"))
|
||||
{
|
||||
delete child;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LMMS_BUILD_WIN32)
|
||||
installNativeEventFilter(this);
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QShortcut>
|
||||
#include <QLibrary>
|
||||
#include <QSplitter>
|
||||
|
||||
#include "AboutDialog.h"
|
||||
@@ -78,22 +77,6 @@
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU)
|
||||
//Work around an issue on KDE5 as per https://bugs.kde.org/show_bug.cgi?id=337491#c21
|
||||
void disableAutoKeyAccelerators(QWidget* mainWindow)
|
||||
{
|
||||
using DisablerFunc = void(*)(QWidget*);
|
||||
QLibrary kf5WidgetsAddon("KF5WidgetsAddons", 5);
|
||||
auto setNoAccelerators
|
||||
= reinterpret_cast<DisablerFunc>(kf5WidgetsAddon.resolve("_ZN19KAcceleratorManager10setNoAccelEP7QWidget"));
|
||||
if(setNoAccelerators)
|
||||
{
|
||||
setNoAccelerators(mainWindow);
|
||||
}
|
||||
kf5WidgetsAddon.unload();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
MainWindow::MainWindow() :
|
||||
m_workspace( nullptr ),
|
||||
@@ -103,20 +86,17 @@ MainWindow::MainWindow() :
|
||||
m_metronomeToggle( 0 ),
|
||||
m_session( Normal )
|
||||
{
|
||||
#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU)
|
||||
disableAutoKeyAccelerators(this);
|
||||
#endif
|
||||
setAttribute( Qt::WA_DeleteOnClose );
|
||||
|
||||
auto main_widget = new QWidget(this);
|
||||
auto vbox = new QVBoxLayout(main_widget);
|
||||
vbox->setSpacing( 0 );
|
||||
vbox->setMargin( 0 );
|
||||
vbox->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto w = new QWidget(main_widget);
|
||||
auto hbox = new QHBoxLayout(w);
|
||||
hbox->setSpacing( 0 );
|
||||
hbox->setMargin( 0 );
|
||||
hbox->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto sideBar = new SideBar(Qt::Vertical, w);
|
||||
|
||||
@@ -226,7 +206,7 @@ MainWindow::MainWindow() :
|
||||
|
||||
// add layout for organizing quite complex toolbar-layouting
|
||||
m_toolBarLayout = new QGridLayout( m_toolBar/*, 2, 1*/ );
|
||||
m_toolBarLayout->setMargin( 0 );
|
||||
m_toolBarLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_toolBarLayout->setSpacing( 0 );
|
||||
|
||||
vbox->addWidget( m_toolBar );
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QLayout>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QStyle>
|
||||
@@ -59,7 +61,7 @@ MixerView::MixerView() :
|
||||
m->setHook( this );
|
||||
|
||||
//QPalette pal = palette();
|
||||
//pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) );
|
||||
//pal.setColor( QPalette::Window, QColor( 72, 76, 88 ) );
|
||||
//setPalette( pal );
|
||||
|
||||
setAutoFillBackground( true );
|
||||
@@ -79,7 +81,7 @@ MixerView::MixerView() :
|
||||
chLayout = new QHBoxLayout( m_channelAreaWidget );
|
||||
chLayout->setSizeConstraint( QLayout::SetMinimumSize );
|
||||
chLayout->setSpacing( 0 );
|
||||
chLayout->setMargin( 0 );
|
||||
chLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_channelAreaWidget->setLayout(chLayout);
|
||||
|
||||
// create rack layout before creating the first channel
|
||||
@@ -385,6 +387,12 @@ void MixerView::deleteChannel(int index)
|
||||
// can't delete master
|
||||
if( index == 0 ) return;
|
||||
|
||||
// if there is no user confirmation, do nothing
|
||||
if (!confirmRemoval(index))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// remember selected line
|
||||
int selLine = m_currentMixerLine->channelIndex();
|
||||
|
||||
@@ -397,7 +405,7 @@ void MixerView::deleteChannel(int index)
|
||||
|
||||
// delete the view
|
||||
chLayout->removeWidget(m_mixerChannelViews[index]->m_mixerLine);
|
||||
m_racksLayout->removeWidget( m_mixerChannelViews[index]->m_rackView );
|
||||
m_racksLayout->removeWidget(m_mixerChannelViews[index]->m_rackView);
|
||||
delete m_mixerChannelViews[index]->m_fader;
|
||||
delete m_mixerChannelViews[index]->m_muteBtn;
|
||||
delete m_mixerChannelViews[index]->m_soloBtn;
|
||||
@@ -409,56 +417,74 @@ void MixerView::deleteChannel(int index)
|
||||
m_channelAreaWidget->adjustSize();
|
||||
|
||||
// make sure every channel knows what index it is
|
||||
for(int i=index + 1; i<m_mixerChannelViews.size(); ++i)
|
||||
for (int i = index + 1; i < m_mixerChannelViews.size(); ++i)
|
||||
{
|
||||
m_mixerChannelViews[i]->m_mixerLine->setChannelIndex(i-1);
|
||||
m_mixerChannelViews[i]->m_mixerLine->setChannelIndex(i - 1);
|
||||
}
|
||||
m_mixerChannelViews.remove(index);
|
||||
|
||||
// select the next channel
|
||||
if( selLine >= m_mixerChannelViews.size() )
|
||||
if (selLine >= m_mixerChannelViews.size())
|
||||
{
|
||||
selLine = m_mixerChannelViews.size()-1;
|
||||
selLine = m_mixerChannelViews.size() - 1;
|
||||
}
|
||||
setCurrentMixerLine(selLine);
|
||||
|
||||
updateMaxChannelSelector();
|
||||
}
|
||||
|
||||
bool MixerView::confirmRemoval(int index)
|
||||
{
|
||||
// if config variable is set to false, there is no need for user confirmation
|
||||
bool needConfirm = ConfigManager::inst()->value("ui", "mixerchanneldeletionwarning", "1").toInt();
|
||||
if (!needConfirm) { return true; }
|
||||
|
||||
Mixer* mix = Engine::mixer();
|
||||
|
||||
if (!mix->isChannelInUse(index))
|
||||
{
|
||||
// is the channel is not in use, there is no need for user confirmation
|
||||
return true;
|
||||
}
|
||||
|
||||
QString messageRemoveTrack = tr("This Mixer Channel is being used.\n"
|
||||
"Are you sure you want to remove this channel?\n\n"
|
||||
"Warning: This operation can not be undone.");
|
||||
|
||||
QString messageTitleRemoveTrack = tr("Confirm removal");
|
||||
QString askAgainText = tr("Don't ask again");
|
||||
auto askAgainCheckBox = new QCheckBox(askAgainText, nullptr);
|
||||
connect(askAgainCheckBox, &QCheckBox::stateChanged, [this](int state) {
|
||||
// Invert button state, if it's checked we *shouldn't* ask again
|
||||
ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning", state ? "0" : "1");
|
||||
});
|
||||
|
||||
QMessageBox mb(this);
|
||||
mb.setText(messageRemoveTrack);
|
||||
mb.setWindowTitle(messageTitleRemoveTrack);
|
||||
mb.setIcon(QMessageBox::Warning);
|
||||
mb.addButton(QMessageBox::Cancel);
|
||||
mb.addButton(QMessageBox::Ok);
|
||||
mb.setCheckBox(askAgainCheckBox);
|
||||
mb.setDefaultButton(QMessageBox::Cancel);
|
||||
|
||||
int answer = mb.exec();
|
||||
|
||||
return answer == QMessageBox::Ok;
|
||||
}
|
||||
|
||||
|
||||
void MixerView::deleteUnusedChannels()
|
||||
{
|
||||
TrackContainer::TrackList tracks;
|
||||
tracks += Engine::getSong()->tracks();
|
||||
tracks += Engine::patternStore()->tracks();
|
||||
Mixer* mix = Engine::mixer();
|
||||
|
||||
std::vector<bool> inUse(m_mixerChannelViews.size(), false);
|
||||
|
||||
//Populate inUse by checking the destination channel for every track
|
||||
for (Track* t: tracks)
|
||||
// Check all channels except master, delete those with no incoming sends
|
||||
for (int i = m_mixerChannelViews.size() - 1; i > 0; --i)
|
||||
{
|
||||
//The channel that this track sends to. Since master channel is always in use,
|
||||
//setting this to 0 is a safe default (for tracks that don't sent to the mixer).
|
||||
int channel = 0;
|
||||
if (t->type() == Track::InstrumentTrack)
|
||||
if (!mix->isChannelInUse(i))
|
||||
{
|
||||
auto inst = dynamic_cast<InstrumentTrack*>(t);
|
||||
channel = inst->mixerChannelModel()->value();
|
||||
deleteChannel(i);
|
||||
}
|
||||
else if (t->type() == Track::SampleTrack)
|
||||
{
|
||||
auto strack = dynamic_cast<SampleTrack*>(t);
|
||||
channel = strack->mixerChannelModel()->value();
|
||||
}
|
||||
inUse[channel] = true;
|
||||
}
|
||||
|
||||
//Check all channels except master, delete those with no incoming sends
|
||||
for(int i = m_mixerChannelViews.size()-1; i > 0; --i)
|
||||
{
|
||||
if (!inUse[i] && Engine::mixer()->mixerChannel(i)->m_receives.isEmpty())
|
||||
{ deleteChannel(i); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
@@ -34,7 +35,10 @@
|
||||
|
||||
#include "embed.h"
|
||||
#include "Engine.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "Song.h"
|
||||
#include "StringPairDrag.h"
|
||||
#include "TrackContainerView.h"
|
||||
#include "PluginFactory.h"
|
||||
|
||||
namespace lmms::gui
|
||||
@@ -52,7 +56,7 @@ PluginBrowser::PluginBrowser( QWidget * _parent ) :
|
||||
addContentWidget( m_view );
|
||||
|
||||
auto view_layout = new QVBoxLayout(m_view);
|
||||
view_layout->setMargin( 5 );
|
||||
view_layout->setContentsMargins(5, 5, 5, 5);
|
||||
view_layout->setSpacing( 5 );
|
||||
|
||||
|
||||
@@ -287,4 +291,24 @@ void PluginDescWidget::mousePressEvent( QMouseEvent * _me )
|
||||
}
|
||||
|
||||
|
||||
void PluginDescWidget::contextMenuEvent(QContextMenuEvent* e)
|
||||
{
|
||||
QMenu contextMenu(this);
|
||||
contextMenu.addAction(
|
||||
tr("Send to new instrument track"),
|
||||
[=]{ openInNewInstrumentTrack(m_pluginKey.desc->name); }
|
||||
);
|
||||
contextMenu.exec(e->globalPos());
|
||||
}
|
||||
|
||||
|
||||
void PluginDescWidget::openInNewInstrumentTrack(QString value)
|
||||
{
|
||||
TrackContainer* tc = Engine::getSong();
|
||||
auto it = dynamic_cast<InstrumentTrack*>(Track::create(Track::InstrumentTrack, tc));
|
||||
auto ilt = new InstrumentLoaderThread(this, it, value);
|
||||
ilt->start();
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
@@ -57,7 +57,7 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) :
|
||||
// init own layout + widgets
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
auto vlayout = new QVBoxLayout(this);
|
||||
vlayout->setMargin(0);
|
||||
vlayout->setContentsMargins(0, 0, 0, 0);
|
||||
vlayout->setSpacing(0);
|
||||
|
||||
auto generalSettingsWidget = new TabWidget(tr("GENERAL SETTINGS"), this);
|
||||
|
||||
@@ -44,7 +44,7 @@ SideBarWidget::SideBarWidget( const QString & _title, const QPixmap & _icon,
|
||||
m_contents = new QWidget( this );
|
||||
m_layout = new QVBoxLayout( m_contents );
|
||||
m_layout->setSpacing( 5 );
|
||||
m_layout->setMargin( 0 );
|
||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||
m_closeBtn = new QPushButton(embed::getIconPixmap("close"), QString(), this);
|
||||
m_closeBtn->resize(m_buttonSize);
|
||||
m_closeBtn->setToolTip(tr("Close"));
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
#include "MidiClip.h"
|
||||
#include "MidiClipView.h"
|
||||
#include "Note.h"
|
||||
#include "PatternClip.h"
|
||||
#include "PatternStore.h"
|
||||
#include "SampleClip.h"
|
||||
#include "Song.h"
|
||||
#include "SongEditor.h"
|
||||
@@ -502,10 +504,11 @@ void ClipView::dropEvent( QDropEvent * de )
|
||||
void ClipView::updateCursor(QMouseEvent * me)
|
||||
{
|
||||
auto sClip = dynamic_cast<SampleClip*>(m_clip);
|
||||
auto pClip = dynamic_cast<PatternClip*>(m_clip);
|
||||
|
||||
// If we are at the edges, use the resize cursor
|
||||
if (!me->buttons() && !m_clip->getAutoResize() && !isSelected()
|
||||
&& ((me->x() > width() - RESIZE_GRIP_WIDTH) || (me->x() < RESIZE_GRIP_WIDTH && sClip)))
|
||||
&& ((me->x() > width() - RESIZE_GRIP_WIDTH) || (me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip))))
|
||||
{
|
||||
setCursor(Qt::SizeHorCursor);
|
||||
}
|
||||
@@ -633,6 +636,7 @@ void ClipView::mousePressEvent( QMouseEvent * me )
|
||||
if( !fixedClips() && me->button() == Qt::LeftButton )
|
||||
{
|
||||
auto sClip = dynamic_cast<SampleClip*>(m_clip);
|
||||
auto pClip = dynamic_cast<PatternClip*>(m_clip);
|
||||
const bool knifeMode = m_trackView->trackContainerView()->knifeMode();
|
||||
|
||||
if ( me->modifiers() & Qt::ControlModifier && !(sClip && knifeMode) )
|
||||
@@ -677,7 +681,7 @@ void ClipView::mousePressEvent( QMouseEvent * me )
|
||||
m_action = Resize;
|
||||
setCursor( Qt::SizeHorCursor );
|
||||
}
|
||||
else if( me->x() < RESIZE_GRIP_WIDTH && sClip )
|
||||
else if( me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip) )
|
||||
{
|
||||
m_action = ResizeLeft;
|
||||
setCursor( Qt::SizeHorCursor );
|
||||
@@ -836,7 +840,6 @@ void ClipView::mouseMoveEvent( QMouseEvent * me )
|
||||
if( m_action == Move )
|
||||
{
|
||||
TimePos newPos = draggedClipPos( me );
|
||||
|
||||
m_clip->movePosition(newPos);
|
||||
newPos = m_clip->startPosition(); // Get the real position the Clip was dragged to for the label
|
||||
m_trackView->getTrackContentWidget()->changePosition();
|
||||
@@ -916,7 +919,8 @@ void ClipView::mouseMoveEvent( QMouseEvent * me )
|
||||
else
|
||||
{
|
||||
auto sClip = dynamic_cast<SampleClip*>(m_clip);
|
||||
if( sClip )
|
||||
auto pClip = dynamic_cast<PatternClip*>(m_clip);
|
||||
if( sClip || pClip )
|
||||
{
|
||||
const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x();
|
||||
|
||||
@@ -948,12 +952,27 @@ void ClipView::mouseMoveEvent( QMouseEvent * me )
|
||||
t = qMin<int>( m_initialClipEnd - minLength, m_initialClipPos + offset );
|
||||
}
|
||||
|
||||
TimePos oldPos = m_clip->startPosition();
|
||||
if( m_clip->length() + ( oldPos - t ) >= 1 )
|
||||
TimePos positionOffset = m_clip->startPosition() - t;
|
||||
if (m_clip->length() + positionOffset >= 1)
|
||||
{
|
||||
m_clip->movePosition( t );
|
||||
m_clip->changeLength( m_clip->length() + ( oldPos - t ) );
|
||||
sClip->setStartTimeOffset( sClip->startTimeOffset() + ( oldPos - t ) );
|
||||
m_clip->movePosition(t);
|
||||
m_clip->changeLength(m_clip->length() + positionOffset);
|
||||
if (sClip)
|
||||
{
|
||||
sClip->setStartTimeOffset(sClip->startTimeOffset() + positionOffset);
|
||||
}
|
||||
else if (pClip)
|
||||
{
|
||||
// Modulus the start time offset as we need it only for offsets
|
||||
// inside the pattern length. This is done to prevent a value overflow.
|
||||
// The start time offset may still become larger than the pattern length
|
||||
// whenever the pattern length decreases without a clip resize following.
|
||||
// To deal safely with it, always modulus before use.
|
||||
tick_t patternLength = Engine::patternStore()->lengthOfPattern(pClip->patternIndex())
|
||||
* TimePos::ticksPerBar();
|
||||
TimePos position = (pClip->startTimeOffset() + positionOffset) % patternLength;
|
||||
pClip->setStartTimeOffset(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,14 +115,18 @@ void PatternClipView::paintEvent(QPaintEvent*)
|
||||
|
||||
// bar lines
|
||||
const int lineSize = 3;
|
||||
int pixelsPerPattern = Engine::patternStore()->lengthOfPattern(m_patternClip->patternIndex()) * pixelsPerBar();
|
||||
int offset = static_cast<int>(m_patternClip->startTimeOffset() * (pixelsPerBar() / TimePos::ticksPerBar()))
|
||||
% pixelsPerPattern;
|
||||
if (offset < 2) {
|
||||
offset += pixelsPerPattern;
|
||||
}
|
||||
|
||||
p.setPen( c.darker( 200 ) );
|
||||
|
||||
bar_t t = Engine::patternStore()->lengthOfPattern(m_patternClip->patternIndex());
|
||||
if (m_patternClip->length() > TimePos::ticksPerBar() && t > 0)
|
||||
if (pixelsPerPattern > 0)
|
||||
{
|
||||
for( int x = static_cast<int>( t * pixelsPerBar() );
|
||||
x < width() - 2;
|
||||
x += static_cast<int>( t * pixelsPerBar() ) )
|
||||
for (int x = offset; x < width() - 2; x += pixelsPerPattern)
|
||||
{
|
||||
p.drawLine( x, BORDER_WIDTH, x, BORDER_WIDTH + lineSize );
|
||||
p.drawLine( x, rect().bottom() - ( BORDER_WIDTH + lineSize ),
|
||||
|
||||
@@ -968,8 +968,8 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
|
||||
{
|
||||
if( m_y_auto )
|
||||
{
|
||||
int y[] = { grid_bottom, TOP_MARGIN + font_height / 2 };
|
||||
float level[] = { m_minLevel, m_maxLevel };
|
||||
auto y = std::array{grid_bottom, TOP_MARGIN + font_height / 2};
|
||||
auto level = std::array{m_minLevel, m_maxLevel};
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
const QString & label = m_clip->firstObject()
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "PatternStore.h"
|
||||
#include "PianoView.h"
|
||||
#include "PositionLine.h"
|
||||
#include "SimpleTextFloat.h"
|
||||
#include "SongEditor.h"
|
||||
#include "StepRecorderWidget.h"
|
||||
#include "TextFloat.h"
|
||||
@@ -127,9 +128,9 @@ QPixmap * PianoRoll::s_toolMove = nullptr;
|
||||
QPixmap * PianoRoll::s_toolOpen = nullptr;
|
||||
QPixmap* PianoRoll::s_toolKnife = nullptr;
|
||||
|
||||
TextFloat * PianoRoll::s_textFloat = nullptr;
|
||||
SimpleTextFloat * PianoRoll::s_textFloat = nullptr;
|
||||
|
||||
static QString s_noteStrings[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
|
||||
static std::array<QString, 12> s_noteStrings {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
|
||||
|
||||
static QString getNoteString(int key)
|
||||
{
|
||||
@@ -137,7 +138,7 @@ static QString getNoteString(int key)
|
||||
}
|
||||
|
||||
// used for drawing of piano
|
||||
PianoRoll::PianoRollKeyTypes PianoRoll::prKeyOrder[] =
|
||||
std::array<PianoRoll::PianoRollKeyTypes, 12> PianoRoll::prKeyOrder
|
||||
{
|
||||
PR_WHITE_KEY_SMALL, PR_BLACK_KEY, PR_WHITE_KEY_BIG, PR_BLACK_KEY,
|
||||
PR_WHITE_KEY_SMALL, PR_WHITE_KEY_SMALL, PR_BLACK_KEY, PR_WHITE_KEY_BIG,
|
||||
@@ -290,7 +291,7 @@ PianoRoll::PianoRoll() :
|
||||
// init text-float
|
||||
if( s_textFloat == nullptr )
|
||||
{
|
||||
s_textFloat = new TextFloat;
|
||||
s_textFloat = new SimpleTextFloat;
|
||||
}
|
||||
|
||||
setAttribute( Qt::WA_OpaquePaintEvent, true );
|
||||
@@ -369,10 +370,10 @@ PianoRoll::PianoRoll() :
|
||||
// Set up note length model
|
||||
m_noteLenModel.addItem( tr( "Last note" ),
|
||||
std::make_unique<PixmapLoader>( "edit_draw" ) );
|
||||
const QString pixmaps[] = { "whole", "half", "quarter", "eighth",
|
||||
const auto pixmaps = std::array<QString, 11>{"whole", "half", "quarter", "eighth",
|
||||
"sixteenth", "thirtysecond", "triplethalf",
|
||||
"tripletquarter", "tripleteighth",
|
||||
"tripletsixteenth", "tripletthirtysecond" } ;
|
||||
"tripletsixteenth", "tripletthirtysecond"};
|
||||
|
||||
for( int i = 0; i < NUM_EVEN_LENGTHS; ++i )
|
||||
{
|
||||
@@ -600,7 +601,7 @@ void PianoRoll::markSemiTone(int i, bool fromMenu)
|
||||
|
||||
const int first = chord->isScale() ? 0 : key;
|
||||
const int last = chord->isScale() ? NumKeys : key + chord->last();
|
||||
const int cap = ( chord->isScale() || chord->last() == 0 ) ? KeysPerOctave : chord->last();
|
||||
const int cap = (chord->isScale() || chord->last() == 0) ? trackOctaveSize() : chord->last();
|
||||
|
||||
for( int i = first; i <= last; i++ )
|
||||
{
|
||||
@@ -858,8 +859,7 @@ void PianoRoll::setCurrentMidiClip( MidiClip* newMidiClip )
|
||||
}
|
||||
|
||||
// force the song-editor to stop playing if it played a MIDI clip before
|
||||
if( Engine::getSong()->isPlaying() &&
|
||||
Engine::getSong()->playMode() == Song::Mode_PlayMidiClip )
|
||||
if (Engine::getSong()->playMode() == Song::Mode_PlayMidiClip)
|
||||
{
|
||||
Engine::getSong()->playMidiClip( nullptr );
|
||||
}
|
||||
@@ -938,6 +938,15 @@ void PianoRoll::hideMidiClip( MidiClip* clip )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PianoRoll::trackOctaveSize() const
|
||||
{
|
||||
if (!m_midiClip) { return KeysPerOctave; }
|
||||
auto ut = m_midiClip->instrumentTrack()->microtuner();
|
||||
return ut->enabled() ? ut->octaveSize() : KeysPerOctave;
|
||||
}
|
||||
|
||||
|
||||
void PianoRoll::selectRegionFromPixels( int xStart, int xEnd )
|
||||
{
|
||||
|
||||
@@ -3951,7 +3960,8 @@ QList<int> PianoRoll::getAllOctavesForKey( int keyToMirror ) const
|
||||
{
|
||||
QList<int> keys;
|
||||
|
||||
for (int i=keyToMirror % KeysPerOctave; i < NumKeys; i += KeysPerOctave)
|
||||
int trackKeysPerOctave = trackOctaveSize();
|
||||
for (int i = keyToMirror % trackKeysPerOctave; i < NumKeys; i += trackKeysPerOctave)
|
||||
{
|
||||
keys.append(i);
|
||||
}
|
||||
@@ -5180,6 +5190,8 @@ void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de )
|
||||
de.appendChild(markedSemiTonesRoot);
|
||||
}
|
||||
|
||||
de.setAttribute("stopbehaviour", m_editor->m_timeLine->behaviourAtStop());
|
||||
|
||||
MainWindow::saveWidgetState( this, de );
|
||||
}
|
||||
|
||||
@@ -5193,6 +5205,8 @@ void PianoRollWindow::loadSettings( const QDomElement & de )
|
||||
|
||||
MainWindow::restoreWidgetState( this, de );
|
||||
|
||||
m_editor->m_timeLine->setBehaviourAtStop(de.attribute("stopbehaviour").toInt());
|
||||
|
||||
// update margins here because we're later in the startup process
|
||||
// We can't earlier because everything is still starting with the
|
||||
// WHITE_KEY_WIDTH default
|
||||
|
||||
@@ -213,7 +213,7 @@ SongEditor::SongEditor( Song * song ) :
|
||||
// create widget for oscilloscope- and cpu-load-widget
|
||||
auto vc_w = new QWidget(tb);
|
||||
auto vcw_layout = new QVBoxLayout(vc_w);
|
||||
vcw_layout->setMargin( 0 );
|
||||
vcw_layout->setContentsMargins(0, 0, 0, 0);
|
||||
vcw_layout->setSpacing( 0 );
|
||||
|
||||
vcw_layout->addStretch();
|
||||
|
||||
@@ -90,13 +90,13 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) :
|
||||
//keeps the direction of the widget, undepended on the locale
|
||||
setLayoutDirection( Qt::LeftToRight );
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setMargin( 0 );
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing( 0 );
|
||||
layout->addWidget( m_scrollArea );
|
||||
|
||||
auto scrollContent = new QWidget;
|
||||
m_scrollLayout = new QVBoxLayout( scrollContent );
|
||||
m_scrollLayout->setMargin( 0 );
|
||||
m_scrollLayout->setContentsMargins(0, 0, 0, 0);
|
||||
m_scrollLayout->setSpacing( 0 );
|
||||
m_scrollLayout->setSizeConstraint( QLayout::SetMinAndMaxSize );
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ InstrumentFunctionNoteStackingView::InstrumentFunctionNoteStackingView( Instrume
|
||||
m_chordRangeKnob( new Knob( knobBright_26 ) )
|
||||
{
|
||||
auto topLayout = new QHBoxLayout(this);
|
||||
topLayout->setMargin( 0 );
|
||||
topLayout->setContentsMargins(0, 0, 0, 0);
|
||||
topLayout->addWidget( m_chordsGroupBox );
|
||||
|
||||
auto mainLayout = new QGridLayout(m_chordsGroupBox);
|
||||
@@ -109,7 +109,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti
|
||||
m_arpModeComboBox( new ComboBox() )
|
||||
{
|
||||
auto topLayout = new QHBoxLayout(this);
|
||||
topLayout->setMargin( 0 );
|
||||
topLayout->setContentsMargins(0, 0, 0, 0);
|
||||
topLayout->addWidget( m_arpGroupBox );
|
||||
|
||||
auto mainLayout = new QGridLayout(m_arpGroupBox);
|
||||
|
||||
@@ -48,7 +48,7 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget* parent ) :
|
||||
m_wpBtn( nullptr )
|
||||
{
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setMargin( 5 );
|
||||
layout->setContentsMargins(5, 5, 5, 5);
|
||||
m_midiInputGroupBox = new GroupBox( tr( "ENABLE MIDI INPUT" ) );
|
||||
layout->addWidget( m_midiInputGroupBox );
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ InstrumentMiscView::InstrumentMiscView(InstrumentTrack *it, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setMargin(5);
|
||||
layout->setContentsMargins(5, 5, 5, 5);
|
||||
|
||||
// Master pitch toggle
|
||||
m_pitchGroupBox = new GroupBox(tr("GLOBAL TRANSPOSITION"));
|
||||
|
||||
@@ -90,7 +90,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) :
|
||||
// init own layout + widgets
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
auto vlayout = new QVBoxLayout(this);
|
||||
vlayout->setMargin( 0 );
|
||||
vlayout->setContentsMargins(0, 0, 0, 0);
|
||||
vlayout->setSpacing( 0 );
|
||||
|
||||
auto generalSettingsWidget = new TabWidget(tr("GENERAL SETTINGS"), this);
|
||||
@@ -246,7 +246,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) :
|
||||
// FUNC tab
|
||||
auto instrumentFunctions = new QWidget(m_tabWidget);
|
||||
auto instrumentFunctionsLayout = new QVBoxLayout(instrumentFunctions);
|
||||
instrumentFunctionsLayout->setMargin( 5 );
|
||||
instrumentFunctionsLayout->setContentsMargins(5, 5, 5, 5);
|
||||
m_noteStackingView = new InstrumentFunctionNoteStackingView( &m_track->m_noteStacking );
|
||||
m_arpeggioView = new InstrumentFunctionArpeggioView( &m_track->m_arpeggio );
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace lmms::gui
|
||||
|
||||
/*! The scale of C Major - white keys only.
|
||||
*/
|
||||
Keys WhiteKeys[] =
|
||||
auto WhiteKeys = std::array
|
||||
{
|
||||
Key_C, Key_D, Key_E, Key_F, Key_G, Key_A, Key_H
|
||||
} ;
|
||||
@@ -147,7 +147,7 @@ PianoView::PianoView(QWidget *parent) :
|
||||
// create a layout for ourselves
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setSpacing( 0 );
|
||||
layout->setMargin( 0 );
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addSpacing( PIANO_BASE+PW_WHITE_KEY_HEIGHT );
|
||||
layout->addWidget( m_pianoScroll );
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent,
|
||||
|
||||
auto btn_layout = new QHBoxLayout(buttons);
|
||||
btn_layout->setSpacing( 0 );
|
||||
btn_layout->setMargin( 0 );
|
||||
btn_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto select_btn = new QPushButton(embed::getIconPixmap("add"), tr("OK"), buttons);
|
||||
connect( select_btn, SIGNAL(clicked()),
|
||||
|
||||
@@ -213,14 +213,14 @@ void EffectSelectDialog::rowChanged( const QModelIndex & _idx,
|
||||
hbox->addWidget(textualInfoWidget);
|
||||
|
||||
auto textWidgetLayout = new QVBoxLayout(textualInfoWidget);
|
||||
textWidgetLayout->setMargin( 4 );
|
||||
textWidgetLayout->setContentsMargins(4, 4, 4, 4);
|
||||
textWidgetLayout->setSpacing( 0 );
|
||||
|
||||
if ( m_currentSelection.desc->subPluginFeatures )
|
||||
{
|
||||
auto subWidget = new QWidget(textualInfoWidget);
|
||||
auto subLayout = new QVBoxLayout(subWidget);
|
||||
subLayout->setMargin( 4 );
|
||||
subLayout->setContentsMargins(4, 4, 4, 4);
|
||||
subLayout->setSpacing( 0 );
|
||||
m_currentSelection.desc->subPluginFeatures->
|
||||
fillDescriptionWidget( subWidget, &m_currentSelection );
|
||||
|
||||
@@ -79,14 +79,14 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name,
|
||||
cbIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int const MAX_LEVEL=8;
|
||||
for(int i=0; i<=MAX_LEVEL; ++i)
|
||||
{
|
||||
QString info="";
|
||||
if ( i==0 ){ info = tr( "( Fastest - biggest )" ); }
|
||||
else if ( i==MAX_LEVEL ){ info = tr( "( Slowest - smallest )" ); }
|
||||
|
||||
|
||||
compLevelCB->addItem(
|
||||
QString::number(i)+" "+info,
|
||||
QVariant(i/static_cast<double>(MAX_LEVEL))
|
||||
@@ -159,8 +159,8 @@ void ExportProjectDialog::startExport()
|
||||
static_cast<AudioEngine::qualitySettings::Interpolation>(interpolationCB->currentIndex()),
|
||||
static_cast<AudioEngine::qualitySettings::Oversampling>(oversamplingCB->currentIndex()) );
|
||||
|
||||
const int samplerates[5] = { 44100, 48000, 88200, 96000, 192000 };
|
||||
const bitrate_t bitrates[6] = { 64, 128, 160, 192, 256, 320 };
|
||||
const auto samplerates = std::array{44100, 48000, 88200, 96000, 192000};
|
||||
const auto bitrates = std::array{64, 128, 160, 192, 256, 320};
|
||||
|
||||
bool useVariableBitRate = checkBoxVariableBitRate->isChecked();
|
||||
|
||||
|
||||
@@ -112,6 +112,8 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
"app", "sololegacybehavior", "0").toInt()),
|
||||
m_trackDeletionWarning(ConfigManager::inst()->value(
|
||||
"ui", "trackdeletionwarning", "1").toInt()),
|
||||
m_mixerChannelDeletionWarning(ConfigManager::inst()->value(
|
||||
"ui", "mixerchanneldeletionwarning", "1").toInt()),
|
||||
m_MMPZ(!ConfigManager::inst()->value(
|
||||
"app", "nommpz").toInt()),
|
||||
m_disableBackup(!ConfigManager::inst()->value(
|
||||
@@ -175,12 +177,12 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
// Vertical layout.
|
||||
auto vlayout = new QVBoxLayout(this);
|
||||
vlayout->setSpacing(0);
|
||||
vlayout->setMargin(0);
|
||||
vlayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// Horizontal layout.
|
||||
auto hlayout = new QHBoxLayout(main_w);
|
||||
hlayout->setSpacing(0);
|
||||
hlayout->setMargin(0);
|
||||
hlayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// Tab bar for the main tabs.
|
||||
m_tabBar = new TabBar(main_w, QBoxLayout::TopToBottom);
|
||||
@@ -195,9 +197,21 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
auto general_w = new QWidget(settings_w);
|
||||
auto general_layout = new QVBoxLayout(general_w);
|
||||
general_layout->setSpacing(10);
|
||||
general_layout->setMargin(0);
|
||||
general_layout->setContentsMargins(0, 0, 0, 0);
|
||||
labelWidget(general_w, tr("General"));
|
||||
|
||||
// General scroll area.
|
||||
auto generalScroll = new QScrollArea(general_w);
|
||||
generalScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
generalScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
// General controls widget.
|
||||
auto generalControls = new QWidget(general_w);
|
||||
|
||||
// Path selectors layout.
|
||||
auto generalControlsLayout = new QVBoxLayout;
|
||||
generalControlsLayout->setSpacing(10);
|
||||
|
||||
auto addLedCheckBox = [&XDelta, &YDelta, this](const QString& ledText, TabWidget* tw, int& counter,
|
||||
bool initialState, const char* toggledSlot, bool showRestartWarning) {
|
||||
auto checkBox = new LedCheckBox(ledText, tw);
|
||||
@@ -214,7 +228,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
int counter = 0;
|
||||
|
||||
// GUI tab.
|
||||
auto gui_tw = new TabWidget(tr("Graphical user interface (GUI)"), general_w);
|
||||
auto gui_tw = new TabWidget(tr("Graphical user interface (GUI)"), generalControls);
|
||||
|
||||
addLedCheckBox(tr("Display volume as dBFS "), gui_tw, counter,
|
||||
m_displaydBFS, SLOT(toggleDisplaydBFS(bool)), true);
|
||||
@@ -236,14 +250,19 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
m_soloLegacyBehavior, SLOT(toggleSoloLegacyBehavior(bool)), false);
|
||||
addLedCheckBox(tr("Show warning when deleting tracks"), gui_tw, counter,
|
||||
m_trackDeletionWarning, SLOT(toggleTrackDeletionWarning(bool)), false);
|
||||
addLedCheckBox(tr("Show warning when deleting a mixer channel that is in use"), gui_tw, counter,
|
||||
m_mixerChannelDeletionWarning, SLOT(toggleMixerChannelDeletionWarning(bool)), false);
|
||||
|
||||
gui_tw->setFixedHeight(YDelta + YDelta * counter);
|
||||
|
||||
generalControlsLayout->addWidget(gui_tw);
|
||||
generalControlsLayout->addSpacing(10);
|
||||
|
||||
|
||||
counter = 0;
|
||||
|
||||
// Projects tab.
|
||||
auto projects_tw = new TabWidget(tr("Projects"), general_w);
|
||||
auto projects_tw = new TabWidget(tr("Projects"), generalControls);
|
||||
|
||||
addLedCheckBox(tr("Compress project files by default"), projects_tw, counter,
|
||||
m_MMPZ, SLOT(toggleMMPZ(bool)), true);
|
||||
@@ -254,8 +273,12 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
|
||||
projects_tw->setFixedHeight(YDelta + YDelta * counter);
|
||||
|
||||
generalControlsLayout->addWidget(projects_tw);
|
||||
generalControlsLayout->addSpacing(10);
|
||||
|
||||
|
||||
// Language tab.
|
||||
auto lang_tw = new TabWidget(tr("Language"), general_w);
|
||||
auto lang_tw = new TabWidget(tr("Language"), generalControls);
|
||||
lang_tw->setFixedHeight(48);
|
||||
auto changeLang = new QComboBox(lang_tw);
|
||||
changeLang->move(XDelta, 20);
|
||||
@@ -310,11 +333,15 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
connect(changeLang, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(showRestartWarning()));
|
||||
|
||||
generalControlsLayout->addWidget(lang_tw);
|
||||
generalControlsLayout->addSpacing(10);
|
||||
|
||||
// General layout ordering.
|
||||
general_layout->addWidget(gui_tw);
|
||||
general_layout->addWidget(projects_tw);
|
||||
general_layout->addWidget(lang_tw);
|
||||
generalControlsLayout->addStretch();
|
||||
generalControls->setLayout(generalControlsLayout);
|
||||
generalScroll->setWidget(generalControls);
|
||||
generalScroll->setWidgetResizable(true);
|
||||
general_layout->addWidget(generalScroll);
|
||||
general_layout->addStretch();
|
||||
|
||||
|
||||
@@ -324,7 +351,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
auto performance_w = new QWidget(settings_w);
|
||||
auto performance_layout = new QVBoxLayout(performance_w);
|
||||
performance_layout->setSpacing(10);
|
||||
performance_layout->setMargin(0);
|
||||
performance_layout->setContentsMargins(0, 0, 0, 0);
|
||||
labelWidget(performance_w,
|
||||
tr("Performance"));
|
||||
|
||||
@@ -442,7 +469,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
auto audio_w = new QWidget(settings_w);
|
||||
auto audio_layout = new QVBoxLayout(audio_w);
|
||||
audio_layout->setSpacing(10);
|
||||
audio_layout->setMargin(0);
|
||||
audio_layout->setContentsMargins(0, 0, 0, 0);
|
||||
labelWidget(audio_w,
|
||||
tr("Audio"));
|
||||
|
||||
@@ -460,7 +487,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
|
||||
auto as_w_layout = new QHBoxLayout(as_w);
|
||||
as_w_layout->setSpacing(0);
|
||||
as_w_layout->setMargin(0);
|
||||
as_w_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
#ifdef LMMS_HAVE_JACK
|
||||
m_audioIfaceSetupWidgets[AudioJack::name()] =
|
||||
@@ -592,7 +619,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
auto midi_w = new QWidget(settings_w);
|
||||
auto midi_layout = new QVBoxLayout(midi_w);
|
||||
midi_layout->setSpacing(10);
|
||||
midi_layout->setMargin(0);
|
||||
midi_layout->setContentsMargins(0, 0, 0, 0);
|
||||
labelWidget(midi_w,
|
||||
tr("MIDI"));
|
||||
|
||||
@@ -609,7 +636,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
|
||||
auto ms_w_layout = new QHBoxLayout(ms_w);
|
||||
ms_w_layout->setSpacing(0);
|
||||
ms_w_layout->setMargin(0);
|
||||
ms_w_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
#ifdef LMMS_HAVE_ALSA
|
||||
m_midiIfaceSetupWidgets[MidiAlsaSeq::name()] =
|
||||
@@ -709,7 +736,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
|
||||
auto paths_layout = new QVBoxLayout(paths_w);
|
||||
paths_layout->setSpacing(10);
|
||||
paths_layout->setMargin(0);
|
||||
paths_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
labelWidget(paths_w, tr("Paths"));
|
||||
|
||||
@@ -823,7 +850,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) :
|
||||
auto extras_w = new QWidget(this);
|
||||
auto extras_layout = new QHBoxLayout(extras_w);
|
||||
extras_layout->setSpacing(0);
|
||||
extras_layout->setMargin(0);
|
||||
extras_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// Restart warning label.
|
||||
restartWarningLbl = new QLabel(
|
||||
@@ -896,6 +923,8 @@ void SetupDialog::accept()
|
||||
QString::number(m_soloLegacyBehavior));
|
||||
ConfigManager::inst()->setValue("ui", "trackdeletionwarning",
|
||||
QString::number(m_trackDeletionWarning));
|
||||
ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning",
|
||||
QString::number(m_mixerChannelDeletionWarning));
|
||||
ConfigManager::inst()->setValue("app", "nommpz",
|
||||
QString::number(!m_MMPZ));
|
||||
ConfigManager::inst()->setValue("app", "disablebackup",
|
||||
@@ -1017,6 +1046,11 @@ void SetupDialog::toggleTrackDeletionWarning(bool enabled)
|
||||
m_trackDeletionWarning = enabled;
|
||||
}
|
||||
|
||||
void SetupDialog::toggleMixerChannelDeletionWarning(bool enabled)
|
||||
{
|
||||
m_mixerChannelDeletionWarning = enabled;
|
||||
}
|
||||
|
||||
|
||||
void SetupDialog::toggleMMPZ(bool enabled)
|
||||
{
|
||||
|
||||
@@ -211,7 +211,7 @@ InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow()
|
||||
getGUI()->mainWindow()->workspace()->subWindowList(
|
||||
QMdiArea::ActivationHistoryOrder ) )
|
||||
{
|
||||
if( sw->isVisible() && sw->widget()->inherits( "InstrumentTrackWindow" ) )
|
||||
if( sw->isVisible() && sw->widget()->inherits( "lmms::gui::InstrumentTrackWindow" ) )
|
||||
{
|
||||
w = qobject_cast<InstrumentTrackWindow *>( sw->widget() );
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) :
|
||||
m_panningKnob->show();
|
||||
|
||||
m_activityIndicator = new FadeButton(
|
||||
QApplication::palette().color(QPalette::Active, QPalette::Background),
|
||||
QApplication::palette().color(QPalette::Active, QPalette::Window),
|
||||
QApplication::palette().color(QPalette::Active, QPalette::BrightText),
|
||||
QApplication::palette().color(QPalette::Active, QPalette::BrightText).darker(),
|
||||
getTrackSettingsWidget()
|
||||
|
||||
@@ -105,6 +105,7 @@ void TrackLabelButton::renameFinished()
|
||||
{
|
||||
if( !( ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt() ) )
|
||||
{
|
||||
m_renameLineEdit->clearFocus();
|
||||
m_renameLineEdit->hide();
|
||||
if( m_renameLineEdit->text() != "" )
|
||||
{
|
||||
|
||||
@@ -75,7 +75,7 @@ TrackView::TrackView( Track * track, TrackContainerView * tcv ) :
|
||||
m_trackSettingsWidget.setAutoFillBackground( true );
|
||||
|
||||
auto layout = new QHBoxLayout(this);
|
||||
layout->setMargin( 0 );
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing( 0 );
|
||||
layout->addWidget( &m_trackOperationsWidget );
|
||||
layout->addWidget( &m_trackSettingsWidget );
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
* CustomTextKnob.cpp
|
||||
*
|
||||
* Copyright (c) 2020 Ibuki Sugiyama <main/at/fuwa.dev>
|
||||
*
|
||||
* 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 "CustomTextKnob.h"
|
||||
|
||||
namespace lmms::gui
|
||||
|
||||
@@ -54,13 +54,13 @@
|
||||
#include "embed.h"
|
||||
#include "CaptionMenu.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "TextFloat.h"
|
||||
#include "SimpleTextFloat.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
TextFloat * Fader::s_textFloat = nullptr;
|
||||
SimpleTextFloat * Fader::s_textFloat = nullptr;
|
||||
QPixmap * Fader::s_back = nullptr;
|
||||
QPixmap * Fader::s_leds = nullptr;
|
||||
QPixmap * Fader::s_knob = nullptr;
|
||||
@@ -83,7 +83,7 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) :
|
||||
{
|
||||
if( s_textFloat == nullptr )
|
||||
{
|
||||
s_textFloat = new TextFloat;
|
||||
s_textFloat = new SimpleTextFloat;
|
||||
}
|
||||
if( ! s_back )
|
||||
{
|
||||
@@ -125,7 +125,7 @@ Fader::Fader( FloatModel * model, const QString & name, QWidget * parent, QPixma
|
||||
{
|
||||
if( s_textFloat == nullptr )
|
||||
{
|
||||
s_textFloat = new TextFloat;
|
||||
s_textFloat = new SimpleTextFloat;
|
||||
}
|
||||
|
||||
m_back = back;
|
||||
@@ -328,7 +328,8 @@ void Fader::updateTextFloat()
|
||||
{
|
||||
s_textFloat->setText( m_description + " " + QString("%1 ").arg( model()->value() * m_conversionFactor ) + " " + m_unit );
|
||||
}
|
||||
s_textFloat->moveGlobal( this, QPoint( width() - ( *m_knob ).width() - 5, knobPosY() - 46 ) );
|
||||
|
||||
s_textFloat->moveGlobal(this, QPoint(width() + 2, knobPosY() - s_textFloat->height() / 2));
|
||||
}
|
||||
|
||||
|
||||
@@ -483,4 +484,4 @@ void Fader::setPeakYellow( const QColor & c )
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
} // namespace lmms::gui
|
||||
|
||||
@@ -45,14 +45,14 @@
|
||||
#include "LocaleHelper.h"
|
||||
#include "MainWindow.h"
|
||||
#include "ProjectJournal.h"
|
||||
#include "SimpleTextFloat.h"
|
||||
#include "StringPairDrag.h"
|
||||
#include "TextFloat.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
TextFloat * Knob::s_textFloat = nullptr;
|
||||
SimpleTextFloat * Knob::s_textFloat = nullptr;
|
||||
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ void Knob::initUi( const QString & _name )
|
||||
{
|
||||
if( s_textFloat == nullptr )
|
||||
{
|
||||
s_textFloat = new TextFloat;
|
||||
s_textFloat = new SimpleTextFloat;
|
||||
}
|
||||
|
||||
setWindowTitle( _name );
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "CaptionMenu.h"
|
||||
#include "DeprecationHelper.h"
|
||||
#include "embed.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "gui_templates.h"
|
||||
@@ -179,7 +180,7 @@ void LcdFloatSpinBox::mouseReleaseEvent(QMouseEvent*)
|
||||
void LcdFloatSpinBox::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
// switch between integer and fractional step based on cursor position
|
||||
if (event->x() < m_wholeDisplay.width()) { m_intStep = true; }
|
||||
if (position(event).x() < m_wholeDisplay.width()) { m_intStep = true; }
|
||||
else { m_intStep = false; }
|
||||
|
||||
event->accept();
|
||||
@@ -239,9 +240,9 @@ void LcdFloatSpinBox::paintEvent(QPaintEvent*)
|
||||
{
|
||||
p.setFont(pointSizeF(p.font(), 6.5));
|
||||
p.setPen(m_wholeDisplay.textShadowColor());
|
||||
p.drawText(width() / 2 - p.fontMetrics().width(m_label) / 2 + 1, height(), m_label);
|
||||
p.drawText(width() / 2 - horizontalAdvance(p.fontMetrics(), m_label) / 2 + 1, height(), m_label);
|
||||
p.setPen(m_wholeDisplay.textColor());
|
||||
p.drawText(width() / 2 - p.fontMetrics().width(m_label) / 2, height() - 1, m_label);
|
||||
p.drawText(width() / 2 - horizontalAdvance(p.fontMetrics(), m_label) / 2, height() - 1, m_label);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
static const QString names[LedCheckBox::NumColors] =
|
||||
static const auto names = std::array<QString, 3>
|
||||
{
|
||||
"led_yellow", "led_green", "led_red"
|
||||
} ;
|
||||
|
||||
@@ -43,12 +43,12 @@ MeterDialog::MeterDialog( QWidget * _parent, bool _simple ) :
|
||||
{
|
||||
auto vlayout = new QVBoxLayout(this);
|
||||
vlayout->setSpacing( 0 );
|
||||
vlayout->setMargin( 0 );
|
||||
vlayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto num = new QWidget(this);
|
||||
auto num_layout = new QHBoxLayout(num);
|
||||
num_layout->setSpacing( 0 );
|
||||
num_layout->setMargin( 0 );
|
||||
num_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
|
||||
m_numerator = new LcdSpinBox( 2, num, tr( "Meter Numerator" ) );
|
||||
@@ -69,7 +69,7 @@ MeterDialog::MeterDialog( QWidget * _parent, bool _simple ) :
|
||||
auto den = new QWidget(this);
|
||||
auto den_layout = new QHBoxLayout(den);
|
||||
den_layout->setSpacing( 0 );
|
||||
den_layout->setMargin( 0 );
|
||||
den_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_denominator = new LcdSpinBox( 2, den, tr( "Meter Denominator" ) );
|
||||
m_denominator->setToolTip(tr("Meter denominator"));
|
||||
|
||||
62
src/gui/widgets/SimpleTextFloat.cpp
Normal file
62
src/gui/widgets/SimpleTextFloat.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* TextFloat.cpp - class textFloat, a floating text-label
|
||||
*
|
||||
* Copyright (c) LMMS team
|
||||
*
|
||||
* 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 "SimpleTextFloat.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QStyleOption>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "GuiApplication.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
SimpleTextFloat::SimpleTextFloat() :
|
||||
QWidget(getGUI()->mainWindow(), Qt::ToolTip)
|
||||
{
|
||||
QHBoxLayout * layout = new QHBoxLayout(this);
|
||||
layout->setMargin(3);
|
||||
setLayout(layout);
|
||||
|
||||
m_textLabel = new QLabel(this);
|
||||
layout->addWidget(m_textLabel);
|
||||
}
|
||||
|
||||
void SimpleTextFloat::setText(const QString & text)
|
||||
{
|
||||
m_textLabel->setText(text);
|
||||
}
|
||||
|
||||
|
||||
void SimpleTextFloat::setVisibilityTimeOut(int msecs)
|
||||
{
|
||||
QTimer::singleShot(msecs, this, SLOT(hide()));
|
||||
show();
|
||||
}
|
||||
|
||||
} // namespace lmms::gui
|
||||
@@ -37,7 +37,7 @@ TabBar::TabBar( QWidget * _parent, QBoxLayout::Direction _dir ) :
|
||||
m_layout( new QBoxLayout( _dir, this ) ),
|
||||
m_exclusive( false )
|
||||
{
|
||||
m_layout->setMargin( 8 );
|
||||
m_layout->setContentsMargins(8, 8, 8, 8);
|
||||
m_layout->setSpacing( 0 );
|
||||
|
||||
setLayout( m_layout );
|
||||
|
||||
@@ -60,9 +60,9 @@ TabWidget::TabWidget(const QString & caption, QWidget * parent, bool usePixmap,
|
||||
setFont( pointSize<8>( font() ) );
|
||||
|
||||
setAutoFillBackground( true );
|
||||
QColor bg_color = QApplication::palette().color( QPalette::Active, QPalette::Background ). darker( 132 );
|
||||
QColor bg_color = QApplication::palette().color( QPalette::Active, QPalette::Window ). darker( 132 );
|
||||
QPalette pal = palette();
|
||||
pal.setColor( QPalette::Background, bg_color );
|
||||
pal.setColor( QPalette::Window, bg_color );
|
||||
setPalette( pal );
|
||||
|
||||
}
|
||||
|
||||
@@ -22,12 +22,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TextFloat.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "TextFloat.h"
|
||||
#include "gui_templates.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
@@ -36,170 +39,97 @@ namespace lmms::gui
|
||||
|
||||
|
||||
TextFloat::TextFloat() :
|
||||
QWidget( getGUI()->mainWindow(), Qt::ToolTip ),
|
||||
m_title(),
|
||||
m_text(),
|
||||
m_pixmap()
|
||||
TextFloat("", "", QPixmap())
|
||||
{
|
||||
resize( 20, 20 );
|
||||
hide();
|
||||
|
||||
setAttribute( Qt::WA_TranslucentBackground, true );
|
||||
setStyle( QApplication::style() );
|
||||
setFont( pointSize<8>( font() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::setTitle( const QString & _title )
|
||||
TextFloat::TextFloat(const QString & title, const QString & text, const QPixmap & pixmap) :
|
||||
QWidget(getGUI()->mainWindow(), Qt::ToolTip)
|
||||
{
|
||||
m_title = _title;
|
||||
updateSize();
|
||||
QHBoxLayout * mainLayout = new QHBoxLayout();
|
||||
setLayout(mainLayout);
|
||||
|
||||
// Create the label that displays the pixmap
|
||||
m_pixmapLabel = new QLabel(this);
|
||||
mainLayout->addWidget(m_pixmapLabel);
|
||||
|
||||
// Create the widget that displays the title and the text
|
||||
QWidget * titleAndTextWidget = new QWidget(this);
|
||||
QVBoxLayout * titleAndTextLayout = new QVBoxLayout();
|
||||
titleAndTextWidget->setLayout(titleAndTextLayout);
|
||||
|
||||
m_titleLabel = new QLabel(titleAndTextWidget);
|
||||
m_titleLabel->setStyleSheet("font-weight: bold;");
|
||||
titleAndTextLayout->addWidget(m_titleLabel);
|
||||
|
||||
m_textLabel = new QLabel(titleAndTextWidget);
|
||||
titleAndTextLayout->addWidget(m_textLabel);
|
||||
|
||||
mainLayout->addWidget(titleAndTextWidget);
|
||||
|
||||
// Call the setters so that the hidden state is updated
|
||||
setTitle(title);
|
||||
setText(text);
|
||||
setPixmap(pixmap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::setText( const QString & _text )
|
||||
void TextFloat::setTitle(const QString & title)
|
||||
{
|
||||
m_text = _text;
|
||||
updateSize();
|
||||
m_titleLabel->setText(title);
|
||||
m_titleLabel->setHidden(title.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::setPixmap( const QPixmap & _pixmap )
|
||||
void TextFloat::setText(const QString & text)
|
||||
{
|
||||
m_pixmap = _pixmap;
|
||||
updateSize();
|
||||
m_textLabel->setText(text);
|
||||
m_textLabel->setHidden(text.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::setVisibilityTimeOut( int _msecs )
|
||||
void TextFloat::setPixmap(const QPixmap & pixmap)
|
||||
{
|
||||
QTimer::singleShot( _msecs, this, SLOT(hide()));
|
||||
m_pixmapLabel->setPixmap(pixmap);
|
||||
m_pixmapLabel->setHidden(pixmap.isNull());
|
||||
}
|
||||
|
||||
void TextFloat::setVisibilityTimeOut(int msecs)
|
||||
{
|
||||
QTimer::singleShot(msecs, this, SLOT(hide()));
|
||||
show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TextFloat * TextFloat::displayMessage( const QString & _msg, int _timeout,
|
||||
QWidget * _parent, int _add_y_margin )
|
||||
TextFloat * TextFloat::displayMessage(const QString & title,
|
||||
const QString & msg,
|
||||
const QPixmap & pixmap,
|
||||
int timeout, QWidget * parent)
|
||||
{
|
||||
QWidget * mw = getGUI()->mainWindow();
|
||||
auto tf = new TextFloat;
|
||||
if( _parent != nullptr )
|
||||
{
|
||||
tf->moveGlobal( _parent, QPoint( _parent->width() + 2, 0 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
tf->moveGlobal( mw, QPoint( 32, mw->height() - tf->height() - 8 - _add_y_margin ) );
|
||||
}
|
||||
tf->setText( _msg );
|
||||
auto tf = new TextFloat(title, msg, pixmap);
|
||||
|
||||
// Show the widget so that the correct height is calculated in the code that follows
|
||||
tf->show();
|
||||
if( _timeout > 0 )
|
||||
|
||||
if(parent != nullptr)
|
||||
{
|
||||
tf->setAttribute( Qt::WA_DeleteOnClose, true );
|
||||
QTimer::singleShot( _timeout, tf, SLOT(close()));
|
||||
}
|
||||
return( tf );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TextFloat * TextFloat::displayMessage( const QString & _title,
|
||||
const QString & _msg,
|
||||
const QPixmap & _pixmap,
|
||||
int _timeout, QWidget * _parent )
|
||||
{
|
||||
TextFloat * tf = displayMessage( _msg, _timeout, _parent, 16 );
|
||||
tf->setTitle( _title );
|
||||
tf->setPixmap( _pixmap );
|
||||
return( tf );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::paintEvent( QPaintEvent * _pe )
|
||||
{
|
||||
QStyleOption opt;
|
||||
opt.init( this );
|
||||
QPainter p( this );
|
||||
p.fillRect( 0, 0, width(), height(), QColor( 0, 0, 0, 0 ) );
|
||||
|
||||
/* p.setPen( p.pen().brush().color() );
|
||||
p.setBrush( p.background() );*/
|
||||
|
||||
p.setFont( pointSize<8>( p.font() ) );
|
||||
|
||||
style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this );
|
||||
|
||||
/* p.drawRect( 0, 0, rect().right(), rect().bottom() );*/
|
||||
|
||||
if( m_title.isEmpty() )
|
||||
{
|
||||
p.drawText( opt.rect, Qt::AlignCenter, m_text );
|
||||
tf->moveGlobal(parent, QPoint(parent->width() + 2, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
int text_x = opt.rect.left() + 2;
|
||||
int text_y = opt.rect.top() + 12;
|
||||
if( m_pixmap.isNull() == false )
|
||||
{
|
||||
p.drawPixmap( opt.rect.topLeft() + QPoint( 5, 5 ), m_pixmap );
|
||||
text_x += m_pixmap.width() + 8;
|
||||
}
|
||||
p.drawText( text_x, text_y + 16, m_text );
|
||||
QFont f = p.font();
|
||||
f.setBold( true );
|
||||
p.setFont( f );
|
||||
p.drawText( text_x, text_y, m_title );
|
||||
// If no parent is given move the window to the lower left area of the main window
|
||||
QWidget * mw = getGUI()->mainWindow();
|
||||
tf->moveGlobal(mw, QPoint(32, mw->height() - tf->height() - 8));
|
||||
}
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
tf->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
QTimer::singleShot(timeout, tf, SLOT(close()));
|
||||
}
|
||||
|
||||
return tf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::mousePressEvent( QMouseEvent * )
|
||||
void TextFloat::mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TextFloat::updateSize()
|
||||
{
|
||||
QFontMetrics metrics( pointSize<8>( font() ) );
|
||||
QRect textBound = metrics.boundingRect( m_text );
|
||||
if( !m_title.isEmpty() )
|
||||
{
|
||||
QFont f = pointSize<8>( font() );
|
||||
f.setBold( true );
|
||||
int title_w = QFontMetrics( f ).boundingRect( m_title ).width();
|
||||
if( title_w > textBound.width() )
|
||||
{
|
||||
textBound.setWidth( title_w );
|
||||
}
|
||||
textBound.setHeight( textBound.height() * 2 + 8 );
|
||||
}
|
||||
if( m_pixmap.isNull() == false )
|
||||
{
|
||||
textBound.setWidth( textBound.width() + m_pixmap.width() + 10 );
|
||||
}
|
||||
resize( textBound.width() + 5, textBound.height()+2 );
|
||||
//move( QPoint( parentWidget()->width() + 5, 5 ) );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
@@ -43,7 +43,7 @@ TimeDisplayWidget::TimeDisplayWidget() :
|
||||
m_milliSecondsLCD( 3, this )
|
||||
{
|
||||
m_spinBoxesLayout.setSpacing( 0 );
|
||||
m_spinBoxesLayout.setMargin( 0 );
|
||||
m_spinBoxesLayout.setContentsMargins(0, 0, 0, 0);
|
||||
m_spinBoxesLayout.addWidget( &m_majorLCD );
|
||||
m_spinBoxesLayout.addWidget( &m_minorLCD );
|
||||
m_spinBoxesLayout.addWidget( &m_milliSecondsLCD );
|
||||
|
||||
@@ -609,8 +609,6 @@ void InstrumentTrack::setName( const QString & _new_name )
|
||||
Track::setName( _new_name );
|
||||
m_midiPort.setName( name() );
|
||||
m_audioPort.setName( name() );
|
||||
|
||||
emit nameChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -424,7 +424,7 @@ void MidiClip::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
movePosition( _this.attribute( "pos" ).toInt() );
|
||||
}
|
||||
if( _this.attribute( "muted" ).toInt() != isMuted() )
|
||||
if (static_cast<bool>(_this.attribute("muted").toInt()) != isMuted())
|
||||
{
|
||||
toggleMute();
|
||||
}
|
||||
|
||||
@@ -108,19 +108,27 @@ bool PatternTrack::play( const TimePos & _start, const fpp_t _frames,
|
||||
}
|
||||
|
||||
TimePos lastPosition;
|
||||
TimePos lastLen;
|
||||
TimePos lastLength;
|
||||
tick_t lastOffset = 0;
|
||||
for (const auto& clip : clips)
|
||||
{
|
||||
if (!clip->isMuted() && clip->startPosition() >= lastPosition)
|
||||
{
|
||||
lastPosition = clip->startPosition();
|
||||
lastLen = clip->length();
|
||||
lastLength = clip->length();
|
||||
tick_t patternLength = Engine::patternStore()->lengthOfPattern(static_cast<PatternClip*>(clip)->patternIndex())
|
||||
* TimePos::ticksPerBar();
|
||||
lastOffset = patternLength - (clip->startTimeOffset() % patternLength);
|
||||
if (lastOffset == patternLength)
|
||||
{
|
||||
lastOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( _start - lastPosition < lastLen )
|
||||
if( _start - lastPosition < lastLength )
|
||||
{
|
||||
return Engine::patternStore()->play(_start - lastPosition, _frames, _offset, s_infoMap[this]);
|
||||
return Engine::patternStore()->play(_start - lastPosition + lastOffset, _frames, _offset, s_infoMap[this]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -240,4 +248,4 @@ void PatternTrack::swapPatternTracks(Track* track1, Track* track2)
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
} // namespace lmms
|
||||
|
||||
Reference in New Issue
Block a user