This commit is contained in:
Raine M. Ekman
2014-02-02 20:41:59 +02:00
61 changed files with 411 additions and 140 deletions

14
AUTHORS
View File

@@ -26,6 +26,10 @@ Andrew Kelley
<superjoe30/at/gmail/dot/com>
Development
Wong Cho Ching
<chwongie/hyphen/banana/at/yahoo/dot/com>
Development
Andreas Brandmaier
<andy/at/brandmaier/dot/de>
BitInvader plugin
@@ -43,7 +47,7 @@ Gabriel
Additional artwork
Vesa Kivimäki
<dii/dot/dii/at/nbl/dot/fi>
<contact/dot/diizy/at/nbl/dot/fi>
UI Lead developer
Gurjot Singh
@@ -73,3 +77,11 @@ Rubén Ibarra Pastor
LocoMatt
<samozelko123/at/gmail/dot/com>
3osc skin developer
Chrissy McManus
<chrissy/dot/mc/dot/1/at/hotmail/dot/co/dot/uk>
UI developer
Oskar Wallgren
<oskar/dot/wallgren13/at/gmail/dot/com>
Development

View File

@@ -1,4 +1,4 @@
INCLUDE(InstallHelpers)
INSTALL_DATA_SUBDIRS("samples" "*.wav;*.ogg;*.ds")
INSTALL_DATA_SUBDIRS("samples" "*.wav;*.ogg;*.ds;*.flac")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -153,7 +153,7 @@ private:
} ;
// some constants...
static const int INITIAL_WIDTH = 740;
static const int INITIAL_WIDTH = 860;
static const int INITIAL_HEIGHT = 480;
static const int SCROLLBAR_SIZE = 16;
@@ -249,6 +249,7 @@ private:
bool m_scrollBack;
void drawCross( QPainter & _p );
void drawAutomationPoint( QPainter & p, timeMap::iterator it );
bool inBBEditor();

View File

@@ -111,6 +111,16 @@ public:
return m_tangents;
}
inline float getMin() const
{
return firstObject()->minValue<float>();
}
inline float getMax() const
{
return firstObject()->maxValue<float>();
}
inline bool hasAutomation() const
{
return m_timeMap.isEmpty() == false;
@@ -169,6 +179,8 @@ private:
bool m_dragging;
static const float DEFAULT_MIN_VALUE = 0;
static const float DEFAULT_MAX_VALUE = 1;
friend class AutomationPatternView;

View File

@@ -66,6 +66,8 @@ private:
QPixmap m_paintPixmap;
bool m_needsUpdate;
void scaleTimemapToFit( float oldMin, float oldMax );
} ;

View File

@@ -53,6 +53,9 @@ public:
virtual void loadSettings( const QDomElement & _this );
virtual QString nodeName() const;
static void initGetControllerBySetting();
static PeakController * getControllerBySetting( const QDomElement & _this );
static PeakControllerEffectVector s_effects;
@@ -67,6 +70,12 @@ protected:
PeakControllerEffect * m_peakEffect;
friend class PeakControllerDialog;
private:
//backward compatibility for <= 0.4.15
static int m_getCount;
static int m_loadCount;
static bool m_buggedFile;
} ;

View File

@@ -174,7 +174,8 @@ public:
QString openAudioFile() const;
QString openAndSetAudioFile();
QString openAndSetWaveformFile();
QString & toBase64( QString & _dst ) const;

View File

@@ -48,6 +48,11 @@ public:
return m_lastSample;
}
PeakController * controller()
{
return m_autoController;
}
int m_effectId;
private:
@@ -57,7 +62,7 @@ private:
float m_lastRMS;
bool m_lastRMSavail;
Controller * m_autoController;
PeakController * m_autoController;
friend class PeakControllerEffectControls;

View File

