Merge remote-tracking branch 'origin/stable-0.4-test' into stable-0.4
Conflicts: include/song.h src/core/song.cpp
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* AutomatableModel.cpp - some implementations of AutomatableModel-class
|
||||
*
|
||||
* Copyright (c) 2008-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -44,6 +44,8 @@ AutomatableModel::AutomatableModel( DataType _type,
|
||||
bool _default_constructed ) :
|
||||
Model( _parent, _display_name, _default_constructed ),
|
||||
m_dataType( _type ),
|
||||
m_value( _val ),
|
||||
m_initValue( _val ),
|
||||
m_minValue( _min ),
|
||||
m_maxValue( _max ),
|
||||
m_step( _step ),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* AutomationPattern.cpp - implementation of class AutomationPattern which
|
||||
* holds dynamic values
|
||||
*
|
||||
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
@@ -41,11 +41,9 @@
|
||||
AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) :
|
||||
trackContentObject( _auto_track ),
|
||||
m_autoTrack( _auto_track ),
|
||||
m_objects(),
|
||||
m_hasAutomation( false )
|
||||
m_objects()
|
||||
{
|
||||
changeLength( midiTime( 1, 0 ) );
|
||||
m_timeMap[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +52,7 @@ AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) :
|
||||
AutomationPattern::AutomationPattern( const AutomationPattern & _pat_to_copy ) :
|
||||
trackContentObject( _pat_to_copy.m_autoTrack ),
|
||||
m_autoTrack( _pat_to_copy.m_autoTrack ),
|
||||
m_objects( _pat_to_copy.m_objects ),
|
||||
m_hasAutomation( _pat_to_copy.m_hasAutomation )
|
||||
m_objects( _pat_to_copy.m_objects )
|
||||
{
|
||||
for( timeMap::const_iterator it = _pat_to_copy.m_timeMap.begin();
|
||||
it != _pat_to_copy.m_timeMap.end(); ++it )
|
||||
@@ -100,13 +97,15 @@ void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
|
||||
|
||||
if( addIt )
|
||||
{
|
||||
m_objects += _obj;
|
||||
// been empty before?
|
||||
if( m_objects.size() == 1 && !hasAutomation() )
|
||||
if( m_objects.isEmpty() && hasAutomation() == false )
|
||||
{
|
||||
// then initialize default-value
|
||||
// then initialize default value
|
||||
putValue( 0, _obj->value<float>(), false );
|
||||
}
|
||||
|
||||
m_objects += _obj;
|
||||
|
||||
connect( _obj, SIGNAL( destroyed( jo_id_t ) ),
|
||||
this, SLOT( objectDestroyed( jo_id_t ) ),
|
||||
Qt::DirectConnection );
|
||||
@@ -152,6 +151,8 @@ midiTime AutomationPattern::putValue( const midiTime & _time,
|
||||
const float _value,
|
||||
const bool _quant_pos )
|
||||
{
|
||||
cleanObjects();
|
||||
|
||||
midiTime newTime = _quant_pos && engine::automationEditor() ?
|
||||
note::quantized( _time,
|
||||
engine::automationEditor()->quantization() ) :
|
||||
@@ -159,44 +160,6 @@ midiTime AutomationPattern::putValue( const midiTime & _time,
|
||||
|
||||
m_timeMap[newTime] = _value;
|
||||
|
||||
if( newTime == 0 )
|
||||
{
|
||||
for( objectVector::iterator it = m_objects.begin();
|
||||
it != m_objects.end(); )
|
||||
{
|
||||
if( *it )
|
||||
{
|
||||
( *it )->setValue( _value );
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
it = m_objects.erase( it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// just one automation value?
|
||||
if( m_timeMap.size() == 1 )
|
||||
{
|
||||
m_hasAutomation = m_objects.isEmpty(); // usually false
|
||||
for( objectVector::iterator it = m_objects.begin();
|
||||
it != m_objects.end(); ++it )
|
||||
{
|
||||
// default value differs from current value?
|
||||
if( *it && _value != ( *it )->initValue<float>() )
|
||||
{
|
||||
// then enable automating this object
|
||||
m_hasAutomation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// in all other cases assume we have automation
|
||||
m_hasAutomation = true;
|
||||
}
|
||||
|
||||
// we need to maximize our length in case we're part of a hidden
|
||||
// automation track as the user can't resize this pattern
|
||||
if( getTrack() && getTrack()->type() == track::HiddenAutomationTrack )
|
||||
@@ -214,41 +177,17 @@ midiTime AutomationPattern::putValue( const midiTime & _time,
|
||||
|
||||
void AutomationPattern::removeValue( const midiTime & _time )
|
||||
{
|
||||
if( _time != 0 )
|
||||
cleanObjects();
|
||||
|
||||
m_timeMap.remove( _time );
|
||||
|
||||
if( getTrack() &&
|
||||
getTrack()->type() == track::HiddenAutomationTrack )
|
||||
{
|
||||
m_timeMap.remove( _time );
|
||||
|
||||
if( m_timeMap.size() == 1 )
|
||||
{
|
||||
const float val = m_timeMap[0];
|
||||
m_hasAutomation = false;
|
||||
for( objectVector::iterator it = m_objects.begin();
|
||||
it != m_objects.end(); )
|
||||
{
|
||||
if( *it )
|
||||
{
|
||||
( *it )->setValue( val );
|
||||
if( ( *it )->initValue<float>() != val )
|
||||
{
|
||||
m_hasAutomation = true;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
it = m_objects.erase( it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( getTrack() &&
|
||||
getTrack()->type() == track::HiddenAutomationTrack )
|
||||
{
|
||||
changeLength( length() );
|
||||
}
|
||||
|
||||
emit dataChanged();
|
||||
changeLength( length() );
|
||||
}
|
||||
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -260,10 +199,22 @@ float AutomationPattern::valueAt( const midiTime & _time ) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
timeMap::const_iterator v = m_timeMap.lowerBound( _time );
|
||||
|
||||
if( m_timeMap.contains( _time ) )
|
||||
{
|
||||
return m_timeMap[_time];
|
||||
}
|
||||
|
||||
// lowerBound returns next value with greater key, therefore we take
|
||||
// the previous element to get the current value
|
||||
return ( v != m_timeMap.begin() ) ? (v-1).value() : v.value();
|
||||
timeMap::ConstIterator v = m_timeMap.lowerBound( _time );
|
||||
|
||||
if( v == m_timeMap.begin() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (v-1).value();
|
||||
}
|
||||
|
||||
|
||||
@@ -325,18 +276,6 @@ void AutomationPattern::loadSettings( const QDomElement & _this )
|
||||
}
|
||||
}
|
||||
|
||||
m_hasAutomation = m_timeMap.size() > 0;
|
||||
if( m_hasAutomation == false )
|
||||
{
|
||||
for( objectVector::iterator it = m_objects.begin();
|
||||
it != m_objects.end(); ++it )
|
||||
{
|
||||
if( *it )
|
||||
{
|
||||
( *it )->setValue( m_timeMap[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
int len = _this.attribute( "len" ).toInt();
|
||||
if( len <= 0 )
|
||||
{
|
||||
@@ -366,7 +305,7 @@ const QString AutomationPattern::name() const
|
||||
|
||||
void AutomationPattern::processMidiTime( const midiTime & _time )
|
||||
{
|
||||
if( _time >= 0 && m_hasAutomation )
|
||||
if( _time >= 0 && hasAutomation() )
|
||||
{
|
||||
const float val = valueAt( _time );
|
||||
for( objectVector::iterator it = m_objects.begin();
|
||||
@@ -411,7 +350,7 @@ bool AutomationPattern::isAutomated( const AutomatableModel * _m )
|
||||
{
|
||||
const AutomationPattern * a =
|
||||
dynamic_cast<const AutomationPattern *>( *j );
|
||||
if( a && a->m_hasAutomation )
|
||||
if( a && a->hasAutomation() )
|
||||
{
|
||||
for( objectVector::const_iterator k = a->m_objects.begin();
|
||||
k != a->m_objects.end(); ++k )
|
||||
@@ -502,9 +441,9 @@ void AutomationPattern::resolveAllIDs()
|
||||
|
||||
void AutomationPattern::clear()
|
||||
{
|
||||
const float val = firstObject()->value<float>();
|
||||
m_timeMap.clear();
|
||||
putValue( 0, val );
|
||||
|
||||
emit dataChanged();
|
||||
|
||||
if( engine::automationEditor() &&
|
||||
engine::automationEditor()->currentPattern() == this )
|
||||
@@ -537,6 +476,21 @@ void AutomationPattern::objectDestroyed( jo_id_t _id )
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::cleanObjects()
|
||||
{
|
||||
for( objectVector::iterator it = m_objects.begin(); it != m_objects.end(); )
|
||||
{
|
||||
if( *it )
|
||||
{
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
it = m_objects.erase( it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "moc_AutomationPattern.cxx"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* InstrumentFunctions.cpp - models for instrument-function-tab
|
||||
*
|
||||
* Copyright (c) 2004-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -48,7 +48,7 @@ ChordCreator::ChordTable::Init ChordCreator::ChordTable::s_initTable[] =
|
||||
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "6" ), { 0, 4, 7, 9, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "6sus4" ), { 0, 5, 7, 9, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "6add9" ), { 0, 4, 7, 12, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "6add9" ), { 0, 4, 7, 9, 14, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "m6" ), { 0, 3, 7, 9, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "m6add9" ), { 0, 3, 7, 9, 14, -1 } },
|
||||
|
||||
@@ -56,11 +56,11 @@ ChordCreator::ChordTable::Init ChordCreator::ChordTable::s_initTable[] =
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7sus4" ), { 0, 5, 7, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#5" ), { 0, 4, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7b5" ), { 0, 4, 6, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#9" ), { 0, 4, 7, 10, 13, 18, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7b9" ), { 0, 4, 7, 10, 13, 16, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#5#9" ), { 0, 4, 8, 12, 14, 19, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#5b9" ), { 0, 4, 8, 12, 14, 17, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7b5b9" ), { 0, 4, 6, 10, 12, 15, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#9" ), { 0, 4, 7, 10, 15, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7b9" ), { 0, 4, 7, 10, 13, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#5#9" ), { 0, 4, 8, 10, 15, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#5b9" ), { 0, 4, 8, 10, 13, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7b5b9" ), { 0, 4, 6, 10, 13, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7add11" ), { 0, 4, 7, 10, 17, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7add13" ), { 0, 4, 7, 10, 21, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "7#11" ), { 0, 4, 7, 10, 18, -1 } },
|
||||
@@ -113,7 +113,7 @@ ChordCreator::ChordTable::Init ChordCreator::ChordTable::s_initTable[] =
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Melodic minor" ), { 0, 2, 3, 5, 7, 9, 11, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Whole tone" ), { 0, 2, 4, 6, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Diminished" ), { 0, 2, 3, 5, 6, 8, 9, 11, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Major pentatonic" ), { 0, 2, 4, 7, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Major pentatonic" ), { 0, 2, 4, 7, 9, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Minor pentatonic" ), { 0, 3, 5, 7, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Jap in sen" ), { 0, 1, 5, 7, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Major bebop" ), { 0, 2, 4, 5, 7, 8, 9, 11, -1 } },
|
||||
@@ -130,6 +130,7 @@ ChordCreator::ChordTable::Init ChordCreator::ChordTable::s_initTable[] =
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Mixolydian" ), { 0, 2, 4, 5, 7, 9, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Aeolian" ), { 0, 2, 3, 5, 7, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Locrian" ), { 0, 1, 3, 5, 6, 8, 10, -1 } },
|
||||
{ QT_TRANSLATE_NOOP( "ChordCreator", "Minor" ), { 0, 2, 3, 5, 7, 8, 10, -1 } },
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#ifdef LMMS_HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include <QMutexLocker>
|
||||
|
||||
FileEncodeDevice __fileEncodeDevices[] =
|
||||
{
|
||||
@@ -126,6 +126,7 @@ ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension(
|
||||
|
||||
void ProjectRenderer::startProcessing()
|
||||
{
|
||||
|
||||
if( isReady() )
|
||||
{
|
||||
// have to do mixer stuff with GUI-thread-affinity in order to
|
||||
@@ -139,11 +140,11 @@ void ProjectRenderer::startProcessing()
|
||||
QThread::HighPriority
|
||||
#endif
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::run()
|
||||
{
|
||||
#if 0
|
||||
@@ -157,6 +158,7 @@ void ProjectRenderer::run()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
engine::getSong()->startExport();
|
||||
|
||||
song::playPos & pp = engine::getSong()->getPlayPos(
|
||||
|
||||
@@ -230,14 +230,13 @@ bool RemotePlugin::process( const sampleFrame * _in_buf,
|
||||
|
||||
lock();
|
||||
sendMessage( IdStartProcessing );
|
||||
unlock();
|
||||
|
||||
if( m_failed || _out_buf == NULL || m_outputCount == 0 )
|
||||
{
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
lock();
|
||||
waitForMessage( IdProcessingDone );
|
||||
unlock();
|
||||
|
||||
@@ -314,7 +313,7 @@ void RemotePlugin::resizeSharedProcessingMemory()
|
||||
#endif
|
||||
}
|
||||
|
||||
int shm_key = 0;
|
||||
static int shm_key = 0;
|
||||
#ifdef USE_QT_SHMEM
|
||||
do
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* This file is based on encode.c from vorbis-tools-source, for more information
|
||||
* see below.
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -49,7 +49,7 @@ AudioFileOgg::AudioFileOgg( const sample_rate_t _sample_rate,
|
||||
_nom_bitrate, _min_bitrate, _max_bitrate,
|
||||
_depth, _mixer )
|
||||
{
|
||||
m_ok = _success_ful = startEncoding();
|
||||
m_ok = _success_ful = outputFileOpened() && startEncoding();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* AudioFileWave.cpp - audio-device which encodes wave-stream and writes it
|
||||
* into a WAVE-file. This is used for song-export.
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -38,9 +38,10 @@ AudioFileWave::AudioFileWave( const sample_rate_t _sample_rate,
|
||||
mixer * _mixer ) :
|
||||
AudioFileDevice( _sample_rate, _channels, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate, _max_bitrate,
|
||||
_depth, _mixer )
|
||||
_depth, _mixer ),
|
||||
m_sf( NULL )
|
||||
{
|
||||
_success_ful = startEncoding();
|
||||
_success_ful = outputFileOpened() && startEncoding();
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +69,13 @@ bool AudioFileWave::startEncoding()
|
||||
case 16:
|
||||
default: m_si.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; break;
|
||||
}
|
||||
m_sf = sf_open( outputFile().toUtf8().constData(), SFM_WRITE, &m_si );
|
||||
m_sf = sf_open(
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
outputFile().toLocal8Bit().constData(),
|
||||
#else
|
||||
outputFile().toUtf8().constData(),
|
||||
#endif
|
||||
SFM_WRITE, &m_si );
|
||||
sf_set_string ( m_sf, SF_STR_SOFTWARE, "LMMS" );
|
||||
return true;
|
||||
}
|
||||
@@ -110,6 +117,9 @@ void AudioFileWave::writeBuffer( const surroundSampleFrame * _ab,
|
||||
|
||||
void AudioFileWave::finishEncoding()
|
||||
{
|
||||
sf_close( m_sf );
|
||||
if( m_sf )
|
||||
{
|
||||
sf_close( m_sf );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ int DrumSynth::GetDSFileSamples(const char *dsfile, int16_t *&wave, int channels
|
||||
int MainFilter, HighPass;
|
||||
|
||||
long NON, NT, TON, DiON, TDroop=0, DStep;
|
||||
float a, b=0.f, c=0.f, d=0.f, g, TT=0.f, TL, NL, F1, F2, Fsync;
|
||||
float a, b=0.f, c=0.f, d=0.f, g, TT=0.f, TL, NL, F1, F2;
|
||||
float TphiStart=0.f, Tphi, TDroopRate, ddF, DAtten, DGain;
|
||||
|
||||
long BON, BON2, BFStep, BFStep2, botmp;
|
||||
@@ -354,7 +354,6 @@ int DrumSynth::GetDSFileSamples(const char *dsfile, int16_t *&wave, int channels
|
||||
F1 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F1",200.0,dsfile) / Fs;
|
||||
if(fabs(F1)<0.001f) F1=0.001f; //to prevent overtone ratio div0
|
||||
F2 = MasterTune * TwoPi * GetPrivateProfileFloat(sec,"F2",120.0,dsfile) / Fs;
|
||||
Fsync = F2;
|
||||
TDroopRate = GetPrivateProfileFloat(sec,"Droop",0.f,dsfile);
|
||||
if(TDroopRate>0.f)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fft_helpers.cpp - some functions around FFT analysis
|
||||
*
|
||||
* Copyright (c) 2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#include "fft_helpers.h"
|
||||
|
||||
#ifdef LMMS_HAVE_FFTW3F
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
@@ -243,5 +241,3 @@ float signalpower(float *timesignal, int num_values)
|
||||
return power;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* MidiAlsaSeq.cpp - ALSA sequencer client
|
||||
*
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -73,6 +73,7 @@ static QString __portName( snd_seq_t * _seq, const snd_seq_addr_t * _addr )
|
||||
|
||||
MidiAlsaSeq::MidiAlsaSeq() :
|
||||
MidiClient(),
|
||||
m_seqMutex(),
|
||||
m_seqHandle( NULL ),
|
||||
m_queueID( -1 ),
|
||||
m_quit( false ),
|
||||
@@ -131,9 +132,11 @@ MidiAlsaSeq::~MidiAlsaSeq()
|
||||
m_quit = true;
|
||||
wait( EventPollTimeOut*2 );
|
||||
|
||||
m_seqMutex.lock();
|
||||
snd_seq_stop_queue( m_seqHandle, m_queueID, NULL );
|
||||
snd_seq_free_queue( m_seqHandle, m_queueID );
|
||||
snd_seq_close( m_seqHandle );
|
||||
m_seqMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,8 +231,10 @@ void MidiAlsaSeq::processOutEvent( const midiEvent & _me,
|
||||
return;
|
||||
}
|
||||
|
||||
m_seqMutex.lock();
|
||||
snd_seq_event_output( m_seqHandle, &ev );
|
||||
snd_seq_drain_output( m_seqHandle );
|
||||
m_seqMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
@@ -238,6 +243,8 @@ void MidiAlsaSeq::processOutEvent( const midiEvent & _me,
|
||||
|
||||
void MidiAlsaSeq::applyPortMode( MidiPort * _port )
|
||||
{
|
||||
m_seqMutex.lock();
|
||||
|
||||
// determine port-capabilities
|
||||
unsigned int caps[2] = { 0, 0 };
|
||||
|
||||
@@ -297,6 +304,7 @@ void MidiAlsaSeq::applyPortMode( MidiPort * _port )
|
||||
}
|
||||
}
|
||||
|
||||
m_seqMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -304,6 +312,8 @@ void MidiAlsaSeq::applyPortMode( MidiPort * _port )
|
||||
|
||||
void MidiAlsaSeq::applyPortName( MidiPort * _port )
|
||||
{
|
||||
m_seqMutex.lock();
|
||||
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
if( m_portIDs[_port][i] == -1 )
|
||||
@@ -320,6 +330,8 @@ void MidiAlsaSeq::applyPortName( MidiPort * _port )
|
||||
port_info );
|
||||
snd_seq_port_info_free( port_info );
|
||||
}
|
||||
|
||||
m_seqMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -329,8 +341,11 @@ void MidiAlsaSeq::removePort( MidiPort * _port )
|
||||
{
|
||||
if( m_portIDs.contains( _port ) )
|
||||
{
|
||||
m_seqMutex.lock();
|
||||
snd_seq_delete_simple_port( m_seqHandle, m_portIDs[_port][0] );
|
||||
snd_seq_delete_simple_port( m_seqHandle, m_portIDs[_port][1] );
|
||||
m_seqMutex.unlock();
|
||||
|
||||
m_portIDs.remove( _port );
|
||||
}
|
||||
MidiClient::removePort( _port );
|
||||
@@ -361,11 +376,16 @@ void MidiAlsaSeq::subscribeReadablePort( MidiPort * _port,
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_seqMutex.lock();
|
||||
|
||||
snd_seq_addr_t sender;
|
||||
if( snd_seq_parse_address( m_seqHandle, &sender,
|
||||
_dest.section( ' ', 0, 0 ).toAscii().constData() ) )
|
||||
{
|
||||
fprintf( stderr, "error parsing sender-address!\n" );
|
||||
|
||||
m_seqMutex.unlock();
|
||||
return;
|
||||
}
|
||||
snd_seq_port_info_t * port_info;
|
||||
@@ -386,6 +406,8 @@ void MidiAlsaSeq::subscribeReadablePort( MidiPort * _port,
|
||||
}
|
||||
snd_seq_port_subscribe_free( subs );
|
||||
snd_seq_port_info_free( port_info );
|
||||
|
||||
m_seqMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -406,11 +428,14 @@ void MidiAlsaSeq::subscribeWritablePort( MidiPort * _port,
|
||||
return;
|
||||
}
|
||||
|
||||
m_seqMutex.lock();
|
||||
|
||||
snd_seq_addr_t dest;
|
||||
if( snd_seq_parse_address( m_seqHandle, &dest,
|
||||
_dest.section( ' ', 0, 0 ).toAscii().constData() ) )
|
||||
{
|
||||
fprintf( stderr, "error parsing dest-address!\n" );
|
||||
m_seqMutex.unlock();
|
||||
return;
|
||||
}
|
||||
snd_seq_port_info_t * port_info;
|
||||
@@ -431,6 +456,7 @@ void MidiAlsaSeq::subscribeWritablePort( MidiPort * _port,
|
||||
}
|
||||
snd_seq_port_subscribe_free( subs );
|
||||
snd_seq_port_info_free( port_info );
|
||||
m_seqMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -471,15 +497,20 @@ void MidiAlsaSeq::run()
|
||||
break;
|
||||
}
|
||||
|
||||
m_seqMutex.lock();
|
||||
|
||||
// while event queue is not empty
|
||||
while( snd_seq_event_input_pending( m_seqHandle, true ) > 0 )
|
||||
{
|
||||
snd_seq_event_t * ev;
|
||||
if( snd_seq_event_input( m_seqHandle, &ev ) < 0 )
|
||||
{
|
||||
m_seqMutex.unlock();
|
||||
|
||||
qCritical( "error while fetching MIDI event from sequencer" );
|
||||
break;
|
||||
}
|
||||
m_seqMutex.unlock();
|
||||
|
||||
snd_seq_addr_t * source = NULL;
|
||||
MidiPort * dest = NULL;
|
||||
@@ -582,8 +613,12 @@ void MidiAlsaSeq::run()
|
||||
break;
|
||||
} // end switch
|
||||
|
||||
m_seqMutex.lock();
|
||||
|
||||
} // end while
|
||||
|
||||
m_seqMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
delete[] pollfd_set;
|
||||
@@ -594,9 +629,13 @@ void MidiAlsaSeq::run()
|
||||
|
||||
void MidiAlsaSeq::changeQueueTempo( bpm_t _bpm )
|
||||
{
|
||||
m_seqMutex.lock();
|
||||
|
||||
snd_seq_change_queue_tempo( m_seqHandle, m_queueID,
|
||||
60000000 / (int) _bpm, NULL );
|
||||
snd_seq_drain_output( m_seqHandle );
|
||||
|
||||
m_seqMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -615,6 +654,9 @@ void MidiAlsaSeq::updatePortList()
|
||||
snd_seq_port_info_malloc( &pinfo );
|
||||
|
||||
snd_seq_client_info_set_client( cinfo, -1 );
|
||||
|
||||
m_seqMutex.lock();
|
||||
|
||||
while( snd_seq_query_next_client( m_seqHandle, cinfo ) >= 0 )
|
||||
{
|
||||
int client = snd_seq_client_info_get_client( cinfo );
|
||||
@@ -643,6 +685,9 @@ void MidiAlsaSeq::updatePortList()
|
||||
}
|
||||
}
|
||||
|
||||
m_seqMutex.unlock();
|
||||
|
||||
|
||||
snd_seq_client_info_free( cinfo );
|
||||
snd_seq_port_info_free( pinfo );
|
||||
|
||||
|
||||
@@ -222,11 +222,11 @@ void MidiClientRaw::parseData( const Uint8 _c )
|
||||
m_midiParseData.m_buffer[0] - KeysPerOctave;
|
||||
m_midiParseData.m_midiEvent.m_data.m_param[1] =
|
||||
m_midiParseData.m_buffer[1];
|
||||
break;
|
||||
|
||||
case MidiControlChange:
|
||||
m_midiParseData.m_midiEvent.m_data.m_param[0] =
|
||||
m_midiParseData.m_buffer[0] - KeysPerOctave;
|
||||
m_midiParseData.m_midiEvent.m_data.m_param[1] =
|
||||
m_midiParseData.m_buffer[1];
|
||||
m_midiParseData.m_midiEvent.m_data.m_param[0] = m_midiParseData.m_buffer[0];
|
||||
m_midiParseData.m_midiEvent.m_data.m_param[1] = m_midiParseData.m_buffer[1];
|
||||
break;
|
||||
|
||||
case MidiPitchBend:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* MidiPort.cpp - abstraction of MIDI-ports which are part of LMMS's MIDI-
|
||||
* sequencing system
|
||||
*
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -45,15 +45,17 @@ MidiPort::MidiPort( const QString & _name, MidiClient * _mc,
|
||||
m_outputChannelModel( 1, 1, MidiChannelCount, this,
|
||||
tr( "Output channel" ) ),
|
||||
m_inputControllerModel( 0, 0, MidiControllerCount, this,
|
||||
tr( "Input controller" ) ),
|
||||
tr( "Input controller" ) ),
|
||||
m_outputControllerModel( 0, 0, MidiControllerCount, this,
|
||||
tr( "Output controller" ) ),
|
||||
tr( "Output controller" ) ),
|
||||
m_fixedInputVelocityModel( -1, -1, MidiMaxVelocity, this,
|
||||
tr( "Fixed input velocity" ) ),
|
||||
tr( "Fixed input velocity" ) ),
|
||||
m_fixedOutputVelocityModel( -1, -1, MidiMaxVelocity, this,
|
||||
tr( "Fixed output velocity" ) ),
|
||||
m_fixedOutputNoteModel( -1, -1, MidiMaxNote, this,
|
||||
tr( "Fixed output note" ) ),
|
||||
m_outputProgramModel( 1, 1, MidiProgramCount, this,
|
||||
tr( "Output MIDI program" ) ),
|
||||
tr( "Output MIDI program" ) ),
|
||||
m_readableModel( false, this, tr( "Receive MIDI-events" ) ),
|
||||
m_writableModel( false, this, tr( "Send MIDI-events" ) )
|
||||
{
|
||||
@@ -127,20 +129,24 @@ void MidiPort::processInEvent( const midiEvent & _me, const midiTime & _time )
|
||||
if( inputEnabled() &&
|
||||
( inputChannel()-1 == _me.m_channel || inputChannel() == 0 ) )
|
||||
{
|
||||
midiEvent ev = _me;
|
||||
if( _me.m_type == MidiNoteOn ||
|
||||
_me.m_type == MidiNoteOff ||
|
||||
_me.m_type == MidiKeyPressure )
|
||||
{
|
||||
if( _me.key() < 0 || _me.key() >= NumKeys )
|
||||
ev.key() = ev.key() + KeysPerOctave;
|
||||
if( ev.key() < 0 || ev.key() >= NumKeys )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
midiEvent ev = _me;
|
||||
|
||||
if( fixedInputVelocity() >= 0 && _me.velocity() > 0 )
|
||||
{
|
||||
ev.velocity() = fixedInputVelocity();
|
||||
}
|
||||
|
||||
ev.setFromMidiPort( true );
|
||||
m_midiEventProcessor->processInEvent( ev, _time );
|
||||
}
|
||||
}
|
||||
@@ -156,9 +162,17 @@ void MidiPort::processOutEvent( const midiEvent & _me, const midiTime & _time )
|
||||
midiEvent ev = _me;
|
||||
// we use/display MIDI channels 1...16 but we need 0...15 for
|
||||
// the outside world
|
||||
if( ev.m_channel > 0 )
|
||||
// We are already in "real" MIDI channel space here
|
||||
/* if( ev.m_channel > 0 )
|
||||
{
|
||||
--ev.m_channel;
|
||||
} */
|
||||
if( ( _me.m_type == MidiNoteOn || _me.m_type == MidiNoteOff ) &&
|
||||
fixedOutputNote() >= 0 )
|
||||
{
|
||||
// Convert MIDI note number (from spinbox) -> LMMS note number
|
||||
// that will be converted back when outputted.
|
||||
ev.key() = fixedOutputNote() - KeysPerOctave;
|
||||
}
|
||||
if( fixedOutputVelocity() >= 0 && _me.velocity() > 0 &&
|
||||
( _me.m_type == MidiNoteOn ||
|
||||
@@ -183,6 +197,8 @@ void MidiPort::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
"fixedinputvelocity" );
|
||||
m_fixedOutputVelocityModel.saveSettings( _doc, _this,
|
||||
"fixedoutputvelocity" );
|
||||
m_fixedOutputNoteModel.saveSettings( _doc, _this,
|
||||
"fixedoutputnote" );
|
||||
m_outputProgramModel.saveSettings( _doc, _this, "outputprogram" );
|
||||
m_readableModel.saveSettings( _doc, _this, "readable" );
|
||||
m_writableModel.saveSettings( _doc, _this, "writable" );
|
||||
|
||||
@@ -190,6 +190,7 @@ void notePlayHandle::play( sampleFrame * _working_buffer )
|
||||
}
|
||||
|
||||
if( m_released == false &&
|
||||
instrumentTrack()->isSustainPedalPressed() == false &&
|
||||
m_totalFramesPlayed + engine::getMixer()->framesPerPeriod()
|
||||
>= m_frames )
|
||||
{
|
||||
@@ -293,7 +294,11 @@ void notePlayHandle::play( sampleFrame * _working_buffer )
|
||||
|
||||
f_cnt_t notePlayHandle::framesLeft() const
|
||||
{
|
||||
if( m_released && actualReleaseFramesToDo() == 0 )
|
||||
if( instrumentTrack()->isSustainPedalPressed() )
|
||||
{
|
||||
return 4*engine::getMixer()->framesPerPeriod();
|
||||
}
|
||||
else if( m_released && actualReleaseFramesToDo() == 0 )
|
||||
{
|
||||
return m_framesBeforeRelease;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* sample_buffer.cpp - container-class sampleBuffer
|
||||
*
|
||||
* Copyright (c) 2005-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -699,8 +699,10 @@ f_cnt_t sampleBuffer::getLoopedIndex( f_cnt_t _index ) const
|
||||
|
||||
|
||||
void sampleBuffer::visualize( QPainter & _p, const QRect & _dr,
|
||||
const QRect & _clip )
|
||||
const QRect & _clip, f_cnt_t _from_frame, f_cnt_t _to_frame )
|
||||
{
|
||||
const bool focus_on_range = _to_frame <= m_frames
|
||||
&& 0 <= _from_frame && _from_frame < _to_frame;
|
||||
// _p.setClipRect( _clip );
|
||||
// _p.setPen( QColor( 0x22, 0xFF, 0x44 ) );
|
||||
//_p.setPen( QColor( 64, 224, 160 ) );
|
||||
@@ -709,25 +711,28 @@ void sampleBuffer::visualize( QPainter & _p, const QRect & _dr,
|
||||
|
||||
const int yb = h / 2 + _dr.y();
|
||||
const float y_space = h*0.25f;
|
||||
const int nb_frames = focus_on_range ? _to_frame - _from_frame : m_frames;
|
||||
|
||||
if( m_frames < 60000 )
|
||||
if( nb_frames < 60000 )
|
||||
{
|
||||
_p.setRenderHint( QPainter::Antialiasing );
|
||||
QColor c = _p.pen().color();
|
||||
_p.setPen( QPen( c, 0.7 ) );
|
||||
}
|
||||
const int fpp = tLimit<int>( m_frames / w, 1, 20 );
|
||||
QPoint * l = new QPoint[m_frames / fpp + 1];
|
||||
const int fpp = tLimit<int>( nb_frames / w, 1, 20 );
|
||||
QPoint * l = new QPoint[nb_frames / fpp + 1];
|
||||
int n = 0;
|
||||
const int xb = _dr.x();
|
||||
for( int frame = 0; frame < m_frames; frame += fpp )
|
||||
const int first = focus_on_range ? _from_frame : 0;
|
||||
const int last = focus_on_range ? _to_frame : m_frames;
|
||||
for( int frame = first; frame < last; frame += fpp )
|
||||
{
|
||||
l[n] = QPoint( xb + ( frame * w / m_frames ),
|
||||
l[n] = QPoint( xb + ( (frame - first) * double( w ) / nb_frames ),
|
||||
(int)( yb - ( ( m_data[frame][0]+m_data[frame][1] ) *
|
||||
y_space ) ) );
|
||||
++n;
|
||||
}
|
||||
_p.drawPolyline( l, m_frames / fpp );
|
||||
_p.drawPolyline( l, nb_frames / fpp );
|
||||
delete[] l;
|
||||
}
|
||||
|
||||
@@ -737,6 +742,9 @@ void sampleBuffer::visualize( QPainter & _p, const QRect & _dr,
|
||||
QString sampleBuffer::openAudioFile() const
|
||||
{
|
||||
QFileDialog ofd( NULL, tr( "Open audio file" ) );
|
||||
#if QT_VERSION >= 0x040806
|
||||
ofd.setOption( QFileDialog::DontUseCustomDirectoryIcons );
|
||||
#endif
|
||||
|
||||
QString dir;
|
||||
if( !m_audioFile.isEmpty() )
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* song.cpp - root of the model tree
|
||||
*
|
||||
* Copyright (c) 2004-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -61,6 +61,20 @@
|
||||
#include "text_float.h"
|
||||
#include "timeline.h"
|
||||
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#ifndef USE_QT_SHMEM
|
||||
#define USE_QT_SHMEM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_QT_SHMEM
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
tick_t midiTime::s_ticksPerTact = DefaultTicksPerTact;
|
||||
|
||||
@@ -81,6 +95,7 @@ song::song() :
|
||||
m_modified( false ),
|
||||
m_recording( false ),
|
||||
m_exporting( false ),
|
||||
m_exportLoop( false ),
|
||||
m_playing( false ),
|
||||
m_paused( false ),
|
||||
m_loadingProject( false ),
|
||||
@@ -88,7 +103,13 @@ song::song() :
|
||||
m_length( 0 ),
|
||||
m_trackToPlay( NULL ),
|
||||
m_patternToPlay( NULL ),
|
||||
m_loopPattern( false )
|
||||
m_loopPattern( false ),
|
||||
m_elapsedMilliSeconds( 0 ),
|
||||
m_elapsedTicks( 0 ),
|
||||
m_elapsedTacts( 0 ),
|
||||
m_shmID( -1 ),
|
||||
m_SncVSTplug( NULL ),
|
||||
m_shmQtID( "/usr/bin/lmms" )
|
||||
{
|
||||
connect( &m_tempoModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( setTempo() ) );
|
||||
@@ -101,6 +122,59 @@ song::song() :
|
||||
connect( engine::getMixer(), SIGNAL( sampleRateChanged() ), this,
|
||||
SLOT( updateFramesPerTick() ) );
|
||||
|
||||
// handle VST plugins sync
|
||||
if( configManager::inst()->value( "ui", "syncvstplugins" ).toInt() )
|
||||
{
|
||||
connect( engine::getMixer(), SIGNAL( sampleRateChanged() ), this,
|
||||
SLOT( updateSampleRateSHM() ) );
|
||||
#ifdef USE_QT_SHMEM
|
||||
if ( !m_shmQtID.create( sizeof( sncVST ) ) )
|
||||
{
|
||||
fprintf(stderr, "song.cpp::m_shmQtID create SHM error: %s\n",
|
||||
m_shmQtID.errorString().toStdString().c_str() );
|
||||
}
|
||||
m_SncVSTplug = (sncVST *) m_shmQtID.data();
|
||||
#else
|
||||
key_t key; // make the key:
|
||||
if( ( key = ftok( VST_SNC_SHM_KEY_FILE, 'R' ) ) == -1 )
|
||||
{
|
||||
perror( "song.cpp::ftok" );
|
||||
}
|
||||
else
|
||||
{ // connect to shared memory segment
|
||||
if( ( m_shmID = shmget( key, sizeof( sncVST ),
|
||||
0644 | IPC_CREAT ) ) == -1 )
|
||||
{
|
||||
perror( "song.cpp::shmget" );
|
||||
}
|
||||
else
|
||||
{ // attach segment
|
||||
m_SncVSTplug = (sncVST *)shmat(m_shmID, 0, 0);
|
||||
if( m_SncVSTplug == (sncVST *)( -1 ) )
|
||||
{
|
||||
perror( "song.cpp::shmat" );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// if we are connected into shared memory
|
||||
if( m_SncVSTplug != NULL )
|
||||
{
|
||||
m_SncVSTplug->isPlayin = m_playing | m_exporting;
|
||||
m_SncVSTplug->hasSHM = true;
|
||||
m_SncVSTplug->m_sampleRate =
|
||||
engine::getMixer()->processingSampleRate();
|
||||
m_SncVSTplug->m_bufferSize =
|
||||
engine::getMixer()->framesPerPeriod();
|
||||
m_SncVSTplug->timeSigNumer = 4;
|
||||
m_SncVSTplug->timeSigDenom = 4;
|
||||
}
|
||||
} // end of VST plugin sync section
|
||||
|
||||
if( m_SncVSTplug == NULL )
|
||||
{
|
||||
m_SncVSTplug = (sncVST*) malloc( sizeof( sncVST ) );
|
||||
}
|
||||
|
||||
connect( &m_masterVolumeModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( masterVolumeChanged() ) );
|
||||
@@ -108,7 +182,6 @@ song::song() :
|
||||
this, SLOT( masterPitchChanged() ) );*/
|
||||
|
||||
qRegisterMetaType<note>( "note" );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +189,24 @@ song::song() :
|
||||
|
||||
song::~song()
|
||||
{
|
||||
// detach shared memory, delete it:
|
||||
#ifdef USE_QT_SHMEM
|
||||
m_shmQtID.detach();
|
||||
#else
|
||||
if( shmdt( m_SncVSTplug ) == -1)
|
||||
{
|
||||
if( m_SncVSTplug->hasSHM )
|
||||
{
|
||||
perror("~song::shmdt");
|
||||
}
|
||||
if( m_SncVSTplug != NULL )
|
||||
{
|
||||
delete m_SncVSTplug;
|
||||
m_SncVSTplug = NULL;
|
||||
}
|
||||
}
|
||||
shmctl(m_shmID, IPC_RMID, NULL);
|
||||
#endif
|
||||
m_playing = false;
|
||||
delete m_globalAutomationTrack;
|
||||
}
|
||||
@@ -150,6 +241,13 @@ void song::setTempo()
|
||||
|
||||
engine::updateFramesPerTick();
|
||||
|
||||
m_SncVSTplug->m_bpm = tempo;
|
||||
|
||||
#ifdef VST_SNC_LATENCY
|
||||
m_SncVSTplug->m_latency = m_SncVSTplug->m_bufferSize * tempo /
|
||||
( (float) m_SncVSTplug->m_sampleRate * 60 );
|
||||
#endif
|
||||
|
||||
emit tempoChanged( tempo );
|
||||
}
|
||||
|
||||
@@ -162,6 +260,8 @@ void song::setTimeSignature()
|
||||
emit timeSignatureChanged( m_oldTicksPerTact, ticksPerTact() );
|
||||
emit dataChanged();
|
||||
m_oldTicksPerTact = ticksPerTact();
|
||||
m_SncVSTplug->timeSigNumer = getTimeSigModel().getNumerator();
|
||||
m_SncVSTplug->timeSigDenom = getTimeSigModel().getDenominator();
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +271,118 @@ void song::savePos()
|
||||
{
|
||||
timeLine * tl = m_playPos[m_playMode].m_timeLine;
|
||||
|
||||
while( !m_actions.empty() )
|
||||
{
|
||||
switch( m_actions.front() )
|
||||
{
|
||||
case ActionStop:
|
||||
{
|
||||
m_playing = false;
|
||||
m_SncVSTplug->isPlayin = m_exporting;
|
||||
m_recording = true;
|
||||
if( tl != NULL )
|
||||
{
|
||||
|
||||
switch( tl->behaviourAtStop() )
|
||||
{
|
||||
case timeLine::BackToZero:
|
||||
m_playPos[m_playMode].setTicks( 0 );
|
||||
m_elapsedMilliSeconds = 0;
|
||||
break;
|
||||
|
||||
case timeLine::BackToStart:
|
||||
if( tl->savedPos() >= 0 )
|
||||
{
|
||||
m_playPos[m_playMode].setTicks(
|
||||
tl->savedPos().getTicks() );
|
||||
m_elapsedMilliSeconds = (((tl->savedPos().getTicks())*60*1000/48)/getTempo());
|
||||
tl->savePos( -1 );
|
||||
}
|
||||
break;
|
||||
|
||||
case timeLine::KeepStopPosition:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_playPos[m_playMode].setTicks( 0 );
|
||||
m_elapsedMilliSeconds = 0;
|
||||
}
|
||||
|
||||
m_playPos[m_playMode].setCurrentFrame( 0 );
|
||||
|
||||
// remove all note-play-handles that are active
|
||||
engine::getMixer()->clear();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ActionPlaySong:
|
||||
m_playMode = Mode_PlaySong;
|
||||
m_playing = true;
|
||||
m_SncVSTplug->isPlayin = true;
|
||||
Controller::resetFrameCounter();
|
||||
break;
|
||||
|
||||
case ActionPlayTrack:
|
||||
m_playMode = Mode_PlayTrack;
|
||||
m_playing = true;
|
||||
m_SncVSTplug->isPlayin = true;
|
||||
break;
|
||||
|
||||
case ActionPlayBB:
|
||||
m_playMode = Mode_PlayBB;
|
||||
m_playing = true;
|
||||
m_SncVSTplug->isPlayin = true;
|
||||
break;
|
||||
|
||||
case ActionPlayPattern:
|
||||
m_playMode = Mode_PlayPattern;
|
||||
m_playing = true;
|
||||
m_SncVSTplug->isPlayin = true;
|
||||
break;
|
||||
|
||||
case ActionPause:
|
||||
m_playing = false;// just set the play-flag
|
||||
m_SncVSTplug->isPlayin = m_exporting;
|
||||
m_paused = true;
|
||||
break;
|
||||
|
||||
case ActionResumeFromPause:
|
||||
m_playing = true;// just set the play-flag
|
||||
m_SncVSTplug->isPlayin = true;
|
||||
m_paused = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// a second switch for saving pos when starting to play
|
||||
// anything (need pos for restoring it later in certain
|
||||
// timeline-modes)
|
||||
switch( m_actions.front() )
|
||||
{
|
||||
case ActionPlaySong:
|
||||
case ActionPlayTrack:
|
||||
case ActionPlayBB:
|
||||
case ActionPlayPattern:
|
||||
{
|
||||
if( tl != NULL )
|
||||
{
|
||||
tl->savePos( m_playPos[m_playMode] );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// keep GCC happy...
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_actions.erase( m_actions.begin() );
|
||||
}
|
||||
|
||||
if( tl != NULL )
|
||||
{
|
||||
tl->savePos( m_playPos[m_playMode] );
|
||||
@@ -246,6 +458,7 @@ void song::processNextBuffer()
|
||||
if( m_playPos[m_playMode] < tl->loopBegin() ||
|
||||
m_playPos[m_playMode] >= tl->loopEnd() )
|
||||
{
|
||||
m_elapsedMilliSeconds = (tl->loopBegin().getTicks()*60*1000/48)/getTempo();
|
||||
m_playPos[m_playMode].setTicks(
|
||||
tl->loopBegin().getTicks() );
|
||||
}
|
||||
@@ -257,8 +470,14 @@ void song::processNextBuffer()
|
||||
while( total_frames_played
|
||||
< engine::getMixer()->framesPerPeriod() )
|
||||
{
|
||||
f_cnt_t played_frames = engine::getMixer()
|
||||
->framesPerPeriod() - total_frames_played;
|
||||
f_cnt_t played_frames = ( m_SncVSTplug->m_bufferSize = engine::getMixer()
|
||||
->framesPerPeriod() ) - total_frames_played;
|
||||
|
||||
#ifdef VST_SNC_LATENCY
|
||||
m_SncVSTplug->m_latency = m_SncVSTplug->m_bufferSize *
|
||||
m_SncVSTplug->m_bpm /
|
||||
( (float) m_SncVSTplug->m_sampleRate * 60 );
|
||||
#endif
|
||||
|
||||
float current_frame = m_playPos[m_playMode].currentFrame();
|
||||
// did we play a tick?
|
||||
@@ -266,6 +485,14 @@ void song::processNextBuffer()
|
||||
{
|
||||
int ticks = m_playPos[m_playMode].getTicks()
|
||||
+ (int)( current_frame / frames_per_tick );
|
||||
|
||||
#ifdef VST_SNC_LATENCY
|
||||
m_SncVSTplug->ppqPos = ( ( ticks + 0 ) / (float)48 ) -
|
||||
m_SncVSTplug->m_latency;
|
||||
#else
|
||||
m_SncVSTplug->ppqPos = ( ( ticks + 0 ) / (float)48 );
|
||||
#endif
|
||||
|
||||
// did we play a whole tact?
|
||||
if( ticks >= midiTime::ticksPerTact() )
|
||||
{
|
||||
@@ -299,18 +526,38 @@ void song::processNextBuffer()
|
||||
// offset
|
||||
ticks = ticks % ( max_tact *
|
||||
midiTime::ticksPerTact() );
|
||||
#ifdef VST_SNC_LATENCY
|
||||
m_SncVSTplug->ppqPos = ( ( ticks + 0 )
|
||||
/ (float)48 )
|
||||
- m_SncVSTplug->m_latency;
|
||||
#else
|
||||
m_SncVSTplug->ppqPos = ( ( ticks + 0 )
|
||||
/ (float)48 );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
m_playPos[m_playMode].setTicks( ticks );
|
||||
|
||||
if( check_loop )
|
||||
{
|
||||
m_SncVSTplug->isCycle = true;
|
||||
m_SncVSTplug->cycleStart =
|
||||
( tl->loopBegin().getTicks() )
|
||||
/ (float)48;
|
||||
m_SncVSTplug->cycleEnd =
|
||||
( tl->loopEnd().getTicks() )
|
||||
/ (float)48;
|
||||
if( m_playPos[m_playMode] >= tl->loopEnd() )
|
||||
{
|
||||
m_playPos[m_playMode].setTicks(
|
||||
tl->loopBegin().getTicks() );
|
||||
m_elapsedMilliSeconds = ((tl->loopBegin().getTicks())*60*1000/48)/getTempo();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SncVSTplug->isCycle = false;
|
||||
}
|
||||
|
||||
current_frame = fmodf( current_frame, frames_per_tick );
|
||||
m_playPos[m_playMode].setCurrentFrame( current_frame );
|
||||
@@ -358,6 +605,9 @@ void song::processNextBuffer()
|
||||
total_frames_played += played_frames;
|
||||
m_playPos[m_playMode].setCurrentFrame( played_frames +
|
||||
current_frame );
|
||||
m_elapsedMilliSeconds += (((played_frames/frames_per_tick)*60*1000/48)/getTempo());
|
||||
m_elapsedTacts = m_playPos[Mode_PlaySong].getTact();
|
||||
m_elapsedTicks = (m_playPos[Mode_PlaySong].getTicks()%ticksPerTact())/48;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,6 +761,8 @@ void song::updateLength()
|
||||
|
||||
void song::setPlayPos( tick_t _ticks, PlayModes _play_mode )
|
||||
{
|
||||
m_elapsedTicks += m_playPos[_play_mode].getTicks() - _ticks;
|
||||
m_elapsedMilliSeconds += (((( _ticks - m_playPos[_play_mode].getTicks()))*60*1000/48)/getTempo());
|
||||
m_playPos[_play_mode].setTicks( _ticks );
|
||||
m_playPos[_play_mode].setCurrentFrame( 0.0f );
|
||||
}
|
||||
@@ -592,6 +844,7 @@ void song::startExport()
|
||||
playSong();
|
||||
|
||||
m_exporting = true;
|
||||
m_SncVSTplug->isPlayin = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -601,6 +854,8 @@ void song::stopExport()
|
||||
{
|
||||
stop();
|
||||
m_exporting = false;
|
||||
m_exportLoop = false;
|
||||
m_SncVSTplug->isPlayin = m_playing;
|
||||
}
|
||||
|
||||
|
||||
@@ -1057,10 +1312,14 @@ void song::importProject()
|
||||
tr("MIDI sequences") +
|
||||
" (*.mid *.midi *.rmi);;" +
|
||||
tr("FL Studio projects") +
|
||||
" (*.flp"
|
||||
");;" +
|
||||
" (*.flp);;" +
|
||||
tr("Hydrogen projects") +
|
||||
" (*.h2song);;" +
|
||||
tr("All file types") +
|
||||
" (*.*)");
|
||||
#if QT_VERSION >= 0x040806
|
||||
ofd.setOption( QFileDialog::DontUseCustomDirectoryIcons );
|
||||
#endif
|
||||
|
||||
ofd.setFileMode( QFileDialog::ExistingFiles );
|
||||
if( ofd.exec () == QDialog::Accepted && !ofd.selectedFiles().isEmpty() )
|
||||
@@ -1098,9 +1357,12 @@ void song::restoreControllerStates( const QDomElement & _this )
|
||||
}
|
||||
|
||||
|
||||
void song::exportProjectTracks()
|
||||
{
|
||||
exportProject(true);
|
||||
}
|
||||
|
||||
|
||||
void song::exportProject()
|
||||
void song::exportProject(bool multiExport)
|
||||
{
|
||||
if( isEmpty() )
|
||||
{
|
||||
@@ -1113,38 +1375,54 @@ void song::exportProject()
|
||||
}
|
||||
|
||||
QFileDialog efd( engine::mainWindow() );
|
||||
efd.setFileMode( QFileDialog::AnyFile );
|
||||
efd.setAcceptMode( QFileDialog::AcceptSave );
|
||||
int idx = 0;
|
||||
QStringList types;
|
||||
while( __fileEncodeDevices[idx].m_fileFormat !=
|
||||
ProjectRenderer::NumFileFormats )
|
||||
#if QT_VERSION >= 0x040806
|
||||
efd.setOption( QFileDialog::DontUseCustomDirectoryIcons );
|
||||
#endif
|
||||
if (multiExport)
|
||||
{
|
||||
types << tr( __fileEncodeDevices[idx].m_description );
|
||||
++idx;
|
||||
}
|
||||
efd.setFilters( types );
|
||||
|
||||
QString base_filename;
|
||||
if( !m_fileName.isEmpty() )
|
||||
{
|
||||
efd.setDirectory( QFileInfo( m_fileName ).absolutePath() );
|
||||
base_filename = QFileInfo( m_fileName ).completeBaseName();
|
||||
efd.setFileMode( QFileDialog::Directory);
|
||||
efd.setWindowTitle( tr( "Select directory for writing exported tracks..." ) );
|
||||
if( !m_fileName.isEmpty() )
|
||||
{
|
||||
efd.setDirectory( QFileInfo( m_fileName ).absolutePath() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
efd.setDirectory( configManager::inst()->userProjectsDir() );
|
||||
base_filename = tr( "untitled" );
|
||||
efd.setFileMode( QFileDialog::AnyFile );
|
||||
int idx = 0;
|
||||
QStringList types;
|
||||
while( __fileEncodeDevices[idx].m_fileFormat !=
|
||||
ProjectRenderer::NumFileFormats )
|
||||
{
|
||||
types << tr( __fileEncodeDevices[idx].m_description );
|
||||
++idx;
|
||||
}
|
||||
efd.setFilters( types );
|
||||
QString base_filename;
|
||||
if( !m_fileName.isEmpty() )
|
||||
{
|
||||
efd.setDirectory( QFileInfo( m_fileName ).absolutePath() );
|
||||
base_filename = QFileInfo( m_fileName ).completeBaseName();
|
||||
}
|
||||
else
|
||||
{
|
||||
efd.setDirectory( configManager::inst()->userProjectsDir() );
|
||||
base_filename = tr( "untitled" );
|
||||
}
|
||||
efd.selectFile( base_filename + __fileEncodeDevices[0].m_extension );
|
||||
efd.setWindowTitle( tr( "Select file for project-export..." ) );
|
||||
}
|
||||
efd.selectFile( base_filename + __fileEncodeDevices[0].m_extension );
|
||||
efd.setWindowTitle( tr( "Select file for project-export..." ) );
|
||||
|
||||
efd.setAcceptMode( QFileDialog::AcceptSave );
|
||||
|
||||
|
||||
if( efd.exec() == QDialog::Accepted &&
|
||||
!efd.selectedFiles().isEmpty() && !efd.selectedFiles()[0].isEmpty() )
|
||||
{
|
||||
const QString export_file_name = efd.selectedFiles()[0];
|
||||
exportProjectDialog epd( export_file_name,
|
||||
engine::mainWindow() );
|
||||
engine::mainWindow(), multiExport );
|
||||
epd.exec();
|
||||
}
|
||||
}
|
||||
@@ -1160,6 +1438,19 @@ void song::updateFramesPerTick()
|
||||
|
||||
|
||||
|
||||
void song::updateSampleRateSHM()
|
||||
{
|
||||
m_SncVSTplug->m_sampleRate = engine::getMixer()->processingSampleRate();
|
||||
|
||||
#ifdef VST_SNC_LATENCY
|
||||
m_SncVSTplug->m_latency = m_SncVSTplug->m_bufferSize * m_SncVSTplug->m_bpm /
|
||||
( (float) m_SncVSTplug->m_sampleRate * 60 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void song::setModified()
|
||||
{
|
||||
if( !m_loadingProject )
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* timeline.cpp - class timeLine, representing a time-line with position marker
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -324,6 +324,7 @@ void timeLine::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
case MovePositionMarker:
|
||||
m_pos.setTicks( t.getTicks() );
|
||||
engine::getSong()->setMilliSeconds(((((t.getTicks()))*60*1000/48)/engine::getSong()->getTempo()));
|
||||
m_pos.setCurrentFrame( 0 );
|
||||
updatePosition();
|
||||
break;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* track.cpp - implementation of classes concerning tracks -> necessary for
|
||||
* all track-like objects (beat/bassline, sample-track...)
|
||||
*
|
||||
* Copyright (c) 2004-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -31,7 +31,7 @@
|
||||
* \mainpage Track classes
|
||||
*
|
||||
* \section introduction Introduction
|
||||
*
|
||||
*
|
||||
* \todo fill this out
|
||||
*/
|
||||
|
||||
@@ -80,13 +80,6 @@ const Sint16 RESIZE_GRIP_WIDTH = 4;
|
||||
const Uint16 TRACK_OP_BTN_WIDTH = 20;
|
||||
const Uint16 TRACK_OP_BTN_HEIGHT = 14;
|
||||
|
||||
/*! The minimum track height in pixels
|
||||
*
|
||||
* Tracks can be resized by shift-dragging anywhere inside the track
|
||||
* display. This sets the minimum size in pixels for a track.
|
||||
*/
|
||||
const Uint16 MINIMAL_TRACK_HEIGHT = 32;
|
||||
|
||||
|
||||
/*! A pointer for that text bubble used when moving segments, etc.
|
||||
*
|
||||
@@ -644,7 +637,7 @@ void trackContentObjectView::mousePressEvent( QMouseEvent * _me )
|
||||
* * If in move mode, move ourselves in the track,
|
||||
* * or if in move-selection mode, move the entire selection,
|
||||
* * or if in resize mode, resize ourselves,
|
||||
* * otherwise ???
|
||||
* * otherwise ???
|
||||
*
|
||||
* \param _me The QMouseEvent to handle.
|
||||
* \todo what does the final else case do here?
|
||||
@@ -1199,7 +1192,7 @@ void trackContentWidget::paintEvent( QPaintEvent * _pe )
|
||||
// Don't draw background on BB-Editor
|
||||
if( m_trackView->getTrackContainerView() != engine::getBBEditor() )
|
||||
{
|
||||
p.drawTiledPixmap( rect(), m_background, QPoint(
|
||||
p.drawTiledPixmap( rect(), m_background, QPoint(
|
||||
tcv->currentPosition().getTact() * ppt, 0 ) );
|
||||
}
|
||||
}
|
||||
@@ -1563,6 +1556,7 @@ track::track( TrackTypes _type, trackContainer * _tc ) :
|
||||
m_trackContentObjects() /*!< The track content objects (segments) */
|
||||
{
|
||||
m_trackContainer->addTrack( this );
|
||||
m_height = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1679,8 +1673,10 @@ void track::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
_this.setAttribute( "type", type() );
|
||||
_this.setAttribute( "name", name() );
|
||||
_this.setAttribute( "muted", isMuted() );
|
||||
// ### TODO
|
||||
// _this.setAttribute( "height", m_trackView->height() );
|
||||
if( m_height >= MINIMAL_TRACK_HEIGHT )
|
||||
{
|
||||
_this.setAttribute( "height", m_height );
|
||||
}
|
||||
|
||||
QDomElement ts_de = _doc.createElement( nodeName() );
|
||||
// let actual track (InstrumentTrack, bbTrack, sampleTrack etc.) save
|
||||
@@ -1772,13 +1768,13 @@ void track::loadSettings( const QDomElement & _this )
|
||||
}
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
/*
|
||||
if( _this.attribute( "height" ).toInt() >= MINIMAL_TRACK_HEIGHT )
|
||||
}
|
||||
|
||||
if( _this.attribute( "height" ).toInt() >= MINIMAL_TRACK_HEIGHT &&
|
||||
_this.attribute( "height" ).toInt() <= DEFAULT_TRACK_HEIGHT ) // workaround for #3585927, tobydox/2012-11-11
|
||||
{
|
||||
m_trackView->setFixedHeight(
|
||||
_this.attribute( "height" ).toInt() );
|
||||
}*/
|
||||
m_height = _this.attribute( "height" ).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2122,6 +2118,7 @@ trackView::trackView( track * _track, trackContainerView * _tcv ) :
|
||||
layout->addWidget( &m_trackOperationsWidget );
|
||||
layout->addWidget( &m_trackSettingsWidget );
|
||||
layout->addWidget( &m_trackContentWidget, 1 );
|
||||
setFixedHeight( m_track->getHeight() );
|
||||
|
||||
resizeEvent( NULL );
|
||||
|
||||
@@ -2225,7 +2222,8 @@ void trackView::modelChanged()
|
||||
connect( m_track, SIGNAL( destroyedTrack() ), this, SLOT( close() ) );
|
||||
m_trackOperationsWidget.m_muteBtn->setModel( &m_track->m_mutedModel );
|
||||
m_trackOperationsWidget.m_soloBtn->setModel( &m_track->m_soloModel );
|
||||
ModelView::modelChanged();
|
||||
ModelView::modelChanged();
|
||||
setFixedHeight( m_track->getHeight() );
|
||||
}
|
||||
|
||||
|
||||
@@ -2256,6 +2254,10 @@ void trackView::undoStep( JournalEntry & _je )
|
||||
MINIMAL_TRACK_HEIGHT ) );
|
||||
m_trackContainerView->realignTracks();
|
||||
break;
|
||||
/*case RestoreTrack:
|
||||
setFixedHeight( DEFAULT_TRACK_HEIGHT );
|
||||
m_trackContainerView->realignTracks();
|
||||
break; */
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
@@ -2331,6 +2333,16 @@ void trackView::dropEvent( QDropEvent * _de )
|
||||
*/
|
||||
void trackView::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
// If previously dragged too small, restore on shift-leftclick
|
||||
if( height() < DEFAULT_TRACK_HEIGHT &&
|
||||
_me->modifiers() & Qt::ShiftModifier &&
|
||||
_me->button() == Qt::LeftButton )
|
||||
{
|
||||
setFixedHeight( DEFAULT_TRACK_HEIGHT );
|
||||
m_track->setHeight( DEFAULT_TRACK_HEIGHT );
|
||||
}
|
||||
|
||||
|
||||
if( m_trackContainerView->allowRubberband() == true )
|
||||
{
|
||||
QWidget::mousePressEvent( _me );
|
||||
@@ -2385,6 +2397,7 @@ void trackView::mousePressEvent( QMouseEvent * _me )
|
||||
*/
|
||||
void trackView::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
|
||||
if( m_trackContainerView->allowRubberband() == true )
|
||||
{
|
||||
QWidget::mouseMoveEvent( _me );
|
||||
@@ -2415,12 +2428,17 @@ void trackView::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
setFixedHeight( qMax<int>( _me->y(), MINIMAL_TRACK_HEIGHT ) );
|
||||
m_trackContainerView->realignTracks();
|
||||
m_track->setHeight( height() );
|
||||
}
|
||||
|
||||
if( height() < DEFAULT_TRACK_HEIGHT )
|
||||
{
|
||||
toolTip::add( this, m_track->m_name );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Handle a mouse release event on this track View.
|
||||
*
|
||||
* \param _me the MouseEvent to handle.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* AutomatableModelView.cpp - implementation of AutomatableModelView
|
||||
*
|
||||
* Copyright (c) 2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2011-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -88,6 +88,12 @@ void AutomatableModelView::addDefaultActions( QMenu * _menu )
|
||||
AutomatableModel::tr( "Edit song-global automation" ),
|
||||
amvSlots,
|
||||
SLOT( editSongGlobalAutomation() ) );
|
||||
|
||||
_menu->addAction( QPixmap(),
|
||||
AutomatableModel::tr( "Remove song-global automation" ),
|
||||
amvSlots,
|
||||
SLOT( removeSongGlobalAutomation() ) );
|
||||
|
||||
_menu->addSeparator();
|
||||
|
||||
QString controllerTxt;
|
||||
@@ -241,4 +247,11 @@ void AutomatableModelViewSlots::editSongGlobalAutomation()
|
||||
|
||||
|
||||
|
||||
void AutomatableModelViewSlots::removeSongGlobalAutomation()
|
||||
{
|
||||
delete AutomationPattern::globalAutomationPattern( amv->modelUntyped() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_AutomatableModelView.cxx"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* AutomationEditor.cpp - implementation of AutomationEditor which is used for
|
||||
* actual setting of dynamic values
|
||||
*
|
||||
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
@@ -36,6 +36,8 @@
|
||||
#include <QtGui/QScrollBar>
|
||||
#include <QtGui/QStyleOption>
|
||||
#include <QtGui/QWheelEvent>
|
||||
#include <QToolTip>
|
||||
|
||||
|
||||
|
||||
#ifndef __USE_XOPEN
|
||||
@@ -1256,6 +1258,10 @@ inline void AutomationEditor::drawCross( QPainter & _p )
|
||||
_p.drawLine( VALUES_WIDTH, (int) cross_y, width(), (int) cross_y );
|
||||
_p.drawLine( mouse_pos.x(), TOP_MARGIN, mouse_pos.x(),
|
||||
height() - SCROLLBAR_SIZE );
|
||||
QPoint tt_pos = QCursor::pos();
|
||||
tt_pos.ry() -= 64;
|
||||
tt_pos.rx() += 32;
|
||||
QToolTip::showText( tt_pos,QString::number( level ),this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1440,7 +1446,8 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe )
|
||||
timeMap & time_map = m_pattern->getTimeMap();
|
||||
timeMap::iterator it = time_map.begin();
|
||||
p.setPen( QColor( 0xFF, 0xDF, 0x20 ) );
|
||||
do
|
||||
|
||||
while( it != time_map.end() )
|
||||
{
|
||||
Sint32 len_ticks = 4;
|
||||
|
||||
@@ -1532,7 +1539,7 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe )
|
||||
}
|
||||
else printf("not in range\n");
|
||||
++it;
|
||||
} while( it != time_map.end() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -427,7 +427,10 @@ void ControllerConnectionDialog::midiValueChanged()
|
||||
if( m_midiAutoDetect.value() )
|
||||
{
|
||||
m_midiController->useDetected();
|
||||
m_readablePorts->updateMenu();
|
||||
if( m_readablePorts )
|
||||
{
|
||||
m_readablePorts->updateMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ FxMixerView::FxMixerView() :
|
||||
flags |= Qt::MSWindowsFixedSizeDialogHint;
|
||||
flags &= ~Qt::WindowMaximizeButtonHint;
|
||||
subWin->setWindowFlags( flags );
|
||||
subWin->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
//subWin->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false );
|
||||
parentWidget()->move( 5, 310 );
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* main_window.cpp - implementation of LMMS-main-window
|
||||
*
|
||||
* Copyright (c) 2004-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -184,9 +182,12 @@ MainWindow::MainWindow( void ) :
|
||||
|
||||
m_updateTimer.start( 1000 / 20, this ); // 20 fps
|
||||
|
||||
// connect auto save
|
||||
connect(&m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSave()));
|
||||
m_autoSaveTimer.start(1000 * 60); // 1 minute
|
||||
if( configManager::inst()->value( "ui", "enableautosave" ).toInt() )
|
||||
{
|
||||
// connect auto save
|
||||
connect(&m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(autoSave()));
|
||||
m_autoSaveTimer.start(1000 * 60); // 1 minute
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +256,12 @@ void MainWindow::finalize( void )
|
||||
engine::getSong(),
|
||||
SLOT( exportProject() ),
|
||||
Qt::CTRL + Qt::Key_E );
|
||||
project_menu->addAction( embed::getIconPixmap( "project_export" ),
|
||||
tr( "E&xport tracks..." ),
|
||||
engine::getSong(),
|
||||
SLOT( exportProjectTracks() ),
|
||||
Qt::CTRL + Qt::SHIFT + Qt::Key_E );
|
||||
|
||||
project_menu->addSeparator();
|
||||
project_menu->addAction( embed::getIconPixmap( "exit" ), tr( "&Quit" ),
|
||||
qApp, SLOT( closeAllWindows() ),
|
||||
@@ -681,6 +688,9 @@ void MainWindow::openProject( void )
|
||||
{
|
||||
QFileDialog ofd( this, tr( "Open project" ), "",
|
||||
tr( "MultiMedia Project (*.mmp *.mmpz *.xml)" ) );
|
||||
#if QT_VERSION >= 0x040806
|
||||
ofd.setOption( QFileDialog::DontUseCustomDirectoryIcons );
|
||||
#endif
|
||||
ofd.setDirectory( configManager::inst()->userProjectsDir() );
|
||||
ofd.setFileMode( QFileDialog::ExistingFiles );
|
||||
if( ofd.exec () == QDialog::Accepted &&
|
||||
@@ -744,6 +754,9 @@ bool MainWindow::saveProjectAs( void )
|
||||
QFileDialog sfd( this, tr( "Save project" ), "",
|
||||
tr( "MultiMedia Project (*.mmp *.mmpz);;"
|
||||
"MultiMedia Project Template (*.mpt)" ) );
|
||||
#if QT_VERSION >= 0x040806
|
||||
sfd.setOption( QFileDialog::DontUseCustomDirectoryIcons );
|
||||
#endif
|
||||
sfd.setAcceptMode( QFileDialog::AcceptSave );
|
||||
sfd.setFileMode( QFileDialog::AnyFile );
|
||||
QString f = engine::getSong()->projectFileName();
|
||||
@@ -801,16 +814,17 @@ void MainWindow::help( void )
|
||||
|
||||
|
||||
|
||||
void MainWindow::toggleWindow( QWidget * _w )
|
||||
void MainWindow::toggleWindow( QWidget *window, bool forceShow )
|
||||
{
|
||||
QWidget * parent = _w->parentWidget();
|
||||
QWidget *parent = window->parentWidget();
|
||||
|
||||
if( m_workspace->activeSubWindow() != parent
|
||||
|| parent->isHidden() )
|
||||
if( forceShow ||
|
||||
m_workspace->activeSubWindow() != parent ||
|
||||
parent->isHidden() )
|
||||
{
|
||||
parent->show();
|
||||
_w->show();
|
||||
_w->setFocus();
|
||||
window->show();
|
||||
window->setFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -827,9 +841,9 @@ void MainWindow::toggleWindow( QWidget * _w )
|
||||
|
||||
|
||||
|
||||
void MainWindow::toggleBBEditorWin( void )
|
||||
void MainWindow::toggleBBEditorWin( bool forceShow )
|
||||
{
|
||||
toggleWindow( engine::getBBEditor() );
|
||||
toggleWindow( engine::getBBEditor(), forceShow );
|
||||
}
|
||||
|
||||
|
||||
@@ -1063,5 +1077,3 @@ void MainWindow::autoSave()
|
||||
|
||||
#include "moc_MainWindow.cxx"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,11 +57,6 @@
|
||||
#include "templates.h"
|
||||
#include "update_event.h"
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*! The black / white order of keys as they appear on the keyboard.
|
||||
*/
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Copyright (c) 2004-2012, LMMS developers</string>
|
||||
<string>Copyright (c) 2004-2013, LMMS developers</string>
|
||||
</property>
|
||||
<property name="wordWrap" >
|
||||
<bool>true</bool>
|
||||
|
||||
@@ -279,6 +279,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exportLoopCB">
|
||||
<property name="text">
|
||||
<string>Export as loop (remove end silence)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="aliasFreeOscillatorsCB" >
|
||||
<property name="text" >
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* export_project_dialog.cpp - implementation of dialog for exporting project
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -23,20 +23,24 @@
|
||||
*/
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
#include "export_project_dialog.h"
|
||||
#include "song.h"
|
||||
#include "engine.h"
|
||||
#include "MainWindow.h"
|
||||
#include "ProjectRenderer.h"
|
||||
#include "bb_track_container.h"
|
||||
#include "bb_track.h"
|
||||
|
||||
|
||||
exportProjectDialog::exportProjectDialog( const QString & _file_name,
|
||||
QWidget * _parent ) :
|
||||
QWidget * _parent, bool multi_export=false ) :
|
||||
QDialog( _parent ),
|
||||
Ui::ExportProjectDialog(),
|
||||
m_fileName( _file_name ),
|
||||
m_renderer( NULL )
|
||||
m_fileExtension(),
|
||||
m_multiExport(multi_export)
|
||||
{
|
||||
setupUi( this );
|
||||
setWindowTitle( tr( "Export project to %1" ).arg(
|
||||
@@ -83,7 +87,12 @@ exportProjectDialog::exportProjectDialog( const QString & _file_name,
|
||||
|
||||
exportProjectDialog::~exportProjectDialog()
|
||||
{
|
||||
delete m_renderer;
|
||||
|
||||
for( RenderVector::ConstIterator it = m_renderers.begin();
|
||||
it != m_renderers.end(); ++it )
|
||||
{
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,13 +100,35 @@ exportProjectDialog::~exportProjectDialog()
|
||||
|
||||
void exportProjectDialog::reject()
|
||||
{
|
||||
if( m_renderer == NULL )
|
||||
for( RenderVector::ConstIterator it = m_renderers.begin(); it != m_renderers.end(); ++it )
|
||||
{
|
||||
accept();
|
||||
(*it)->abortProcessing();
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::accept()
|
||||
{
|
||||
// If more to render, kick off next render job
|
||||
if( m_renderers.isEmpty() == false )
|
||||
{
|
||||
popRender();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderer->abortProcessing();
|
||||
// If done, then reset mute states
|
||||
while( m_unmuted.isEmpty() == false )
|
||||
{
|
||||
track* restoreTrack = m_unmuted.back();
|
||||
m_unmuted.pop_back();
|
||||
restoreTrack->setMuted( false );
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,19 +137,154 @@ void exportProjectDialog::reject()
|
||||
|
||||
void exportProjectDialog::closeEvent( QCloseEvent * _ce )
|
||||
{
|
||||
if( m_renderer != NULL && m_renderer->isRunning() )
|
||||
for( RenderVector::ConstIterator it = m_renderers.begin(); it != m_renderers.end(); ++it )
|
||||
{
|
||||
m_renderer->abortProcessing();
|
||||
if( (*it)->isRunning() )
|
||||
{
|
||||
(*it)->abortProcessing();
|
||||
}
|
||||
}
|
||||
QDialog::closeEvent( _ce );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::popRender()
|
||||
{
|
||||
if( m_multiExport && m_tracksToRender.isEmpty() == false )
|
||||
{
|
||||
track* renderTrack = m_tracksToRender.back();
|
||||
m_tracksToRender.pop_back();
|
||||
|
||||
// Set must states for song tracks
|
||||
for( TrackVector::ConstIterator it = m_unmuted.begin(); it != m_unmuted.end(); ++it )
|
||||
{
|
||||
if( (*it) == renderTrack )
|
||||
{
|
||||
(*it)->setMuted( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
(*it)->setMuted( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pop next render job and start
|
||||
ProjectRenderer* r = m_renderers.back();
|
||||
m_renderers.pop_back();
|
||||
render( r );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::multiRender()
|
||||
{
|
||||
m_dirName = m_fileName;
|
||||
QString path = QDir(m_fileName).filePath("text.txt");
|
||||
|
||||
int x = 1;
|
||||
|
||||
const trackContainer::trackList & tl = engine::getSong()->tracks();
|
||||
|
||||
// Check for all unmuted tracks. Remember list.
|
||||
for( trackContainer::trackList::ConstIterator it = tl.begin();
|
||||
it != tl.end(); ++it )
|
||||
{
|
||||
track* tk = (*it);
|
||||
track::TrackTypes type = tk->type();
|
||||
// Don't mute automation tracks
|
||||
if ( tk->isMuted() == false &&
|
||||
( type == track::InstrumentTrack || type == track::SampleTrack ) )
|
||||
{
|
||||
m_unmuted.push_back(tk);
|
||||
QString nextName = tk->name();
|
||||
nextName = nextName.remove(QRegExp("[^a-zA-Z]"));
|
||||
QString name = QString( "%1_%2%3" ).arg( x++ ).arg( nextName ).arg( m_fileExtension );
|
||||
m_fileName = QDir(m_dirName).filePath(name);
|
||||
prepRender();
|
||||
}
|
||||
else if (! tk->isMuted() && type == track::BBTrack )
|
||||
{
|
||||
m_unmutedBB.push_back(tk);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const trackContainer::trackList t2 = engine::getBBTrackContainer()->tracks();
|
||||
for( trackContainer::trackList::ConstIterator it = t2.begin(); it != t2.end(); ++it )
|
||||
{
|
||||
track* tk = (*it);
|
||||
if ( tk->isMuted() == false )
|
||||
{
|
||||
m_unmuted.push_back(tk);
|
||||
QString nextName = tk->name();
|
||||
nextName = nextName.remove(QRegExp("[^a-zA-Z]"));
|
||||
QString name = QString( "%1_%2%3" ).arg( x++ ).arg( nextName ).arg( m_fileExtension );
|
||||
m_fileName = QDir(m_dirName).filePath(name);
|
||||
prepRender();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_tracksToRender = m_unmuted;
|
||||
|
||||
popRender();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ProjectRenderer* exportProjectDialog::prepRender()
|
||||
{
|
||||
mixer::qualitySettings qs =
|
||||
mixer::qualitySettings(
|
||||
static_cast<mixer::qualitySettings::Interpolation>(interpolationCB->currentIndex()),
|
||||
static_cast<mixer::qualitySettings::Oversampling>(oversamplingCB->currentIndex()),
|
||||
sampleExactControllersCB->isChecked(),
|
||||
aliasFreeOscillatorsCB->isChecked() );
|
||||
|
||||
ProjectRenderer::OutputSettings os = ProjectRenderer::OutputSettings(
|
||||
samplerateCB->currentText().section(" ", 0, 0).toUInt(),
|
||||
false,
|
||||
bitrateCB->currentText().section(" ", 0, 0).toUInt(),
|
||||
static_cast<ProjectRenderer::Depths>( depthCB->currentIndex() ) );
|
||||
|
||||
engine::getSong()->setExportLoop( exportLoopCB->isChecked() );
|
||||
|
||||
ProjectRenderer* renderer = new ProjectRenderer( qs, os, m_ft, m_fileName );
|
||||
|
||||
m_renderers.push_back(renderer);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::render( ProjectRenderer* renderer )
|
||||
{
|
||||
|
||||
if( renderer->isReady() )
|
||||
{
|
||||
connect( renderer, SIGNAL( progressChanged( int ) ), progressBar, SLOT( setValue( int ) ) );
|
||||
connect( renderer, SIGNAL( progressChanged( int ) ), this, SLOT( updateTitleBar( int ) )) ;
|
||||
connect( renderer, SIGNAL( finished() ), this, SLOT( accept() ) );
|
||||
connect( renderer, SIGNAL( finished() ), engine::mainWindow(), SLOT( resetWindowTitle() ) );
|
||||
|
||||
renderer->startProcessing();
|
||||
}
|
||||
else
|
||||
{
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void exportProjectDialog::startBtnClicked()
|
||||
{
|
||||
ProjectRenderer::ExportFileFormats ft = ProjectRenderer::NumFileFormats;
|
||||
m_ft = ProjectRenderer::NumFileFormats;
|
||||
|
||||
for( int i = 0; i < ProjectRenderer::NumFileFormats; ++i )
|
||||
{
|
||||
@@ -126,12 +292,13 @@ void exportProjectDialog::startBtnClicked()
|
||||
ProjectRenderer::tr(
|
||||
__fileEncodeDevices[i].m_description ) )
|
||||
{
|
||||
ft = __fileEncodeDevices[i].m_fileFormat;
|
||||
m_ft = __fileEncodeDevices[i].m_fileFormat;
|
||||
m_fileExtension = QString( QLatin1String( __fileEncodeDevices[i].m_extension ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( ft == ProjectRenderer::NumFileFormats )
|
||||
if( m_ft == ProjectRenderer::NumFileFormats )
|
||||
{
|
||||
QMessageBox::information( this, tr( "Error" ),
|
||||
tr( "Error while determining file-encoder device. "
|
||||
@@ -146,38 +313,14 @@ void exportProjectDialog::startBtnClicked()
|
||||
|
||||
updateTitleBar( 0 );
|
||||
|
||||
mixer::qualitySettings qs = mixer::qualitySettings(
|
||||
static_cast<mixer::qualitySettings::Interpolation>(
|
||||
interpolationCB->currentIndex() ),
|
||||
static_cast<mixer::qualitySettings::Oversampling>(
|
||||
oversamplingCB->currentIndex() ),
|
||||
sampleExactControllersCB->isChecked(),
|
||||
aliasFreeOscillatorsCB->isChecked() );
|
||||
|
||||
ProjectRenderer::OutputSettings os = ProjectRenderer::OutputSettings(
|
||||
samplerateCB->currentText().section( " ", 0, 0 ).toUInt(),
|
||||
false,
|
||||
bitrateCB->currentText().section( " ", 0, 0 ).toUInt(),
|
||||
static_cast<ProjectRenderer::Depths>(
|
||||
depthCB->currentIndex() ) );
|
||||
|
||||
m_renderer = new ProjectRenderer( qs, os, ft, m_fileName );
|
||||
if( m_renderer->isReady() )
|
||||
if (m_multiExport==true)
|
||||
{
|
||||
connect( m_renderer, SIGNAL( progressChanged( int ) ),
|
||||
progressBar, SLOT( setValue( int ) ) );
|
||||
connect( m_renderer, SIGNAL( progressChanged( int ) ),
|
||||
this, SLOT( updateTitleBar( int ) ) );
|
||||
connect( m_renderer, SIGNAL( finished() ),
|
||||
this, SLOT( accept() ) );
|
||||
connect( m_renderer, SIGNAL( finished() ),
|
||||
engine::mainWindow(), SLOT( resetWindowTitle() ) );
|
||||
|
||||
m_renderer->startProcessing();
|
||||
multiRender();
|
||||
}
|
||||
else
|
||||
{
|
||||
accept();
|
||||
prepRender();
|
||||
popRender();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -667,11 +667,12 @@ void pianoRoll::markSemiTone( int i )
|
||||
|
||||
const int first = chord->isScale() ? 0 : key;
|
||||
const int last = chord->isScale() ? NumKeys : key + chord->last();
|
||||
const int cap = chord->isScale() ? KeysPerOctave : chord->last();
|
||||
const int cap = ( chord->isScale() || chord->last() == 0 ) ? KeysPerOctave : chord->last();
|
||||
|
||||
for( int i = first; i <= last; i++ )
|
||||
{
|
||||
if( chord->hasSemiTone( std::abs( key - i ) % cap ) )
|
||||
//if( chord->hasSemiTone( std::abs( key - i ) % cap ) )
|
||||
if( chord->hasSemiTone( ( i + cap - ( key % cap ) ) % cap ) )
|
||||
{
|
||||
m_markedSemiTones.push_back( i );
|
||||
}
|
||||
@@ -2689,6 +2690,24 @@ void pianoRoll::paintEvent( QPaintEvent * _pe )
|
||||
|
||||
int key = m_startKey;
|
||||
|
||||
// display note marks before drawing other lines
|
||||
for( int i = 0; i < m_markedSemiTones.size(); i++ )
|
||||
{
|
||||
const int key_num = m_markedSemiTones.at( i );
|
||||
const int y = keyAreaBottom() + 5
|
||||
- KEY_LINE_HEIGHT * ( key_num - m_startKey + 1 );
|
||||
|
||||
if( y > keyAreaBottom() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p.fillRect( WHITE_KEY_WIDTH+1, y-KEY_LINE_HEIGHT/2,
|
||||
width() - 10, KEY_LINE_HEIGHT,
|
||||
QColor( 0, 80 - ( key_num % KeysPerOctave ) * 3, 64 + key_num / 2) );
|
||||
}
|
||||
|
||||
|
||||
// draw all white keys...
|
||||
for( int y = key_line_y + 1 + y_offset; y > PR_TOP_MARGIN;
|
||||
key_line_y -= KEY_LINE_HEIGHT, ++keys_processed )
|
||||
@@ -2817,22 +2836,6 @@ void pianoRoll::paintEvent( QPaintEvent * _pe )
|
||||
++key;
|
||||
}
|
||||
|
||||
// display note marks
|
||||
for( int i = 0; i < m_markedSemiTones.size(); i++ )
|
||||
{
|
||||
const int key_num = m_markedSemiTones.at( i );
|
||||
const int y = keyAreaBottom() + 5
|
||||
- KEY_LINE_HEIGHT * ( key_num - m_startKey + 1 );
|
||||
|
||||
if( y > keyAreaBottom() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p.fillRect( WHITE_KEY_WIDTH, y,
|
||||
width() - 10, 1,
|
||||
QColor( 64, 64 + ( key_num % KeysPerOctave ) * 7, 96 + key_num ) );
|
||||
}
|
||||
|
||||
// erase the area below the piano, because there might be keys that
|
||||
// should be only half-visible
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* setup_dialog.cpp - dialog for setting up LMMS
|
||||
*
|
||||
* Copyright (c) 2005-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -113,10 +113,15 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
|
||||
m_manualChPiano( configManager::inst()->value( "ui",
|
||||
"manualchannelpiano" ).toInt() ),
|
||||
m_smoothScroll( configManager::inst()->value( "ui", "smoothscroll" ).toInt() ),
|
||||
m_enableAutoSave( configManager::inst()->value( "ui", "enableautosave" ).toInt() ),
|
||||
m_oneInstrumentTrackWindow( configManager::inst()->value( "ui",
|
||||
"oneinstrumenttrackwindow" ).toInt() ),
|
||||
m_compactTrackButtons( configManager::inst()->value( "ui",
|
||||
"compacttrackbuttons" ).toInt() )
|
||||
"compacttrackbuttons" ).toInt() ),
|
||||
m_syncVSTPlugins( configManager::inst()->value( "ui",
|
||||
"syncvstplugins" ).toInt() ),
|
||||
m_animateAFP(configManager::inst()->value( "ui",
|
||||
"animateafp").toInt() )
|
||||
{
|
||||
setWindowIcon( embed::getIconPixmap( "setup_general" ) );
|
||||
setWindowTitle( tr( "Setup LMMS" ) );
|
||||
@@ -185,7 +190,7 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
|
||||
|
||||
|
||||
tabWidget * misc_tw = new tabWidget( tr( "MISC" ), general );
|
||||
misc_tw->setFixedHeight( 156 );
|
||||
misc_tw->setFixedHeight( 174 );
|
||||
|
||||
ledCheckBox * enable_tooltips = new ledCheckBox(
|
||||
tr( "Enable tooltips" ),
|
||||
@@ -246,6 +251,15 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
|
||||
this, SLOT( toggleCompactTrackButtons( bool ) ) );
|
||||
|
||||
|
||||
ledCheckBox * syncVST = new ledCheckBox(
|
||||
tr( "Sync VST plugins to host playback" ),
|
||||
misc_tw );
|
||||
syncVST->move( 10, 144 );
|
||||
syncVST->setChecked( m_syncVSTPlugins );
|
||||
connect( syncVST, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( toggleSyncVSTPlugins( bool ) ) );
|
||||
|
||||
|
||||
|
||||
gen_layout->addWidget( bufsize_tw );
|
||||
gen_layout->addSpacing( 10 );
|
||||
@@ -464,7 +478,7 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
|
||||
tabWidget * ui_fx_tw = new tabWidget( tr( "UI effects vs. "
|
||||
"performance" ).toUpper(),
|
||||
performance );
|
||||
ui_fx_tw->setFixedHeight( 90 );
|
||||
ui_fx_tw->setFixedHeight( 120 );
|
||||
|
||||
ledCheckBox * disable_ch_act_ind = new ledCheckBox(
|
||||
tr( "Disable channel activity indicators" ),
|
||||
@@ -491,6 +505,23 @@ setupDialog::setupDialog( ConfigTabs _tab_to_open ) :
|
||||
this, SLOT( toggleSmoothScroll( bool ) ) );
|
||||
|
||||
|
||||
ledCheckBox * autoSave = new ledCheckBox(
|
||||
tr( "Enable auto save feature" ), ui_fx_tw );
|
||||
autoSave->move( 10, 80 );
|
||||
autoSave->setChecked( m_enableAutoSave );
|
||||
connect( autoSave, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( toggleAutoSave( bool ) ) );
|
||||
|
||||
|
||||
ledCheckBox * animAFP = new ledCheckBox(
|
||||
tr( "Show playback cursor in AudioFileProcessor" ),
|
||||
ui_fx_tw );
|
||||
animAFP->move( 10, 100 );
|
||||
animAFP->setChecked( m_animateAFP );
|
||||
connect( animAFP, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( toggleAnimateAFP( bool ) ) );
|
||||
|
||||
|
||||
|
||||
perf_layout->addWidget( ui_fx_tw );
|
||||
perf_layout->addStretch();
|
||||
@@ -759,10 +790,17 @@ void setupDialog::accept()
|
||||
QString::number( m_manualChPiano ) );
|
||||
configManager::inst()->setValue( "ui", "smoothscroll",
|
||||
QString::number( m_smoothScroll ) );
|
||||
configManager::inst()->setValue( "ui", "enableautosave",
|
||||
QString::number( m_enableAutoSave ) );
|
||||
configManager::inst()->setValue( "ui", "oneinstrumenttrackwindow",
|
||||
QString::number( m_oneInstrumentTrackWindow ) );
|
||||
configManager::inst()->setValue( "ui", "compacttrackbuttons",
|
||||
QString::number( m_compactTrackButtons ) );
|
||||
configManager::inst()->setValue( "ui", "syncvstplugins",
|
||||
QString::number( m_syncVSTPlugins ) );
|
||||
configManager::inst()->setValue( "ui", "animateafp",
|
||||
QString::number( m_animateAFP ) );
|
||||
|
||||
|
||||
configManager::inst()->setWorkingDir( m_workingDir );
|
||||
configManager::inst()->setVSTDir( m_vstDir );
|
||||
@@ -926,6 +964,14 @@ void setupDialog::toggleSmoothScroll( bool _enabled )
|
||||
|
||||
|
||||
|
||||
void setupDialog::toggleAutoSave( bool _enabled )
|
||||
{
|
||||
m_enableAutoSave = _enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::toggleCompactTrackButtons( bool _enabled )
|
||||
@@ -937,6 +983,20 @@ void setupDialog::toggleCompactTrackButtons( bool _enabled )
|
||||
|
||||
|
||||
|
||||
void setupDialog::toggleSyncVSTPlugins( bool _enabled )
|
||||
{
|
||||
m_syncVSTPlugins = _enabled;
|
||||
}
|
||||
|
||||
void setupDialog::toggleAnimateAFP( bool _enabled )
|
||||
{
|
||||
m_animateAFP = _enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void setupDialog::toggleOneInstrumentTrackWindow( bool _enabled )
|
||||
{
|
||||
m_oneInstrumentTrackWindow = _enabled;
|
||||
@@ -950,7 +1010,11 @@ void setupDialog::openWorkingDir()
|
||||
{
|
||||
QString new_dir = QFileDialog::getExistingDirectory( this,
|
||||
tr( "Choose LMMS working directory" ),
|
||||
m_workingDir );
|
||||
m_workingDir
|
||||
#if QT_VERSION >= 0x040806
|
||||
, QFileDialog::DontUseCustomDirectoryIcons
|
||||
#endif
|
||||
);
|
||||
if( new_dir != QString::null )
|
||||
{
|
||||
m_wdLineEdit->setText( new_dir );
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* song_editor.cpp - basic window for song-editing
|
||||
*
|
||||
* Copyright (c) 2004-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "tool_button.h"
|
||||
#include "tooltip.h"
|
||||
#include "visualization_widget.h"
|
||||
#include "TimeDisplayWidget.h"
|
||||
#include "AudioDevice.h"
|
||||
#include "piano_roll.h"
|
||||
#include "config_mgr.h"
|
||||
@@ -130,7 +131,7 @@ songEditor::songEditor( song * _song, songEditor * & _engine_ptr ) :
|
||||
"should be played within a minute (or how many measures "
|
||||
"should be played within four minutes)." ) );
|
||||
|
||||
engine::mainWindow()->addWidgetToToolBar( m_tempoSpinBox, 0 );
|
||||
int tempoSpinBoxCol = engine::mainWindow()->addWidgetToToolBar( m_tempoSpinBox, 0 );
|
||||
|
||||
#if 0
|
||||
toolButton * hq_btn = new toolButton( embed::getIconPixmap( "hq_mode" ),
|
||||
@@ -145,6 +146,9 @@ songEditor::songEditor( song * _song, songEditor * & _engine_ptr ) :
|
||||
|
||||
engine::mainWindow()->addSpacingToToolBar( 10 );
|
||||
|
||||
engine::mainWindow()->addWidgetToToolBar( new TimeDisplayWidget, 1, tempoSpinBoxCol );
|
||||
|
||||
engine::mainWindow()->addSpacingToToolBar( 10 );
|
||||
|
||||
m_timeSigDisplay = new MeterDialog( this, TRUE );
|
||||
m_timeSigDisplay->setModel( &m_s->m_timeSigModel );
|
||||
|
||||
@@ -175,29 +175,36 @@ void EffectRackView::update()
|
||||
Qt::QueuedConnection );
|
||||
view->show();
|
||||
m_effectViews.append( view );
|
||||
view_map[i] = true;
|
||||
if( i < view_map.size() )
|
||||
{
|
||||
view_map[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
view_map.append( true );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int i = m_lastY = 0;
|
||||
int i = m_lastY = 0, nView = 0;
|
||||
for( QVector<EffectView *>::Iterator it = m_effectViews.begin();
|
||||
it != m_effectViews.end(); )
|
||||
it != m_effectViews.end(); i++ )
|
||||
{
|
||||
if( i < view_map.size() && i < m_effectViews.size() &&
|
||||
view_map[i] == false )
|
||||
if( i < view_map.size() && view_map[i] == false )
|
||||
{
|
||||
delete m_effectViews[i];
|
||||
delete m_effectViews[nView];
|
||||
it = m_effectViews.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
( *it )->move( 0, m_lastY );
|
||||
m_lastY += ( *it )->height();
|
||||
++nView;
|
||||
++it;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
w->setFixedSize( 210, m_lastY );
|
||||
|
||||
QWidget::update();
|
||||
@@ -242,7 +249,7 @@ void EffectRackView::addEffect()
|
||||
|
||||
void EffectRackView::modelChanged()
|
||||
{
|
||||
clearViews();
|
||||
//clearViews();
|
||||
m_effectsGroupBox->setModel( &fxChain()->m_enabledModel );
|
||||
connect( fxChain(), SIGNAL( aboutToClear() ),
|
||||
this, SLOT( clearViews() ) );
|
||||
|
||||
@@ -85,6 +85,8 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
|
||||
"while deciding when to stop processing signals." ) );
|
||||
|
||||
|
||||
setModel( _model );
|
||||
|
||||
if( effect()->controls()->controlCount() > 0 )
|
||||
{
|
||||
QPushButton * ctls_btn = new QPushButton( tr( "Controls" ),
|
||||
@@ -94,6 +96,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
|
||||
ctls_btn->setGeometry( 140, 14, 50, 20 );
|
||||
connect( ctls_btn, SIGNAL( clicked() ),
|
||||
this, SLOT( editControls() ) );
|
||||
|
||||
m_controlView = effect()->controls()->createView();
|
||||
if( m_controlView )
|
||||
{
|
||||
@@ -141,7 +144,8 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
|
||||
"Right clicking will bring up a context menu where you can change the order "
|
||||
"in which the effects are processed or delete an effect altogether." ) );
|
||||
|
||||
setModel( _model );
|
||||
//move above vst effect view creation
|
||||
//setModel( _model );
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +153,15 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
|
||||
|
||||
EffectView::~EffectView()
|
||||
{
|
||||
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
|
||||
delete m_subWindow;
|
||||
#else
|
||||
// otherwise on win32 build VST GUI can get lost
|
||||
m_subWindow->hide();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +171,7 @@ void EffectView::editControls()
|
||||
{
|
||||
if( m_subWindow )
|
||||
{
|
||||
if( !effect()->controls()->isViewVisible() )
|
||||
if( !m_subWindow->isVisible() )
|
||||
{
|
||||
m_subWindow->show();
|
||||
m_subWindow->raise();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* EnvelopeAndLfoView.cpp - widget which is m_used by envelope/lfo/filter-
|
||||
* tab of instrument track window
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -341,25 +341,25 @@ void EnvelopeAndLfoView::mousePressEvent( QMouseEvent * _me )
|
||||
if( QRect( ENV_GRAPH_X, ENV_GRAPH_Y, s_envGraph->width(),
|
||||
s_envGraph->height() ).contains( _me->pos() ) == true )
|
||||
{
|
||||
if( m_amountKnob->value<float>() < 1.0f )
|
||||
if( m_params->m_amountModel.value() < 1.0f )
|
||||
{
|
||||
m_amountKnob->setValue( 1.0f );
|
||||
m_params->m_amountModel.setValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_amountKnob->setValue( 0.0f );
|
||||
m_params->m_amountModel.setValue( 0.0f );
|
||||
}
|
||||
}
|
||||
else if( QRect( LFO_GRAPH_X, LFO_GRAPH_Y, s_lfoGraph->width(),
|
||||
s_lfoGraph->height() ).contains( _me->pos() ) == true )
|
||||
{
|
||||
if( m_lfoAmountKnob->value<float>() < 1.0f )
|
||||
if( m_params->m_lfoAmountModel.value() < 1.0f )
|
||||
{
|
||||
m_lfoAmountKnob->setValue( 1.0f );
|
||||
m_params->m_lfoAmountModel.setValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lfoAmountKnob->setValue( 0.0f );
|
||||
m_params->m_lfoAmountModel.setValue( 0.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget * _parent ) :
|
||||
m_midiInputGroupBox = new groupBox( tr( "ENABLE MIDI INPUT" ), this );
|
||||
m_midiInputGroupBox->setGeometry( 4, 5, 242, 80 );
|
||||
|
||||
m_inputChannelSpinBox = new lcdSpinBox( 3, m_midiInputGroupBox );
|
||||
m_inputChannelSpinBox->addTextForValue( 0, "---" );
|
||||
m_inputChannelSpinBox = new lcdSpinBox( 2, m_midiInputGroupBox );
|
||||
m_inputChannelSpinBox->addTextForValue( 0, "--" );
|
||||
m_inputChannelSpinBox->setLabel( tr( "CHANNEL" ) );
|
||||
m_inputChannelSpinBox->move( 16, 32 );
|
||||
m_inputChannelSpinBox->setEnabled( false );
|
||||
@@ -69,7 +69,7 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget * _parent ) :
|
||||
m_midiOutputGroupBox = new groupBox( tr( "ENABLE MIDI OUTPUT" ), this );
|
||||
m_midiOutputGroupBox->setGeometry( 4, 90, 242, 80 );
|
||||
|
||||
m_outputChannelSpinBox = new lcdSpinBox( 3, m_midiOutputGroupBox );
|
||||
m_outputChannelSpinBox = new lcdSpinBox( 2, m_midiOutputGroupBox );
|
||||
m_outputChannelSpinBox->setLabel( tr( "CHANNEL" ) );
|
||||
m_outputChannelSpinBox->move( 16, 32 );
|
||||
m_outputChannelSpinBox->setEnabled( false );
|
||||
@@ -85,26 +85,34 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget * _parent ) :
|
||||
m_outputProgramSpinBox->move( 112, 32 );
|
||||
m_outputProgramSpinBox->setEnabled( false );
|
||||
|
||||
m_fixedOutputNoteSpinBox = new lcdSpinBox( 3, m_midiOutputGroupBox );
|
||||
m_fixedOutputNoteSpinBox->addTextForValue( -1, "---" );
|
||||
m_fixedOutputNoteSpinBox->setLabel( tr( "NOTE" ) );
|
||||
m_fixedOutputNoteSpinBox->move( 160, 32 );
|
||||
m_fixedOutputNoteSpinBox->setEnabled( false );
|
||||
|
||||
|
||||
connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ),
|
||||
m_outputChannelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ),
|
||||
m_fixedOutputVelocitySpinBox, SLOT( setEnabled( bool ) ) );
|
||||
connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ),
|
||||
m_outputProgramSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
connect( m_midiOutputGroupBox->ledButton(), SIGNAL( toggled( bool ) ),
|
||||
m_fixedOutputNoteSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
if( !engine::getMixer()->midiClient()->isRaw() )
|
||||
{
|
||||
m_rpBtn = new QToolButton( m_midiInputGroupBox );
|
||||
m_rpBtn->setText( tr( "MIDI devices to receive MIDI events from" ) );
|
||||
m_rpBtn->setIcon( embed::getIconPixmap( "piano" ) );
|
||||
m_rpBtn->setGeometry( 186, 24, 32, 32 );
|
||||
m_rpBtn->setGeometry( 208, 24, 32, 32 );
|
||||
m_rpBtn->setPopupMode( QToolButton::InstantPopup );
|
||||
|
||||
m_wpBtn = new QToolButton( m_midiOutputGroupBox );
|
||||
m_wpBtn->setText( tr( "MIDI devices to send MIDI events to" ) );
|
||||
m_wpBtn->setIcon( embed::getIconPixmap( "piano" ) );
|
||||
m_wpBtn->setGeometry( 186, 24, 32, 32 );
|
||||
m_wpBtn->setGeometry( 208, 24, 32, 32 );
|
||||
m_wpBtn->setPopupMode( QToolButton::InstantPopup );
|
||||
}
|
||||
}
|
||||
@@ -131,6 +139,8 @@ void InstrumentMidiIOView::modelChanged()
|
||||
m_outputChannelSpinBox->setModel( &mp->m_outputChannelModel );
|
||||
m_fixedOutputVelocitySpinBox->setModel(
|
||||
&mp->m_fixedOutputVelocityModel );
|
||||
m_fixedOutputNoteSpinBox->setModel(
|
||||
&mp->m_fixedOutputNoteModel );
|
||||
m_outputProgramSpinBox->setModel( &mp->m_outputProgramModel );
|
||||
|
||||
if( m_rpBtn )
|
||||
|
||||
246
src/gui/widgets/LcdWidget.cpp
Normal file
246
src/gui/widgets/LcdWidget.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* LcdWidget.cpp - a widget for displaying numbers in LCD style
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008 Paul Giblock <pgllama/at/gmail.com>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* 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 <QtGui/QApplication>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QFontMetrics>
|
||||
#include <QtGui/QStyleOptionFrameV2>
|
||||
|
||||
#include "LcdWidget.h"
|
||||
#include "engine.h"
|
||||
#include "embed.h"
|
||||
#include "gui_templates.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
|
||||
|
||||
LcdWidget::LcdWidget( int numDigits, QWidget* parent, const QString& name ) :
|
||||
QWidget( parent ),
|
||||
m_label(),
|
||||
m_numDigits( numDigits )
|
||||
{
|
||||
setEnabled( true );
|
||||
|
||||
setWindowTitle( name );
|
||||
|
||||
m_lcdPixmap = new QPixmap( embed::getIconPixmap( "lcd_19green" ) );
|
||||
|
||||
m_cellWidth = m_lcdPixmap->size().width() / LcdWidget::charsPerPixmap;
|
||||
m_cellHeight = m_lcdPixmap->size().height() / 2;
|
||||
|
||||
m_marginWidth = m_cellWidth / 2;
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LcdWidget::LcdWidget( int numDigits, const QString& style, QWidget* parent, const QString& name ) :
|
||||
QWidget( parent ),
|
||||
m_label(),
|
||||
m_numDigits( numDigits )
|
||||
{
|
||||
setEnabled( true );
|
||||
|
||||
setWindowTitle( name );
|
||||
|
||||
// We should make a factory for these or something.
|
||||
m_lcdPixmap = new QPixmap( embed::getIconPixmap( QString( "lcd_" + style ).toUtf8().constData() ) );
|
||||
|
||||
m_cellWidth = m_lcdPixmap->size().width() / LcdWidget::charsPerPixmap;
|
||||
m_cellHeight = m_lcdPixmap->size().height() / 2;
|
||||
|
||||
m_marginWidth = m_cellWidth / 2;
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LcdWidget::~LcdWidget()
|
||||
{
|
||||
delete m_lcdPixmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void LcdWidget::setValue( int value )
|
||||
{
|
||||
QString s = m_textForValue[value];
|
||||
if( s.isEmpty() )
|
||||
{
|
||||
s = QString::number( value );
|
||||
// TODO: if pad == true
|
||||
/*
|
||||
while( (int) s.length() < m_numDigits )
|
||||
{
|
||||
s = "0" + s;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
m_display = s;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void LcdWidget::paintEvent( QPaintEvent* )
|
||||
{
|
||||
QPainter p( this );
|
||||
|
||||
QSize cellSize( m_cellWidth, m_cellHeight );
|
||||
|
||||
QRect cellRect( 0, 0, m_cellWidth, m_cellHeight );
|
||||
|
||||
int margin = 1; // QStyle::PM_DefaultFrameWidth;
|
||||
//int lcdWidth = m_cellWidth * m_numDigits + (margin*m_marginWidth)*2;
|
||||
|
||||
// p.translate( width() / 2 - lcdWidth / 2, 0 );
|
||||
p.save();
|
||||
|
||||
p.translate( margin, margin );
|
||||
|
||||
// Left Margin
|
||||
p.drawPixmap( cellRect, *m_lcdPixmap,
|
||||
QRect( QPoint( charsPerPixmap*m_cellWidth,
|
||||
isEnabled()?0:m_cellHeight ),
|
||||
cellSize ) );
|
||||
|
||||
p.translate( m_marginWidth, 0 );
|
||||
|
||||
// Padding
|
||||
for( int i=0; i < m_numDigits - m_display.length(); i++ )
|
||||
{
|
||||
p.drawPixmap( cellRect, *m_lcdPixmap,
|
||||
QRect( QPoint( 10 * m_cellWidth, isEnabled()?0:m_cellHeight) , cellSize ) );
|
||||
p.translate( m_cellWidth, 0 );
|
||||
}
|
||||
|
||||
// Digits
|
||||
for( int i=0; i < m_display.length(); i++ )
|
||||
{
|
||||
int val = m_display[i].digitValue();
|
||||
if( val < 0 )
|
||||
{
|
||||
if( m_display[i] == '-' )
|
||||
val = 11;
|
||||
else
|
||||
val = 10;
|
||||
}
|
||||
p.drawPixmap( cellRect, *m_lcdPixmap,
|
||||
QRect( QPoint( val*m_cellWidth,
|
||||
isEnabled()?0:m_cellHeight ),
|
||||
cellSize ) );
|
||||
p.translate( m_cellWidth, 0 );
|
||||
}
|
||||
|
||||
// Right Margin
|
||||
p.drawPixmap( QRect( 0, 0, m_marginWidth-1, m_cellHeight ), *m_lcdPixmap,
|
||||
QRect( charsPerPixmap*m_cellWidth, isEnabled()?0:m_cellHeight,
|
||||
m_cellWidth / 2, m_cellHeight ) );
|
||||
|
||||
|
||||
p.restore();
|
||||
|
||||
// Border
|
||||
QStyleOptionFrame opt;
|
||||
opt.initFrom( this );
|
||||
opt.state = QStyle::State_Sunken;
|
||||
opt.rect = QRect( 0, 0, m_cellWidth * m_numDigits + (margin+m_marginWidth)*2 - 1,
|
||||
m_cellHeight + (margin*2) );
|
||||
|
||||
style()->drawPrimitive( QStyle::PE_Frame, &opt, &p, this );
|
||||
|
||||
p.resetTransform();
|
||||
|
||||
// Label
|
||||
if( !m_label.isEmpty() )
|
||||
{
|
||||
p.setFont( pointSize<6>( p.font() ) );
|
||||
p.setPen( QColor( 64, 64, 64 ) );
|
||||
p.drawText( width() / 2 -
|
||||
p.fontMetrics().width( m_label ) / 2 + 1,
|
||||
height(), m_label );
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
p.drawText( width() / 2 -
|
||||
p.fontMetrics().width( m_label ) / 2,
|
||||
height() - 1, m_label );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void LcdWidget::setLabel( const QString & _txt )
|
||||
{
|
||||
m_label = _txt;
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void LcdWidget::setMarginWidth( int _width )
|
||||
{
|
||||
m_marginWidth = _width;
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void LcdWidget::updateSize()
|
||||
{
|
||||
int margin = 1;
|
||||
if (m_label.isEmpty()) {
|
||||
setFixedSize( m_cellWidth * m_numDigits + 2*(margin+m_marginWidth),
|
||||
m_cellHeight + (2*margin) );
|
||||
}
|
||||
else {
|
||||
setFixedSize( qMax<int>(
|
||||
m_cellWidth * m_numDigits + 2*(margin+m_marginWidth),
|
||||
QFontMetrics( pointSize<6>( font() ) ).width( m_label ) ),
|
||||
m_cellHeight + (2*margin) + 8 );
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_LcdWidget.cxx"
|
||||
|
||||
139
src/gui/widgets/TimeDisplayWidget.cpp
Normal file
139
src/gui/widgets/TimeDisplayWidget.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* TimeDisplayWidget.cpp - widget for displaying current playback time
|
||||
*
|
||||
* Copyright (c) 2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* 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 <QtGui/QMouseEvent>
|
||||
|
||||
#include "TimeDisplayWidget.h"
|
||||
#include "MainWindow.h"
|
||||
#include "engine.h"
|
||||
#include "tooltip.h"
|
||||
#include "song.h"
|
||||
|
||||
|
||||
|
||||
TimeDisplayWidget::TimeDisplayWidget() :
|
||||
QWidget(),
|
||||
m_displayMode( MinutesSeconds ),
|
||||
m_spinBoxesLayout( this ),
|
||||
m_majorLCD( 2, this ),
|
||||
m_minorLCD( 2, this ),
|
||||
m_milliSecondsLCD( 3, this )
|
||||
{
|
||||
m_spinBoxesLayout.setSpacing( 0 );
|
||||
m_spinBoxesLayout.setMargin( 0 );
|
||||
m_spinBoxesLayout.addWidget( &m_majorLCD );
|
||||
m_spinBoxesLayout.addWidget( &m_minorLCD );
|
||||
m_spinBoxesLayout.addWidget( &m_milliSecondsLCD );
|
||||
|
||||
setMaximumHeight( 32 );
|
||||
|
||||
toolTip::add( this, tr( "click to change time units" ) );
|
||||
|
||||
// update labels of LCD spinboxes
|
||||
setDisplayMode( m_displayMode );
|
||||
|
||||
connect( engine::mainWindow(), SIGNAL( periodicUpdate() ),
|
||||
this, SLOT( updateTime() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TimeDisplayWidget::~TimeDisplayWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void TimeDisplayWidget::setDisplayMode( DisplayMode displayMode )
|
||||
{
|
||||
m_displayMode = displayMode;
|
||||
|
||||
m_milliSecondsLCD.setLabel( "MSEC" );
|
||||
|
||||
switch( m_displayMode )
|
||||
{
|
||||
case MinutesSeconds:
|
||||
m_majorLCD.setLabel( "MIN" );
|
||||
m_minorLCD.setLabel( "SEC" );
|
||||
break;
|
||||
|
||||
case BarsTicks:
|
||||
m_majorLCD.setLabel( "BAR" );
|
||||
m_minorLCD.setLabel( "TICK" );
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TimeDisplayWidget::updateTime()
|
||||
{
|
||||
song* s = engine::getSong();
|
||||
|
||||
switch( m_displayMode )
|
||||
{
|
||||
case MinutesSeconds:
|
||||
m_majorLCD.setValue( s->getMilliseconds() / 60000 );
|
||||
m_minorLCD.setValue( ( s->getMilliseconds() / 1000 ) % 60 );
|
||||
break;
|
||||
|
||||
case BarsTicks:
|
||||
m_majorLCD.setValue( s->getTacts() );
|
||||
m_minorLCD.setValue( ( s->getTicks() % s->ticksPerTact() ) / 3 );
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
m_milliSecondsLCD.setValue( s->getMilliseconds() % 1000 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TimeDisplayWidget::mousePressEvent( QMouseEvent* mouseEvent )
|
||||
{
|
||||
if( mouseEvent->button() == Qt::LeftButton )
|
||||
{
|
||||
if( m_displayMode == MinutesSeconds )
|
||||
{
|
||||
setDisplayMode( BarsTicks );
|
||||
}
|
||||
else
|
||||
{
|
||||
setDisplayMode( MinutesSeconds );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_TimeDisplayWidget.cxx"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* fader.cpp - fader-widget used in mixer - partly taken from Hydrogen
|
||||
*
|
||||
* Copyright (c) 2008-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -45,6 +45,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <QtGui/QInputDialog>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPaintEvent>
|
||||
#include <QtGui/QPainter>
|
||||
@@ -73,7 +74,9 @@ fader::fader( FloatModel * _model, const QString & _name, QWidget * _parent ) :
|
||||
m_fMaxPeak( 1.1 ),
|
||||
m_back( embed::getIconPixmap( "fader_background" ) ),
|
||||
m_leds( embed::getIconPixmap( "fader_leds" ) ),
|
||||
m_knob( embed::getIconPixmap( "fader_knob" ) )
|
||||
m_knob( embed::getIconPixmap( "fader_knob" ) ),
|
||||
m_moveStartPoint( -1 ),
|
||||
m_startValue( 0 )
|
||||
{
|
||||
if( s_textFloat == NULL )
|
||||
{
|
||||
@@ -107,35 +110,67 @@ void fader::contextMenuEvent( QContextMenuEvent * _ev )
|
||||
|
||||
|
||||
|
||||
void fader::mouseMoveEvent( QMouseEvent *ev )
|
||||
void fader::mouseMoveEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
float fVal = (float)( height() - ev->y() ) / (float)height();
|
||||
fVal = fVal * ( m_model->maxValue() - m_model->minValue() );
|
||||
if( m_moveStartPoint >= 0 )
|
||||
{
|
||||
int dy = m_moveStartPoint - mouseEvent->globalY();
|
||||
|
||||
fVal = fVal + m_model->minValue();
|
||||
float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - m_knob.height() );
|
||||
|
||||
m_model->setValue( fVal );
|
||||
model()->setValue( m_startValue + delta );
|
||||
|
||||
updateTextFloat();
|
||||
updateTextFloat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void fader::mousePressEvent( QMouseEvent * _me )
|
||||
void fader::mousePressEvent( QMouseEvent* mouseEvent )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton &&
|
||||
! ( _me->modifiers() & Qt::ControlModifier ) )
|
||||
if( mouseEvent->button() == Qt::LeftButton &&
|
||||
! ( mouseEvent->modifiers() & Qt::ControlModifier ) )
|
||||
{
|
||||
updateTextFloat();
|
||||
s_textFloat->show();
|
||||
if( mouseEvent->y() >= knobPosY() - m_knob.height() && mouseEvent->y() < knobPosY() )
|
||||
{
|
||||
updateTextFloat();
|
||||
s_textFloat->show();
|
||||
|
||||
mouseMoveEvent( _me );
|
||||
_me->accept();
|
||||
m_moveStartPoint = mouseEvent->globalY();
|
||||
m_startValue = model()->value();
|
||||
|
||||
mouseEvent->accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moveStartPoint = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AutomatableModelView::mousePressEvent( _me );
|
||||
AutomatableModelView::mousePressEvent( mouseEvent );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void fader::mouseDoubleClickEvent( QMouseEvent* mouseEvent )
|
||||
{
|
||||
bool ok;
|
||||
|
||||
// TODO: dbV handling
|
||||
int newValue = QInputDialog::getInteger( this, windowTitle(),
|
||||
tr( "Please enter a new value between %1 and %2:" ).
|
||||
arg( model()->minValue()*100 ).
|
||||
arg( model()->maxValue()*100 ),
|
||||
model()->value()*100,
|
||||
model()->minValue()*100,
|
||||
model()->maxValue()*100, 1, &ok );
|
||||
|
||||
if( ok )
|
||||
{
|
||||
model()->setValue( newValue / 100.0f );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,11 +188,11 @@ void fader::wheelEvent ( QWheelEvent *ev )
|
||||
|
||||
if ( ev->delta() > 0 )
|
||||
{
|
||||
m_model->incValue( 5 );
|
||||
m_model->incValue( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->incValue( -5 );
|
||||
m_model->incValue( -1 );
|
||||
}
|
||||
updateTextFloat();
|
||||
s_textFloat->setVisibilityTimeOut( 1000 );
|
||||
@@ -225,7 +260,7 @@ void fader::updateTextFloat()
|
||||
{
|
||||
s_textFloat->setText( QString("Volume: %1 %").arg( m_model->value() * 100 ) );
|
||||
}
|
||||
s_textFloat->moveGlobal( this, QPoint( width() - m_knob.width() - 5, knob_y() - 46 ) );
|
||||
s_textFloat->moveGlobal( this, QPoint( width() - m_knob.width() - 5, knobPosY() - 46 ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -268,18 +303,7 @@ void fader::paintEvent( QPaintEvent * ev)
|
||||
}
|
||||
|
||||
// knob
|
||||
static const uint knob_height = 29;
|
||||
static const uint knob_width = 15;
|
||||
|
||||
float fRange = m_model->maxValue() - m_model->minValue();
|
||||
|
||||
float realVal = m_model->value() - m_model->minValue();
|
||||
|
||||
// uint knob_y = (uint)( 116.0 - ( 86.0 * ( m_model->value() / fRange ) ) );
|
||||
uint knob_y = (uint)( 116.0 - ( 86.0 * ( realVal / fRange ) ) );
|
||||
|
||||
|
||||
painter.drawPixmap( QRect( 4, knob_y - knob_height, knob_width, knob_height), m_knob, QRect( 0, 0, knob_width, knob_height ) );
|
||||
painter.drawPixmap( 4, knobPosY() - m_knob.height(), m_knob );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* lcd_spinbox.cpp - class lcdSpinBox, an improved QLCDNumber
|
||||
*
|
||||
* Copyright (c) 2005-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008 Paul Giblock <pgllama/at/gmail.com>
|
||||
*
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -23,8 +23,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <QtGui/QApplication>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QMouseEvent>
|
||||
@@ -42,228 +40,43 @@
|
||||
|
||||
|
||||
|
||||
lcdSpinBox::lcdSpinBox( int _num_digits, QWidget * _parent,
|
||||
const QString & _name ) :
|
||||
QWidget( _parent ),
|
||||
IntModelView( new IntModel( 0, 0, 0, NULL, _name, true ), this ),
|
||||
m_label(),
|
||||
m_numDigits( _num_digits ),
|
||||
lcdSpinBox::lcdSpinBox( int numDigits, QWidget* parent, const QString& name ) :
|
||||
LcdWidget( numDigits, parent, name ),
|
||||
IntModelView( new IntModel( 0, 0, 0, NULL, name, true ), this ),
|
||||
m_origMousePos()
|
||||
{
|
||||
setEnabled( true );
|
||||
|
||||
setWindowTitle( _name );
|
||||
|
||||
m_lcdPixmap = new QPixmap( embed::getIconPixmap( "lcd_19green" ) );
|
||||
|
||||
m_cellWidth = m_lcdPixmap->size().width() / lcdSpinBox::charsPerPixmap;
|
||||
m_cellHeight = m_lcdPixmap->size().height() / 2;
|
||||
|
||||
m_marginWidth = m_cellWidth / 2;
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
lcdSpinBox::lcdSpinBox( int _num_digits, const QString & _lcd_style,
|
||||
QWidget * _parent, const QString & _name ) :
|
||||
QWidget( _parent ),
|
||||
IntModelView( new IntModel( 0, 0, 0, NULL, _name, true ), this ),
|
||||
m_label(),
|
||||
m_numDigits( _num_digits ),
|
||||
lcdSpinBox::lcdSpinBox( int numDigits, const QString& style, QWidget* parent, const QString& name ) :
|
||||
LcdWidget( numDigits, parent, name ),
|
||||
IntModelView( new IntModel( 0, 0, 0, NULL, name, true ), this ),
|
||||
m_origMousePos()
|
||||
{
|
||||
setEnabled( true );
|
||||
|
||||
setWindowTitle( _name );
|
||||
|
||||
// We should make a factory for these or something.
|
||||
m_lcdPixmap = new QPixmap( embed::getIconPixmap( QString( "lcd_" +
|
||||
_lcd_style ).toUtf8().constData() ) );
|
||||
|
||||
m_cellWidth = m_lcdPixmap->size().width() / lcdSpinBox::charsPerPixmap;
|
||||
m_cellHeight = m_lcdPixmap->size().height() / 2;
|
||||
|
||||
m_marginWidth = m_cellWidth / 2;
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
lcdSpinBox::~lcdSpinBox()
|
||||
{
|
||||
delete m_lcdPixmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::paintEvent( QPaintEvent * _me )
|
||||
{
|
||||
QRect ur = _me->rect();
|
||||
|
||||
QPainter p( this );
|
||||
|
||||
QSize cellSize( m_cellWidth, m_cellHeight );
|
||||
|
||||
QRect cellRect( 0, 0, m_cellWidth, m_cellHeight );
|
||||
|
||||
int margin = 1; // QStyle::PM_DefaultFrameWidth;
|
||||
//int lcdWidth = m_cellWidth * m_numDigits + (margin*m_marginWidth)*2;
|
||||
|
||||
// p.translate( width() / 2 - lcdWidth / 2, 0 );
|
||||
p.save();
|
||||
|
||||
p.translate( margin, margin );
|
||||
|
||||
// Left Margin
|
||||
p.drawPixmap( cellRect, *m_lcdPixmap,
|
||||
QRect( QPoint( charsPerPixmap*m_cellWidth,
|
||||
isEnabled()?0:m_cellHeight ),
|
||||
cellSize ) );
|
||||
|
||||
p.translate( m_marginWidth, 0 );
|
||||
|
||||
// Padding
|
||||
for( int i=0; i < m_numDigits - m_display.length(); i++ )
|
||||
{
|
||||
p.drawPixmap( cellRect, *m_lcdPixmap,
|
||||
QRect( QPoint( 10 * m_cellWidth, isEnabled()?0:m_cellHeight) , cellSize ) );
|
||||
p.translate( m_cellWidth, 0 );
|
||||
}
|
||||
|
||||
// Digits
|
||||
for( int i=0; i < m_display.length(); i++ )
|
||||
{
|
||||
int val = m_display[i].digitValue();
|
||||
if( val < 0 )
|
||||
{
|
||||
if( m_display[i] == '-' )
|
||||
val = 11;
|
||||
else
|
||||
val = 10;
|
||||
}
|
||||
p.drawPixmap( cellRect, *m_lcdPixmap,
|
||||
QRect( QPoint( val*m_cellWidth,
|
||||
isEnabled()?0:m_cellHeight ),
|
||||
cellSize ) );
|
||||
p.translate( m_cellWidth, 0 );
|
||||
}
|
||||
|
||||
// Right Margin
|
||||
p.drawPixmap( QRect( 0, 0, m_marginWidth-1, m_cellHeight ), *m_lcdPixmap,
|
||||
QRect( charsPerPixmap*m_cellWidth, isEnabled()?0:m_cellHeight,
|
||||
m_cellWidth / 2, m_cellHeight ) );
|
||||
|
||||
|
||||
p.restore();
|
||||
|
||||
// Border
|
||||
QStyleOptionFrame opt;
|
||||
opt.initFrom( this );
|
||||
opt.state = QStyle::State_Sunken;
|
||||
opt.rect = QRect( 0, 0, m_cellWidth * m_numDigits + (margin+m_marginWidth)*2 - 1,
|
||||
m_cellHeight + (margin*2) );
|
||||
|
||||
style()->drawPrimitive( QStyle::PE_Frame, &opt, &p, this );
|
||||
|
||||
p.resetTransform();
|
||||
|
||||
// Label
|
||||
if( !m_label.isEmpty() )
|
||||
{
|
||||
p.setFont( pointSize<6>( p.font() ) );
|
||||
p.setPen( QColor( 64, 64, 64 ) );
|
||||
p.drawText( width() / 2 -
|
||||
p.fontMetrics().width( m_label ) / 2 + 1,
|
||||
height(), m_label );
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
p.drawText( width() / 2 -
|
||||
p.fontMetrics().width( m_label ) / 2,
|
||||
height() - 1, m_label );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::update()
|
||||
{
|
||||
QString s = m_textForValue[model()->value()];
|
||||
if( s == "" )
|
||||
{
|
||||
s = QString::number( model()->value() );
|
||||
// TODO: if pad == true
|
||||
/*
|
||||
while( (int) s.length() < m_numDigits )
|
||||
{
|
||||
s = "0" + s;
|
||||
}
|
||||
*/
|
||||
}
|
||||
m_display = s;
|
||||
setValue( model()->value() );
|
||||
|
||||
QWidget::update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::setLabel( const QString & _txt )
|
||||
void lcdSpinBox::contextMenuEvent( QContextMenuEvent* event )
|
||||
{
|
||||
m_label = _txt;
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::setEnabled( bool _on )
|
||||
{
|
||||
QWidget::setEnabled( _on );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::setMarginWidth( int _width )
|
||||
{
|
||||
m_marginWidth = _width;
|
||||
|
||||
updateSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::updateSize()
|
||||
{
|
||||
int margin = 1;
|
||||
if (m_label.isEmpty()) {
|
||||
setFixedSize( m_cellWidth * m_numDigits + 2*(margin+m_marginWidth),
|
||||
m_cellHeight + (2*margin) );
|
||||
}
|
||||
else {
|
||||
setFixedSize( qMax<int>(
|
||||
m_cellWidth * m_numDigits + 2*(margin+m_marginWidth),
|
||||
QFontMetrics( pointSize<6>( font() ) ).width( m_label ) ),
|
||||
m_cellHeight + (2*margin) + 10 );
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::contextMenuEvent( QContextMenuEvent * _me )
|
||||
{
|
||||
m_origMousePos = _me->globalPos();
|
||||
m_origMousePos = event->globalPos();
|
||||
|
||||
// for the case, the user clicked right while pressing left mouse-
|
||||
// button, the context-menu appears while mouse-cursor is still hidden
|
||||
@@ -279,30 +92,30 @@ void lcdSpinBox::contextMenuEvent( QContextMenuEvent * _me )
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::mousePressEvent( QMouseEvent * _me )
|
||||
void lcdSpinBox::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton &&
|
||||
! ( _me->modifiers() & Qt::ControlModifier ) &&
|
||||
_me->y() < m_cellHeight + 2 )
|
||||
if( event->button() == Qt::LeftButton &&
|
||||
! ( event->modifiers() & Qt::ControlModifier ) &&
|
||||
event->y() < cellHeight() + 2 )
|
||||
{
|
||||
m_origMousePos = _me->globalPos();
|
||||
m_origMousePos = event->globalPos();
|
||||
QApplication::setOverrideCursor( Qt::BlankCursor );
|
||||
model()->prepareJournalEntryFromOldVal();
|
||||
}
|
||||
else
|
||||
{
|
||||
IntModelView::mousePressEvent( _me );
|
||||
IntModelView::mousePressEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::mouseMoveEvent( QMouseEvent * _me )
|
||||
void lcdSpinBox::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
if( _me->buttons() & Qt::LeftButton )
|
||||
if( event->buttons() & Qt::LeftButton )
|
||||
{
|
||||
int dy = _me->globalY() - m_origMousePos.y();
|
||||
int dy = event->globalY() - m_origMousePos.y();
|
||||
if( dy > 1 || dy < -1 )
|
||||
{
|
||||
model()->setInitValue( model()->value() -
|
||||
@@ -316,7 +129,7 @@ void lcdSpinBox::mouseMoveEvent( QMouseEvent * _me )
|
||||
|
||||
|
||||
|
||||
void lcdSpinBox::mouseReleaseEvent( QMouseEvent * _me )
|
||||
void lcdSpinBox::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
model()->addJournalEntryFromOldToCurVal();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* pixmap_button.cpp - implementation of pixmap-button (often used as "themed"
|
||||
* checkboxes/radiobuttons etc)
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -57,7 +57,7 @@ void pixmapButton::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QPainter p( this );
|
||||
|
||||
if( model()->value() || m_pressed )
|
||||
if( ( model() != NULL && model()->value() ) || m_pressed )
|
||||
{
|
||||
if( !m_activePixmap.isNull() )
|
||||
{
|
||||
|
||||
@@ -131,7 +131,7 @@ AutomationTrackView::AutomationTrackView( AutomationTrack * _at,
|
||||
trackContainerView * _tcv ) :
|
||||
trackView( _at, _tcv )
|
||||
{
|
||||
setFixedHeight( 32 );
|
||||
setFixedHeight( 32 );
|
||||
trackLabelButton * tlb = new trackLabelButton( this,
|
||||
getTrackSettingsWidget() );
|
||||
tlb->setIcon( embed::getIconPixmap( "automation_track" ) );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* InstrumentTrack.cpp - implementation of instrument-track-class
|
||||
* (window + data-structures)
|
||||
*
|
||||
* Copyright (c) 2004-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -98,6 +98,7 @@ InstrumentTrack::InstrumentTrack( trackContainer * _tc ) :
|
||||
m_midiPort( tr( "unnamed_track" ), engine::getMixer()->midiClient(),
|
||||
this, this ),
|
||||
m_notes(),
|
||||
m_sustainPedalPressed( false ),
|
||||
m_baseNoteModel( 0, 0, KeysPerOctave * NumOctaves - 1, this,
|
||||
tr( "Base note" ) ),
|
||||
m_volumeModel( DefaultVolume, MinVolume, MaxVolume, 0.1f, this,
|
||||
@@ -220,6 +221,19 @@ void InstrumentTrack::processInEvent( const midiEvent & _me,
|
||||
const midiTime & _time )
|
||||
{
|
||||
engine::getMixer()->lock();
|
||||
|
||||
// in the special case this event comes from a MIDI port, the instrument
|
||||
// is MIDI based (VST plugin, Sf2Player etc.) and the user did not set
|
||||
// a dedicated MIDI output channel, directly pass the MIDI event to the
|
||||
// instrument plugin
|
||||
if( _me.isFromMidiPort() && m_instrument->isMidiBased()/* &&
|
||||
midiPort()->realOutputChannel() < 0 */ )
|
||||
{
|
||||
m_instrument->handleMidiEvent( _me, _time );
|
||||
engine::getMixer()->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
switch( _me.m_type )
|
||||
{
|
||||
// we don't send MidiNoteOn, MidiNoteOff and MidiKeyPressure
|
||||
@@ -303,6 +317,29 @@ void InstrumentTrack::processInEvent( const midiEvent & _me,
|
||||
break;
|
||||
|
||||
case MidiControlChange:
|
||||
if( _me.controllerNumber() == MidiControllerSustain )
|
||||
{
|
||||
if( _me.controllerValue() > MidiMaxControllerValue/2 )
|
||||
{
|
||||
m_sustainPedalPressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sustainPedalPressed = false;
|
||||
}
|
||||
}
|
||||
if( _me.controllerNumber() == MidiControllerAllSoundOff ||
|
||||
_me.controllerNumber() == MidiControllerAllNotesOff ||
|
||||
_me.controllerNumber() == MidiControllerOmniOn ||
|
||||
_me.controllerNumber() == MidiControllerOmniOff ||
|
||||
_me.controllerNumber() == MidiControllerMonoOn ||
|
||||
_me.controllerNumber() == MidiControllerPolyOn )
|
||||
{
|
||||
silenceAllNotes();
|
||||
}
|
||||
m_instrument->handleMidiEvent( _me, _time );
|
||||
break;
|
||||
|
||||
case MidiProgramChange:
|
||||
m_instrument->handleMidiEvent( _me, _time );
|
||||
break;
|
||||
@@ -1023,9 +1060,9 @@ void InstrumentTrackView::freeInstrumentTrackWindow()
|
||||
model()->setHook( NULL );
|
||||
m_window->setInstrumentTrackView( NULL );
|
||||
m_window->parentWidget()->hide();
|
||||
m_window->setModel(
|
||||
engine::dummyTrackContainer()->
|
||||
dummyInstrumentTrack() );
|
||||
//m_window->setModel(
|
||||
// engine::dummyTrackContainer()->
|
||||
// dummyInstrumentTrack() );
|
||||
m_window->updateInstrumentView();
|
||||
s_windowCache << m_window;
|
||||
}
|
||||
@@ -1193,6 +1230,9 @@ class fxLineLcdSpinBox : public lcdSpinBox
|
||||
virtual void mouseDoubleClickEvent ( QMouseEvent * _me )
|
||||
{
|
||||
engine::fxMixerView()->setCurrentFxLine( model()->value() );
|
||||
|
||||
engine::fxMixerView()->show();// show fxMixer window
|
||||
engine::fxMixerView()->setFocus();// set focus to fxMixer window
|
||||
//engine::getFxMixerView()->raise();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* bb_track.cpp - implementation of class bbTrack and bbTCO
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "MainWindow.h"
|
||||
#include "mixer.h"
|
||||
#include "rename_dialog.h"
|
||||
#include "song.h"
|
||||
@@ -223,10 +224,9 @@ void bbTCOView::paintEvent( QPaintEvent * )
|
||||
|
||||
void bbTCOView::openInBBEditor()
|
||||
{
|
||||
engine::getBBTrackContainer()->setCurrentBB( bbTrack::numOfBBTrack(
|
||||
m_bbTCO->getTrack() ) );
|
||||
engine::getBBEditor()->show();
|
||||
engine::getBBEditor()->setFocus();
|
||||
engine::getBBTrackContainer()->setCurrentBB( bbTrack::numOfBBTrack( m_bbTCO->getTrack() ) );
|
||||
|
||||
engine::mainWindow()->toggleBBEditorWin( true );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user