@@ -49,6 +49,7 @@ PeakControllerEffectControls( PeakControllerEffect * _eff ) :
void PeakControllerEffectControls::loadSettings( const QDomElement & _this )
{
m_baseModel.loadSettings( _this, "base" );
@@ -77,7 +78,7 @@ void PeakControllerEffectControls::loadSettings( const QDomElement & _this )
m_effect->m_effectId = rand();
}
if( m_effect->m_autoController && ( engine::getSong()->isLoadingProject() == true || PresetPreviewPlayHandle::isPreviewing() == false ) )
if( m_effect->m_autoController && PresetPreviewPlayHandle::isPreviewing() == true )
{
delete m_effect->m_autoController;
m_effect->m_autoController = 0;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 428 B

View File

@@ -319,36 +319,38 @@ bool SfxrSynth::isPlaying() const
}
sfxrInstrument::sfxrInstrument( InstrumentTrack * _instrument_track ) :
Instrument( _instrument_track, &sfxr_plugin_descriptor ),
m_attModel(0.0f, this),
m_holdModel(0.3f, this),
m_susModel(0.0f, this),
m_decModel(0.4f, this),
m_attModel(0.0f, this, "Attack Time"),
m_holdModel(0.3f, this, "Sustain Time"),
m_susModel(0.0f, this, "Sustain Punch"),
m_decModel(0.4f, this, "Decay Time"),
m_startFreqModel(0.3f, this),
m_minFreqModel(0.0f, this),
m_slideModel(0.0f, this),
m_dSlideModel(0.0f, this),
m_vibDepthModel(0.0f, this),
m_vibSpeedModel(0.0f, this),
m_startFreqModel(0.3f, this, "Start Frequency"),
m_minFreqModel(0.0f, this, "Min Frequency"),
m_slideModel(0.0f, this, "Slide"),
m_dSlideModel(0.0f, this, "Delta Slide"),
m_vibDepthModel(0.0f, this, "Vibrato Depth"),
m_vibSpeedModel(0.0f, this, "Vibrato Speed"),
m_changeAmtModel(0.0f, this),
m_changeSpeedModel(0.0f, this),
m_changeAmtModel(0.0f, this, "Change Amount"),
m_changeSpeedModel(0.0f, this, "Change Speed"),
m_sqrDutyModel(0.0f, this),
m_sqrSweepModel(0.0f, this),
m_sqrDutyModel(0.0f, this, "Squre Duty"),
m_sqrSweepModel(0.0f, this, "Squre Sweep"),
m_repeatSpeedModel(0.0f, this),
m_repeatSpeedModel(0.0f, this, "Repeat Speed"),
m_phaserOffsetModel(0.0f, this),
m_phaserSweepModel(0.0f, this),
m_phaserOffsetModel(0.0f, this, "Phaser Offset"),
m_phaserSweepModel(0.0f, this, "Phaser Sweep"),
m_lpFilCutModel(1.0f, this),
m_lpFilCutSweepModel(0.0f, this),
m_lpFilResoModel(0.0f, this),
m_hpFilCutModel(0.0f, this),
m_hpFilCutSweepModel(0.0f, this),
m_lpFilCutModel(1.0f, this, "LP Filter Cutoff"),
m_lpFilCutSweepModel(0.0f, this, "LP Filter Cutoff Sweep"),
m_lpFilResoModel(0.0f, this, "LP Filter Resonance"),
m_hpFilCutModel(0.0f, this, "HP Filter Cutoff"),
m_hpFilCutSweepModel(0.0f, this, "HP Filter Cutoff Sweep"),
m_waveFormModel( SQR_WAVE, 0, WAVES_NUM-1, this, tr( "Wave Form" ) )
{
}
@@ -551,7 +553,7 @@ public:
#define createKnob(_knob, _x, _y, _name)\
#define createKnob( _knob, _x, _y, _name )\
_knob = new sfxrKnob( this ); \
_knob->setHintText( tr( _name ":" ), "" ); \
_knob->move( _x, _y ); \
@@ -560,8 +562,8 @@ public:
#define createButton(_button, _x, _y, _name, _resName)\
_button = new pixmapButton( this, tr( "Sine wave" ) );\
#define createButton( _button, _x, _y, _name, _resName )\
_button = new pixmapButton( this, tr( _name ) );\
_button->move( _x, _y );\
_button->setActiveGraphic( embed::getIconPixmap( _resName "_active" ) );\
_button->setInactiveGraphic( embed::getIconPixmap( _resName "_inactive" ) );\
@@ -570,8 +572,8 @@ public:
#define createButtonLocalGraphic(_button, _x, _y, _name, _resName)\
_button = new pixmapButton( this, tr( "Sine wave" ) );\
#define createButtonLocalGraphic( _button, _x, _y, _name, _resName )\
_button = new pixmapButton( this, tr( _name ) );\
_button->move( _x, _y );\
_button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( _resName "_active" ) );\
_button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( _resName "_inactive" ) );\

View File

@@ -42,11 +42,11 @@ enum SfxrWaves
};
const int WAVEFORM_BASE_X = 20;
const int WAVEFORM_BASE_Y = 14;
const int WAVEFORM_BASE_Y = 15;
const int WAVEFORM_BUTTON_WIDTH = 16;
const int GENERATOR_BASE_X = 110;
const int GENERATOR_BASE_Y = 24;
const int GENERATOR_BASE_Y = 25;
const int GENERATOR_BUTTON_WIDTH = 16;
const int RAND_BUTTON_X = 160;
@@ -126,8 +126,8 @@ private:
class SfxrZeroToOneFloatModel : public FloatModel
{
public:
SfxrZeroToOneFloatModel(float val, Model * parent):
FloatModel( val, 0.0, 1.0, 0.001, parent)
SfxrZeroToOneFloatModel( float val, Model * parent, const QString& displayName ):
FloatModel( val, 0.0, 1.0, 0.001, parent, displayName )
{
}
/* purpose: prevent the initial value of the model from being changed */
@@ -147,8 +147,8 @@ public:
class SfxrNegPosOneFloatModel : public FloatModel
{
public:
SfxrNegPosOneFloatModel(float val, Model * parent):
FloatModel( val, -1.0, 1.0, 0.001, parent)
SfxrNegPosOneFloatModel(float val, Model * parent, const QString& displayName ):
FloatModel( val, -1.0, 1.0, 0.001, parent, displayName )
{
}
/* purpose: prevent the initial value of the model from being changed */

View File

@@ -138,7 +138,7 @@ OscillatorObject::~OscillatorObject()
void OscillatorObject::oscUserDefWaveDblClick()
{
QString af = m_sampleBuffer->openAndSetAudioFile();
QString af = m_sampleBuffer->openAndSetWaveformFile();
if( af != "" )
{
// TODO:

View File

@@ -84,8 +84,6 @@ AutomationPattern::~AutomationPattern()
void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
{
bool addIt = true;
if( _search_dup )
{
for( objectVector::iterator it = m_objects.begin();
@@ -95,27 +93,26 @@ void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
{
// Already exists
// TODO: Maybe let the user know in some non-annoying way
addIt = false;
break;
return;
}
}
}
if( addIt )
// the automation track is unconnected and there is nothing in the track
if( m_objects.isEmpty() && hasAutomation() == false )
{
// been empty before and model's current value is not its init value?
if( m_objects.isEmpty() && hasAutomation() == false && _obj->isAtInitValue() == false )
{
// then initialize first 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 );
// then initialize first value
putValue( MidiTime(0), _obj->value<float>(), false );
}
m_objects += _obj;
connect( _obj, SIGNAL( destroyed( jo_id_t ) ),
this, SLOT( objectDestroyed( jo_id_t ) ),
Qt::DirectConnection );
emit dataChanged();
}
@@ -158,7 +155,7 @@ const AutomatableModel * AutomationPattern::firstObject() const
return m;
}
static FloatModel _fm( 0, 0, 1, 0.001 );
static FloatModel _fm( 0, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE, 0.001 );
return &_fm;
}
@@ -584,18 +581,18 @@ void AutomationPattern::resolveAllIDs()
AutomationPattern * a = dynamic_cast<AutomationPattern *>( *j );
if( a )
{
for( QVector<jo_id_t>::Iterator k = a->m_idsToResolve.begin();
k != a->m_idsToResolve.end(); ++k )
{
JournallingObject * o = engine::projectJournal()->
journallingObject( *k );
if( o && dynamic_cast<AutomatableModel *>( o ) )
{
a->addObject( dynamic_cast<AutomatableModel *>( o ), false );
}
}
a->m_idsToResolve.clear();
a->dataChanged();
for( QVector<jo_id_t>::Iterator k = a->m_idsToResolve.begin();
k != a->m_idsToResolve.end(); ++k )
{
JournallingObject * o = engine::projectJournal()->
journallingObject( *k );
if( o && dynamic_cast<AutomatableModel *>( o ) )
{
a->addObject( dynamic_cast<AutomatableModel *>( o ), false );
}
}
a->m_idsToResolve.clear();
a->dataChanged();
}
}
}
@@ -639,6 +636,20 @@ void AutomationPattern::objectDestroyed( jo_id_t _id )
// case we had to remove ourselves if we're the global automation
// pattern of the destroyed object
m_idsToResolve += _id;
for( objectVector::Iterator objIt = m_objects.begin();
objIt != m_objects.end(); objIt++ )
{
Q_ASSERT( !(*objIt).isNull() );
if( (*objIt)->id() == _id )
{
//Assign to objIt so that this loop work even break; is removed.
objIt = m_objects.erase( objIt );
break;
}
}
emit dataChanged();
}
@@ -703,4 +714,6 @@ void AutomationPattern::generateTangents( timeMap::const_iterator it,
}
#include "moc_AutomationPattern.cxx"

View File

@@ -177,12 +177,13 @@ Controller * Controller::create( ControllerTypes _ct, Model * _parent )
QString() );
break;
case Controller::LfoController:
c = new ::LfoController( _parent );
case Controller::LfoController:
c = new ::LfoController( _parent );
break;
case Controller::PeakController:
c = new ::PeakController( _parent );
//Already instantiated in EffectChain::loadSettings()
Q_ASSERT( false );
break;
case Controller::MidiController:
@@ -200,9 +201,18 @@ Controller * Controller::create( ControllerTypes _ct, Model * _parent )
Controller * Controller::create( const QDomElement & _this, Model * _parent )
{
Controller * c = create(
static_cast<ControllerTypes>( _this.attribute( "type" ).toInt() ),
_parent );
Controller * c;
if( _this.attribute( "type" ).toInt() == Controller::PeakController )
{
c = PeakController::getControllerBySetting( _this );
}
else
{
c = create(
static_cast<ControllerTypes>( _this.attribute( "type" ).toInt() ),
_parent );
}
if( c != NULL )
{
c->restoreState( _this );

View File

@@ -198,6 +198,7 @@ void LfoController::saveSettings( QDomDocument & _doc, QDomElement & _this )
m_phaseModel.saveSettings( _doc, _this, "phase" );
m_waveModel.saveSettings( _doc, _this, "wave" );
m_multiplierModel.saveSettings( _doc, _this, "multiplier" );
_this.setAttribute( "userwavefile" , m_userDefSampleBuffer->audioFile() );
}
@@ -212,6 +213,7 @@ void LfoController::loadSettings( const QDomElement & _this )
m_phaseModel.loadSettings( _this, "phase" );
m_waveModel.loadSettings( _this, "wave" );
m_multiplierModel.loadSettings( _this, "multiplier" );
m_userDefSampleBuffer->setAudioFile( _this.attribute("userwavefile" ) );
updateSampleFunction();
}

View File

@@ -28,6 +28,7 @@
#include <QtXml/QDomElement>
#include <QtCore/QObject>
#include <QtCore/QVector>
#include <QMessageBox>
#include "song.h"
@@ -37,8 +38,12 @@
#include "EffectChain.h"
#include "ControllerDialog.h"
#include "plugins/peak_controller_effect/peak_controller_effect.h"
#include "PresetPreviewPlayHandle.h"
PeakControllerEffectVector PeakController::s_effects;
int PeakController::m_getCount;
int PeakController::m_loadCount;
bool PeakController::m_buggedFile;
PeakController::PeakController( Model * _parent,
@@ -58,7 +63,11 @@ PeakController::PeakController( Model * _parent,
PeakController::~PeakController()
{
if( m_peakEffect != NULL && m_peakEffect->effectChain() != NULL )
//EffectChain::loadSettings() appends effect to EffectChain::m_effects
//When it's previewing, EffectChain::loadSettings(<Controller Fx XML>) is not called
//Therefore, we shouldn't call removeEffect() as it is not even appended.
//NB: Most XML setting are loaded on preview, except controller fx.
if( m_peakEffect != NULL && m_peakEffect->effectChain() != NULL && PresetPreviewPlayHandle::isPreviewing() == false )
{
m_peakEffect->effectChain()->removeEffect( m_peakEffect );
}
@@ -103,7 +112,13 @@ void PeakController::saveSettings( QDomDocument & _doc, QDomElement & _this )
void PeakController::loadSettings( const QDomElement & _this )
{
Controller::loadSettings( _this );
int effectId = _this.attribute( "effectId" ).toInt();
if( m_buggedFile == true )
{
effectId = m_loadCount++;
}
PeakControllerEffectVector::Iterator i;
for( i = s_effects.begin(); i != s_effects.end(); ++i )
@@ -118,6 +133,76 @@ void PeakController::loadSettings( const QDomElement & _this )
//Backward compatibility function for bug in <= 0.4.15
void PeakController::initGetControllerBySetting()
{
m_loadCount = 0;
m_getCount = 0;
m_buggedFile = false;
}
PeakController * PeakController::getControllerBySetting(const QDomElement & _this )
{
int effectId = _this.attribute( "effectId" ).toInt();
PeakControllerEffectVector::Iterator i;
//Backward compatibility for bug in <= 0.4.15 . For >= 1.0.0 ,
//foundCount should always be 1 because m_effectId is initialized with rand()
int foundCount = 0;
if( m_buggedFile == false )
{
for( i = s_effects.begin(); i != s_effects.end(); ++i )
{
if( (*i)->m_effectId == effectId )
{
foundCount++;
}
}
if( foundCount >= 2 )
{
m_buggedFile = true;
int newEffectId = 0;
for( i = s_effects.begin(); i != s_effects.end(); ++i )
{
(*i)->m_effectId = newEffectId++;
}
QMessageBox msgBox;
msgBox.setIcon( QMessageBox::Information );
msgBox.setWindowTitle( tr("Peak Controller Bug") );
msgBox.setText( tr("Due to a bug in older version of LMMS, the peak "
"controllers may not be connect properly. "
"Please ensure that peak controllers are connected "
"properly and re-save this file. "
"Sorry for any inconvenience caused.") );
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
}
}
if( m_buggedFile == true )
{
effectId = m_getCount;
}
m_getCount++; //NB: m_getCount should be increased even m_buggedFile is false
for( i = s_effects.begin(); i != s_effects.end(); ++i )
{
if( (*i)->m_effectId == effectId )
{
return (*i)->controller();
}
}
return NULL;
}
QString PeakController::nodeName() const
{
return( "Peakcontroller" );

View File

@@ -88,8 +88,8 @@ public:
bool isPreviewing()
{
bool ret = m_dataMutex.tryLock();
if( ret == true )
bool ret = !m_dataMutex.tryLock();
if( ret == false )
{
m_dataMutex.unlock();
}

View File

@@ -908,6 +908,27 @@ QString SampleBuffer::openAndSetAudioFile()
}
QString SampleBuffer::openAndSetWaveformFile()
{
if( m_audioFile.isEmpty() )
{
m_audioFile = configManager::inst()->factorySamplesDir() + "waveforms/10saw.flac";
}
QString fileName = this->openAudioFile();
if(!fileName.isEmpty())
{
this->setAudioFile( fileName );
}
else
{
m_audioFile = "";
}
return fileName;
}
#undef LMMS_HAVE_FLAC_STREAM_ENCODER_H /* not yet... */

View File

@@ -61,6 +61,7 @@
#include "templates.h"
#include "text_float.h"
#include "timeline.h"
#include "PeakController.h"
#ifdef LMMS_BUILD_WIN32
#ifndef USE_QT_SHMEM
@@ -1141,6 +1142,10 @@ void song::loadProject( const QString & _file_name )
m_globalAutomationTrack->restoreState( mmp.content().
firstChildElement( "track" ) );
}
//Backward compatibility for LMMS <= 0.4.15
PeakController::initGetControllerBySetting();
QDomNode node = mmp.content().firstChild();
while( !node.isNull() )
{
@@ -1354,7 +1359,16 @@ void song::restoreControllerStates( const QDomElement & _this )
QDomNode node = _this.firstChild();
while( !node.isNull() )
{
addController( Controller::create( node.toElement(), this ) );
Controller * c = Controller::create( node.toElement(), this );
Q_ASSERT( c != NULL );
/* For PeakController, addController() was called in
* PeakControllerEffect::PeakControllerEffect().
* This line removes the previously added controller for PeakController
* without affecting the order of controllers in Controller Rack
*/
engine::getSong()->removeController( c );
addController( c );
node = node.nextSibling();
}

View File

@@ -283,14 +283,14 @@ void timeLine::mousePressEvent( QMouseEvent* event )
m_moveXOff = s_posMarkerPixmap->width() / 2;
}
}
else if( event->button() == Qt::RightButton )
else if( event->button() == Qt::RightButton || event->button() == Qt::MiddleButton )
{
const MidiTime t = m_begin + static_cast<int>( event->x() * MidiTime::ticksPerTact() / m_ppt );
if( m_loopPos[0] > m_loopPos[1] )
{
qSwap( m_loopPos[0], m_loopPos[1] );
}
if( event->modifiers() & Qt::ShiftModifier )
if( ( event->modifiers() & Qt::ShiftModifier ) || event->button() == Qt::MiddleButton )
{
m_action = MoveLoopBegin;
}

View File

@@ -72,6 +72,10 @@ QPixmap * AutomationEditor::s_toolSelect = NULL;
QPixmap * AutomationEditor::s_toolMove = NULL;
const QColor DRAGGABLE_PIN_COLOR = QColor( 0xFF, 0x00, 0x00 );
const QColor DRAGGABLE_PIN_BORDER_COLOR = QColor( 0xFF, 0xFF, 0xFF );
AutomationEditor::AutomationEditor() :
QWidget(),
m_zoomingXModel(),
@@ -1348,6 +1352,22 @@ inline void AutomationEditor::drawCross( QPainter & _p )
inline void AutomationEditor::drawAutomationPoint( QPainter & p, timeMap::iterator it )
{
int x = xCoordOfTick( it.key() );
int y = yCoordOfLevel( it.value() );
int outerRadius = qMin( 8, m_ppt/quantization() );
int innerRadius = qMax( 0, outerRadius-2 );
p.setBrush( QBrush( DRAGGABLE_PIN_BORDER_COLOR ) );
p.drawEllipse( x-outerRadius/2, y-outerRadius/2, outerRadius, outerRadius );
p.setBrush( QBrush( DRAGGABLE_PIN_COLOR ) );
p.drawEllipse( x-innerRadius/2, y-innerRadius/2, innerRadius, innerRadius );
p.setBrush( QBrush() );
}
void AutomationEditor::paintEvent( QPaintEvent * _pe )
{
QMutexLocker m( &m_patternMutex );
@@ -1526,71 +1546,75 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe )
{
int len_ticks = 4;
timeMap & time_map = m_pattern->getTimeMap();
timeMap::iterator it = time_map.begin();
p.setPen( QColor( 0xCF, 0xD9, 0xFF ) );
while( it+1 != time_map.end() )
//Don't bother doing/rendering anything if there is no automation points
if( time_map.size() > 0 )
{
// skip this section if it occurs completely before the
// visible area
int next_x = xCoordOfTick( (it+1).key() );
if( next_x < 0 )
timeMap::iterator it = time_map.begin();
p.setPen( QColor( 0xCF, 0xD9, 0xFF ) );
while( it+1 != time_map.end() )
{
++it;
continue;
}
// skip this section if it occurs completely before the
// visible area
int next_x = xCoordOfTick( (it+1).key() );
if( next_x < 0 )
{
++it;
continue;
}
int x = xCoordOfTick( it.key() );
if( x > width() )
{
break;
}
int x = xCoordOfTick( it.key() );
if( x > width() )
{
break;
}
bool is_selected = FALSE;
// if we're in move-mode, we may only draw
// values in selected area, that have originally
// been selected and not values that are now in
// selection because the user moved it...
if( m_editMode == MOVE )
{
if( m_selValuesForMove.contains( it.key() ) )
bool is_selected = FALSE;
// if we're in move-mode, we may only draw
// values in selected area, that have originally
// been selected and not values that are now in
// selection because the user moved it...
if( m_editMode == MOVE )
{
if( m_selValuesForMove.contains( it.key() ) )
{
is_selected = TRUE;
}
}
else if( it.value() >= selLevel_start &&
it.value() <= selLevel_end &&
it.key() >= sel_pos_start &&
it.key() + len_ticks <= sel_pos_end )
{
is_selected = TRUE;
}
float *values = m_pattern->valuesAfter( it.key() );
for( int i = 0; i < (it+1).key() - it.key(); i++ )
{
drawLevelTick( p, it.key() + i, values[i],
is_selected );
}
delete [] values;
// Draw circle
drawAutomationPoint(p, it);
++it;
}
else if( it.value() >= selLevel_start &&
it.value() <= selLevel_end &&
it.key() >= sel_pos_start &&
it.key() + len_ticks <= sel_pos_end )
Q_ASSERT( it == time_map.end()-1 );
for( int i = it.key(), x = xCoordOfTick( i ); x <= width();
i++, x = xCoordOfTick( i ) )
{
is_selected = TRUE;
// TODO: Find out if the section after the last control
// point is able to be selected and if so set this
// boolean correctly
drawLevelTick( p, i, it.value(), false );
}
float *values = m_pattern->valuesAfter( it.key() );
for( int i = 0; i < (it+1).key() - it.key(); i++ )
{
drawLevelTick( p, it.key() + i, values[i],
is_selected );
}
delete [] values;
// Draw cross
int y = yCoordOfLevel( it.value() );
p.drawLine( x - 1, y, x + 1, y );
p.drawLine( x, y - 1, x, y + 1 );
// _p.setPen( QColor( 0xFF, 0x9F, 0x00 ) );
// _p.setPen( QColor( 0xFF, 0xFF, 0x40 ) );
++it;
}
for( int i = it.key(), x = xCoordOfTick( i ); x <= width();
i++, x = xCoordOfTick( i ) )
{
// TODO: Find out if the section after the last control
// point is able to be selected and if so set this
// boolean correctly
drawLevelTick( p, i, it.value(), false );
// Draw circle(the last one)
drawAutomationPoint(p, it);
}
}
else

View File

@@ -107,10 +107,26 @@ void AutomationPatternView::disconnectObject( QAction * _a )
journallingObject( _a->data().toInt() );
if( j && dynamic_cast<AutomatableModel *>( j ) )
{
float oldMin = m_pat->getMin();
float oldMax = m_pat->getMax();
m_pat->m_objects.erase( qFind( m_pat->m_objects.begin(),
m_pat->m_objects.end(),
dynamic_cast<AutomatableModel *>( j ) ) );
update();
//If automation editor is opened, update its display after disconnection
if( engine::automationEditor() )
{
engine::automationEditor()->updateAfterPatternChange();
}
//if there is no more connection connected to the AutomationPattern
if( m_pat->m_objects.size() == 0 )
{
//scale the points to fit the new min. and max. value
this->scaleTimemapToFit( oldMin, oldMax );
}
}
}
@@ -333,6 +349,14 @@ void AutomationPatternView::dropEvent( QDropEvent * _de )
{
engine::automationEditor()->setCurrentPattern( m_pat );
}
//This is the only model that's just added to AutomationPattern.
if( m_pat->m_objects.size() == 1 )
{
//scale the points to fit the new min. and max. value
this->scaleTimemapToFit( AutomationPattern::DEFAULT_MIN_VALUE,
AutomationPattern::DEFAULT_MAX_VALUE );
}
}
else
{
@@ -343,5 +367,37 @@ void AutomationPatternView::dropEvent( QDropEvent * _de )
/**
* @brief Preserves the auto points over different scale
*/
void AutomationPatternView::scaleTimemapToFit( float oldMin, float oldMax )
{
float newMin = m_pat->getMin();
float newMax = m_pat->getMax();
if( oldMin == newMin && oldMax == newMax )
{
return;
}
for( AutomationPattern::timeMap::iterator it = m_pat->m_timeMap.begin();
it != m_pat->m_timeMap.end(); ++it )
{
if( *it < oldMin )
{
*it = oldMin;
}
else if( *it > oldMax )
{
*it = oldMax;
}
*it = (*it-oldMin)*(newMax-newMin)/(oldMax-oldMin)+newMin;
}
m_pat->generateTangents();
}
#include "moc_AutomationPatternView.cxx"

View File

@@ -252,7 +252,7 @@ void LfoControllerDialog::askUserDefWave()
{
SampleBuffer * sampleBuffer = dynamic_cast<LfoController*>(this->model())->
m_userDefSampleBuffer;
QString fileName = sampleBuffer->openAndSetAudioFile();
QString fileName = sampleBuffer->openAndSetWaveformFile();
if( fileName.isEmpty() == false )
{
// TODO:

View File

@@ -68,12 +68,12 @@ bbEditor::bbEditor( bbTrackContainer* tc ) :
"compacttrackbuttons" ).toInt() )
{
setMinimumWidth( TRACK_OP_WIDTH_COMPACT + DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT
+ 2 * TCO_BORDER_WIDTH + 192 );
+ 2 * TCO_BORDER_WIDTH + 264 );
}
else
{
setMinimumWidth( TRACK_OP_WIDTH + DEFAULT_SETTINGS_WIDGET_WIDTH
+ 2 * TCO_BORDER_WIDTH + 192 );
+ 2 * TCO_BORDER_WIDTH + 264 );
}

View File

@@ -485,7 +485,7 @@ void graphModel::setWaveToNoise()
QString graphModel::setWaveToUser()
{
SampleBuffer * sampleBuffer = new SampleBuffer;
QString fileName = sampleBuffer->openAndSetAudioFile();
QString fileName = sampleBuffer->openAndSetWaveformFile();
if( fileName.isEmpty() == false )
{
for( int i = 0; i < length(); i++ )

View File

@@ -1332,6 +1332,7 @@ void InstrumentTrackWindow::modelChanged()
{
m_pitchKnob->hide();
m_pitchKnob->setModel( NULL );
m_pitchRangeSpinBox->hide();
}
m_ssView->setModel( &m_track->m_soundShaping );