Split Sample Track classes into separate files (#5987)
This commit is contained in:
92
include/SampleTCO.h
Normal file
92
include/SampleTCO.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* SampleTCO.h
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SAMPLE_TCO_H
|
||||
#define SAMPLE_TCO_H
|
||||
|
||||
#include "SampleBuffer.h"
|
||||
#include "SampleTrack.h"
|
||||
#include "TrackContentObject.h"
|
||||
|
||||
|
||||
class SampleTCO : public TrackContentObject
|
||||
{
|
||||
Q_OBJECT
|
||||
mapPropertyFromModel(bool,isRecord,setRecord,m_recordModel);
|
||||
public:
|
||||
SampleTCO( Track * _track );
|
||||
SampleTCO( const SampleTCO& orig );
|
||||
virtual ~SampleTCO();
|
||||
|
||||
SampleTCO& operator=( const SampleTCO& that ) = delete;
|
||||
|
||||
void changeLength( const TimePos & _length ) override;
|
||||
const QString & sampleFile() const;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return "sampletco";
|
||||
}
|
||||
|
||||
SampleBuffer* sampleBuffer()
|
||||
{
|
||||
return m_sampleBuffer;
|
||||
}
|
||||
|
||||
TimePos sampleLength() const;
|
||||
void setSampleStartFrame( f_cnt_t startFrame );
|
||||
void setSamplePlayLength( f_cnt_t length );
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
|
||||
|
||||
bool isPlaying() const;
|
||||
void setIsPlaying(bool isPlaying);
|
||||
|
||||
public slots:
|
||||
void setSampleBuffer( SampleBuffer* sb );
|
||||
void setSampleFile( const QString & _sf );
|
||||
void updateLength();
|
||||
void toggleRecord();
|
||||
void playbackPositionChanged();
|
||||
void updateTrackTcos();
|
||||
|
||||
|
||||
private:
|
||||
SampleBuffer* m_sampleBuffer;
|
||||
BoolModel m_recordModel;
|
||||
bool m_isPlaying;
|
||||
|
||||
friend class SampleTCOView;
|
||||
|
||||
|
||||
signals:
|
||||
void sampleChanged();
|
||||
void wasReversed();
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
65
include/SampleTCOView.h
Normal file
65
include/SampleTCOView.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SampleTCOView.h
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SAMPLE_TCO_VIEW_H
|
||||
#define SAMPLE_TCO_VIEW_H
|
||||
|
||||
#include "SampleTCOView.h"
|
||||
|
||||
#include "SampleTCO.h"
|
||||
#include "TrackContentObjectView.h"
|
||||
|
||||
class SampleTCOView : public TrackContentObjectView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SampleTCOView( SampleTCO * _tco, TrackView * _tv );
|
||||
virtual ~SampleTCOView() = default;
|
||||
|
||||
public slots:
|
||||
void updateSample();
|
||||
void reverseSample();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * _cme ) override;
|
||||
void mousePressEvent( QMouseEvent * _me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * _me ) override;
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * ) override;
|
||||
void paintEvent( QPaintEvent * ) override;
|
||||
|
||||
|
||||
private:
|
||||
SampleTCO * m_tco;
|
||||
QPixmap m_paintPixmap;
|
||||
bool splitTCO( const TimePos pos ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -25,116 +25,14 @@
|
||||
#ifndef SAMPLE_TRACK_H
|
||||
#define SAMPLE_TRACK_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLayout>
|
||||
|
||||
#include "AudioPort.h"
|
||||
#include "FadeButton.h"
|
||||
#include "FxMixer.h"
|
||||
#include "FxLineLcdSpinBox.h"
|
||||
#include "SampleTCO.h"
|
||||
#include "SampleTrackView.h"
|
||||
#include "Track.h"
|
||||
#include "TrackContentObjectView.h"
|
||||
#include "TrackView.h"
|
||||
|
||||
class EffectRackView;
|
||||
class Knob;
|
||||
class SampleBuffer;
|
||||
class SampleTrackWindow;
|
||||
class TrackLabelButton;
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
class SampleTCO : public TrackContentObject
|
||||
{
|
||||
Q_OBJECT
|
||||
mapPropertyFromModel(bool,isRecord,setRecord,m_recordModel);
|
||||
public:
|
||||
SampleTCO( Track * _track );
|
||||
SampleTCO( const SampleTCO& orig );
|
||||
virtual ~SampleTCO();
|
||||
|
||||
SampleTCO& operator=( const SampleTCO& that ) = delete;
|
||||
|
||||
void changeLength( const TimePos & _length ) override;
|
||||
const QString & sampleFile() const;
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
inline QString nodeName() const override
|
||||
{
|
||||
return "sampletco";
|
||||
}
|
||||
|
||||
SampleBuffer* sampleBuffer()
|
||||
{
|
||||
return m_sampleBuffer;
|
||||
}
|
||||
|
||||
TimePos sampleLength() const;
|
||||
void setSampleStartFrame( f_cnt_t startFrame );
|
||||
void setSamplePlayLength( f_cnt_t length );
|
||||
TrackContentObjectView * createView( TrackView * _tv ) override;
|
||||
|
||||
|
||||
bool isPlaying() const;
|
||||
void setIsPlaying(bool isPlaying);
|
||||
|
||||
public slots:
|
||||
void setSampleBuffer( SampleBuffer* sb );
|
||||
void setSampleFile( const QString & _sf );
|
||||
void updateLength();
|
||||
void toggleRecord();
|
||||
void playbackPositionChanged();
|
||||
void updateTrackTcos();
|
||||
|
||||
|
||||
private:
|
||||
SampleBuffer* m_sampleBuffer;
|
||||
BoolModel m_recordModel;
|
||||
bool m_isPlaying;
|
||||
|
||||
friend class SampleTCOView;
|
||||
|
||||
|
||||
signals:
|
||||
void sampleChanged();
|
||||
void wasReversed();
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class SampleTCOView : public TrackContentObjectView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SampleTCOView( SampleTCO * _tco, TrackView * _tv );
|
||||
virtual ~SampleTCOView() = default;
|
||||
|
||||
public slots:
|
||||
void updateSample();
|
||||
void reverseSample();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * _cme ) override;
|
||||
void mousePressEvent( QMouseEvent * _me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * _me ) override;
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * ) override;
|
||||
void paintEvent( QPaintEvent * ) override;
|
||||
|
||||
|
||||
private:
|
||||
SampleTCO * m_tco;
|
||||
QPixmap m_paintPixmap;
|
||||
bool splitTCO( const TimePos pos ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
class SampleTrack : public Track
|
||||
@@ -204,124 +102,4 @@ private:
|
||||
|
||||
|
||||
|
||||
class SampleTrackView : public TrackView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SampleTrackView( SampleTrack* Track, TrackContainerView* tcv );
|
||||
virtual ~SampleTrackView();
|
||||
|
||||
SampleTrackWindow * getSampleTrackWindow()
|
||||
{
|
||||
return m_window;
|
||||
}
|
||||
|
||||
SampleTrack * model()
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
const SampleTrack * model() const
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
|
||||
QMenu * createFxMenu( QString title, QString newFxLabel ) override;
|
||||
|
||||
|
||||
public slots:
|
||||
void showEffects();
|
||||
void updateIndicator();
|
||||
|
||||
|
||||
protected:
|
||||
void modelChanged() override;
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "SampleTrackView";
|
||||
}
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *dee) override;
|
||||
void dropEvent(QDropEvent *de) override;
|
||||
|
||||
private slots:
|
||||
void assignFxLine( int channelIndex );
|
||||
void createFxLine();
|
||||
|
||||
|
||||
private:
|
||||
SampleTrackWindow * m_window;
|
||||
Knob * m_volumeKnob;
|
||||
Knob * m_panningKnob;
|
||||
FadeButton * m_activityIndicator;
|
||||
|
||||
TrackLabelButton * m_tlb;
|
||||
|
||||
FadeButton * getActivityIndicator() override
|
||||
{
|
||||
return m_activityIndicator;
|
||||
}
|
||||
|
||||
friend class SampleTrackWindow;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
class SampleTrackWindow : public QWidget, public ModelView, public SerializingObjectHook
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SampleTrackWindow(SampleTrackView * tv);
|
||||
virtual ~SampleTrackWindow();
|
||||
|
||||
SampleTrack * model()
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
const SampleTrack * model() const
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
void setSampleTrackView(SampleTrackView * tv);
|
||||
|
||||
SampleTrackView *sampleTrackView()
|
||||
{
|
||||
return m_stv;
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void textChanged(const QString & new_name);
|
||||
void toggleVisibility(bool on);
|
||||
void updateName();
|
||||
|
||||
|
||||
protected:
|
||||
// capture close-events for toggling sample-track-button
|
||||
void closeEvent(QCloseEvent * ce) override;
|
||||
|
||||
void saveSettings(QDomDocument & doc, QDomElement & element) override;
|
||||
void loadSettings(const QDomElement & element) override;
|
||||
|
||||
private:
|
||||
void modelChanged() override;
|
||||
|
||||
SampleTrack * m_track;
|
||||
SampleTrackView * m_stv;
|
||||
|
||||
// widgets on the top of an sample-track-window
|
||||
QLineEdit * m_nameLineEdit;
|
||||
Knob * m_volumeKnob;
|
||||
Knob * m_panningKnob;
|
||||
FxLineLcdSpinBox * m_effectChannelNumber;
|
||||
|
||||
EffectRackView * m_effectRack;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
102
include/SampleTrackView.h
Normal file
102
include/SampleTrackView.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* SampleTrackView.h
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SAMPLE_TRACK_VIEW_H
|
||||
#define SAMPLE_TRACK_VIEW_H
|
||||
|
||||
#include "SampleTrack.h"
|
||||
|
||||
#include "TrackView.h"
|
||||
|
||||
class Knob;
|
||||
class SampleTrack;
|
||||
class SampleTrackWindow;
|
||||
class TrackLabelButton;
|
||||
|
||||
|
||||
class SampleTrackView : public TrackView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SampleTrackView( SampleTrack* Track, TrackContainerView* tcv );
|
||||
virtual ~SampleTrackView();
|
||||
|
||||
SampleTrackWindow * getSampleTrackWindow()
|
||||
{
|
||||
return m_window;
|
||||
}
|
||||
|
||||
SampleTrack * model()
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
const SampleTrack * model() const
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
|
||||
QMenu * createFxMenu( QString title, QString newFxLabel ) override;
|
||||
|
||||
|
||||
public slots:
|
||||
void showEffects();
|
||||
void updateIndicator();
|
||||
|
||||
|
||||
protected:
|
||||
void modelChanged() override;
|
||||
QString nodeName() const override
|
||||
{
|
||||
return "SampleTrackView";
|
||||
}
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *dee) override;
|
||||
void dropEvent(QDropEvent *de) override;
|
||||
|
||||
private slots:
|
||||
void assignFxLine( int channelIndex );
|
||||
void createFxLine();
|
||||
|
||||
|
||||
private:
|
||||
SampleTrackWindow * m_window;
|
||||
Knob * m_volumeKnob;
|
||||
Knob * m_panningKnob;
|
||||
FadeButton * m_activityIndicator;
|
||||
|
||||
TrackLabelButton * m_tlb;
|
||||
|
||||
FadeButton * getActivityIndicator() override
|
||||
{
|
||||
return m_activityIndicator;
|
||||
}
|
||||
|
||||
friend class SampleTrackWindow;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
92
include/SampleTrackWindow.h
Normal file
92
include/SampleTrackWindow.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* SampleTrackWindow.h
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SAMPLE_TRACK_WINDOW_H
|
||||
#define SAMPLE_TRACK_WINDOW_H
|
||||
|
||||
#include "FxLineLcdSpinBox.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "EffectRackView.h"
|
||||
#include "SampleTrack.h"
|
||||
|
||||
|
||||
class SampleTrackWindow : public QWidget, public ModelView, public SerializingObjectHook
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SampleTrackWindow(SampleTrackView * tv);
|
||||
virtual ~SampleTrackWindow();
|
||||
|
||||
SampleTrack * model()
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
const SampleTrack * model() const
|
||||
{
|
||||
return castModel<SampleTrack>();
|
||||
}
|
||||
|
||||
void setSampleTrackView(SampleTrackView * tv);
|
||||
|
||||
SampleTrackView *sampleTrackView()
|
||||
{
|
||||
return m_stv;
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
void textChanged(const QString & new_name);
|
||||
void toggleVisibility(bool on);
|
||||
void updateName();
|
||||
|
||||
|
||||
protected:
|
||||
// capture close-events for toggling sample-track-button
|
||||
void closeEvent(QCloseEvent * ce) override;
|
||||
|
||||
void saveSettings(QDomDocument & doc, QDomElement & element) override;
|
||||
void loadSettings(const QDomElement & element) override;
|
||||
|
||||
private:
|
||||
void modelChanged() override;
|
||||
|
||||
SampleTrack * m_track;
|
||||
SampleTrackView * m_stv;
|
||||
|
||||
// widgets on the top of an sample-track-window
|
||||
QLineEdit * m_nameLineEdit;
|
||||
Knob * m_volumeKnob;
|
||||
Knob * m_panningKnob;
|
||||
FxLineLcdSpinBox * m_effectChannelNumber;
|
||||
|
||||
EffectRackView * m_effectRack;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -66,6 +66,7 @@ set(LMMS_SRCS
|
||||
core/SampleBuffer.cpp
|
||||
core/SamplePlayHandle.cpp
|
||||
core/SampleRecordHandle.cpp
|
||||
core/SampleTCO.cpp
|
||||
core/SerializingObject.cpp
|
||||
core/Song.cpp
|
||||
core/TempoSyncKnobModel.cpp
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "Engine.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "Mixer.h"
|
||||
#include "SampleTrack.h"
|
||||
#include "SampleTCO.h"
|
||||
|
||||
|
||||
|
||||
|
||||
316
src/core/SampleTCO.cpp
Normal file
316
src/core/SampleTCO.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* SampleTCO.cpp
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SampleTCO.h"
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "SampleTCOView.h"
|
||||
#include "TimeLineWidget.h"
|
||||
|
||||
SampleTCO::SampleTCO( Track * _track ) :
|
||||
TrackContentObject( _track ),
|
||||
m_sampleBuffer( new SampleBuffer ),
|
||||
m_isPlaying( false )
|
||||
{
|
||||
saveJournallingState( false );
|
||||
setSampleFile( "" );
|
||||
restoreJournallingState();
|
||||
|
||||
// we need to receive bpm-change-events, because then we have to
|
||||
// change length of this TCO
|
||||
connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
|
||||
this, SLOT( updateLength() ), Qt::DirectConnection );
|
||||
connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int,int ) ),
|
||||
this, SLOT( updateLength() ) );
|
||||
|
||||
//care about positionmarker
|
||||
TimeLineWidget * timeLine = Engine::getSong()->getPlayPos( Engine::getSong()->Mode_PlaySong ).m_timeLine;
|
||||
if( timeLine )
|
||||
{
|
||||
connect( timeLine, SIGNAL( positionMarkerMoved() ), this, SLOT( playbackPositionChanged() ) );
|
||||
}
|
||||
//playbutton clicked or space key / on Export Song set isPlaying to false
|
||||
connect( Engine::getSong(), SIGNAL( playbackStateChanged() ),
|
||||
this, SLOT( playbackPositionChanged() ), Qt::DirectConnection );
|
||||
//care about loops
|
||||
connect( Engine::getSong(), SIGNAL( updateSampleTracks() ),
|
||||
this, SLOT( playbackPositionChanged() ), Qt::DirectConnection );
|
||||
//care about mute TCOs
|
||||
connect( this, SIGNAL( dataChanged() ), this, SLOT( playbackPositionChanged() ) );
|
||||
//care about mute track
|
||||
connect( getTrack()->getMutedModel(), SIGNAL( dataChanged() ),
|
||||
this, SLOT( playbackPositionChanged() ), Qt::DirectConnection );
|
||||
//care about TCO position
|
||||
connect( this, SIGNAL( positionChanged() ), this, SLOT( updateTrackTcos() ) );
|
||||
|
||||
switch( getTrack()->trackContainer()->type() )
|
||||
{
|
||||
case TrackContainer::BBContainer:
|
||||
setAutoResize( true );
|
||||
break;
|
||||
|
||||
case TrackContainer::SongContainer:
|
||||
// move down
|
||||
default:
|
||||
setAutoResize( false );
|
||||
break;
|
||||
}
|
||||
updateTrackTcos();
|
||||
}
|
||||
|
||||
SampleTCO::SampleTCO(const SampleTCO& orig) :
|
||||
SampleTCO(orig.getTrack())
|
||||
{
|
||||
// TODO: This creates a new SampleBuffer for the new TCO, eating up memory
|
||||
// & eventually causing performance issues. Letting tracks share buffers
|
||||
// when they're identical would fix this, but isn't possible right now.
|
||||
*m_sampleBuffer = *orig.m_sampleBuffer;
|
||||
m_isPlaying = orig.m_isPlaying;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleTCO::~SampleTCO()
|
||||
{
|
||||
SampleTrack * sampletrack = dynamic_cast<SampleTrack*>( getTrack() );
|
||||
if ( sampletrack )
|
||||
{
|
||||
sampletrack->updateTcos();
|
||||
}
|
||||
Engine::mixer()->requestChangeInModel();
|
||||
sharedObject::unref( m_sampleBuffer );
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::changeLength( const TimePos & _length )
|
||||
{
|
||||
TrackContentObject::changeLength( qMax( static_cast<int>( _length ), 1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QString & SampleTCO::sampleFile() const
|
||||
{
|
||||
return m_sampleBuffer->audioFile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTCO::setSampleBuffer( SampleBuffer* sb )
|
||||
{
|
||||
Engine::mixer()->requestChangeInModel();
|
||||
sharedObject::unref( m_sampleBuffer );
|
||||
Engine::mixer()->doneChangeInModel();
|
||||
m_sampleBuffer = sb;
|
||||
updateLength();
|
||||
|
||||
emit sampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTCO::setSampleFile( const QString & _sf )
|
||||
{
|
||||
int length;
|
||||
if ( _sf.isEmpty() )
|
||||
{ //When creating an empty sample pattern make it a bar long
|
||||
float nom = Engine::getSong()->getTimeSigModel().getNumerator();
|
||||
float den = Engine::getSong()->getTimeSigModel().getDenominator();
|
||||
length = DefaultTicksPerBar * ( nom / den );
|
||||
}
|
||||
else
|
||||
{ //Otherwise set it to the sample's length
|
||||
m_sampleBuffer->setAudioFile( _sf );
|
||||
length = sampleLength();
|
||||
}
|
||||
changeLength(length);
|
||||
|
||||
setStartTimeOffset( 0 );
|
||||
|
||||
emit sampleChanged();
|
||||
emit playbackPositionChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::toggleRecord()
|
||||
{
|
||||
m_recordModel.setValue( !m_recordModel.value() );
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::playbackPositionChanged()
|
||||
{
|
||||
Engine::mixer()->removePlayHandlesOfTypes( getTrack(), PlayHandle::TypeSamplePlayHandle );
|
||||
SampleTrack * st = dynamic_cast<SampleTrack*>( getTrack() );
|
||||
st->setPlayingTcos( false );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::updateTrackTcos()
|
||||
{
|
||||
SampleTrack * sampletrack = dynamic_cast<SampleTrack*>( getTrack() );
|
||||
if( sampletrack)
|
||||
{
|
||||
sampletrack->updateTcos();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool SampleTCO::isPlaying() const
|
||||
{
|
||||
return m_isPlaying;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::setIsPlaying(bool isPlaying)
|
||||
{
|
||||
m_isPlaying = isPlaying;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::updateLength()
|
||||
{
|
||||
emit sampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TimePos SampleTCO::sampleLength() const
|
||||
{
|
||||
return (int)( m_sampleBuffer->frames() / Engine::framesPerTick() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::setSampleStartFrame(f_cnt_t startFrame)
|
||||
{
|
||||
m_sampleBuffer->setStartFrame( startFrame );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::setSamplePlayLength(f_cnt_t length)
|
||||
{
|
||||
m_sampleBuffer->setEndFrame( length );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
if( _this.parentNode().nodeName() == "clipboard" )
|
||||
{
|
||||
_this.setAttribute( "pos", -1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
_this.setAttribute( "pos", startPosition() );
|
||||
}
|
||||
_this.setAttribute( "len", length() );
|
||||
_this.setAttribute( "muted", isMuted() );
|
||||
_this.setAttribute( "src", sampleFile() );
|
||||
_this.setAttribute( "off", startTimeOffset() );
|
||||
if( sampleFile() == "" )
|
||||
{
|
||||
QString s;
|
||||
_this.setAttribute( "data", m_sampleBuffer->toBase64( s ) );
|
||||
}
|
||||
|
||||
_this.setAttribute( "sample_rate", m_sampleBuffer->sampleRate());
|
||||
if( usesCustomClipColor() )
|
||||
{
|
||||
_this.setAttribute( "color", color().name() );
|
||||
}
|
||||
if (m_sampleBuffer->reversed())
|
||||
{
|
||||
_this.setAttribute("reversed", "true");
|
||||
}
|
||||
// TODO: start- and end-frame
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCO::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
if( _this.attribute( "pos" ).toInt() >= 0 )
|
||||
{
|
||||
movePosition( _this.attribute( "pos" ).toInt() );
|
||||
}
|
||||
setSampleFile( _this.attribute( "src" ) );
|
||||
if( sampleFile().isEmpty() && _this.hasAttribute( "data" ) )
|
||||
{
|
||||
m_sampleBuffer->loadFromBase64( _this.attribute( "data" ) );
|
||||
}
|
||||
changeLength( _this.attribute( "len" ).toInt() );
|
||||
setMuted( _this.attribute( "muted" ).toInt() );
|
||||
setStartTimeOffset( _this.attribute( "off" ).toInt() );
|
||||
|
||||
if ( _this.hasAttribute( "sample_rate" ) ) {
|
||||
m_sampleBuffer->setSampleRate( _this.attribute( "sample_rate" ).toInt() );
|
||||
}
|
||||
|
||||
if( _this.hasAttribute( "color" ) )
|
||||
{
|
||||
useCustomClipColor( true );
|
||||
setColor( _this.attribute( "color" ) );
|
||||
}
|
||||
|
||||
if(_this.hasAttribute("reversed"))
|
||||
{
|
||||
m_sampleBuffer->setReversed(true);
|
||||
emit wasReversed(); // tell SampleTCOView to update the view
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TrackContentObjectView * SampleTCO::createView( TrackView * _tv )
|
||||
{
|
||||
return new SampleTCOView( this, _tv );
|
||||
}
|
||||
@@ -33,6 +33,9 @@ SET(LMMS_SRCS
|
||||
gui/PianoView.cpp
|
||||
gui/PluginBrowser.cpp
|
||||
gui/RowTableView.cpp
|
||||
gui/SampleTCOView.cpp
|
||||
gui/SampleTrackView.cpp
|
||||
gui/SampleTrackWindow.cpp
|
||||
gui/SetupDialog.cpp
|
||||
gui/StringPairDrag.cpp
|
||||
gui/SubWindow.cpp
|
||||
|
||||
410
src/gui/SampleTCOView.cpp
Normal file
410
src/gui/SampleTCOView.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* SampleTCOView.cpp
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SampleTCOView.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
|
||||
#include "embed.h"
|
||||
#include "gui_templates.h"
|
||||
#include "PathUtil.h"
|
||||
#include "Song.h"
|
||||
#include "StringPairDrag.h"
|
||||
#include "ToolTip.h"
|
||||
|
||||
SampleTCOView::SampleTCOView( SampleTCO * _tco, TrackView * _tv ) :
|
||||
TrackContentObjectView( _tco, _tv ),
|
||||
m_tco( _tco ),
|
||||
m_paintPixmap()
|
||||
{
|
||||
// update UI and tooltip
|
||||
updateSample();
|
||||
|
||||
// track future changes of SampleTCO
|
||||
connect(m_tco, SIGNAL(sampleChanged()), this, SLOT(updateSample()));
|
||||
|
||||
connect(m_tco, SIGNAL(wasReversed()), this, SLOT(update()));
|
||||
|
||||
setStyle( QApplication::style() );
|
||||
}
|
||||
|
||||
void SampleTCOView::updateSample()
|
||||
{
|
||||
update();
|
||||
// set tooltip to filename so that user can see what sample this
|
||||
// sample-tco contains
|
||||
ToolTip::add( this, ( m_tco->m_sampleBuffer->audioFile() != "" ) ?
|
||||
PathUtil::toAbsolute(m_tco->m_sampleBuffer->audioFile()) :
|
||||
tr( "Double-click to open sample" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::contextMenuEvent( QContextMenuEvent * _cme )
|
||||
{
|
||||
// Depending on whether we right-clicked a selection or an individual TCO we will have
|
||||
// different labels for the actions.
|
||||
bool individualTCO = getClickedTCOs().size() <= 1;
|
||||
|
||||
if( _cme->modifiers() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu contextMenu( this );
|
||||
|
||||
if( fixedTCOs() == false )
|
||||
{
|
||||
contextMenu.addAction(
|
||||
embed::getIconPixmap( "cancel" ),
|
||||
individualTCO
|
||||
? tr("Delete (middle mousebutton)")
|
||||
: tr("Delete selection (middle mousebutton)"),
|
||||
[this](){ contextMenuAction( Remove ); } );
|
||||
|
||||
contextMenu.addSeparator();
|
||||
|
||||
contextMenu.addAction(
|
||||
embed::getIconPixmap( "edit_cut" ),
|
||||
individualTCO
|
||||
? tr("Cut")
|
||||
: tr("Cut selection"),
|
||||
[this](){ contextMenuAction( Cut ); } );
|
||||
}
|
||||
|
||||
contextMenu.addAction(
|
||||
embed::getIconPixmap( "edit_copy" ),
|
||||
individualTCO
|
||||
? tr("Copy")
|
||||
: tr("Copy selection"),
|
||||
[this](){ contextMenuAction( Copy ); } );
|
||||
|
||||
contextMenu.addAction(
|
||||
embed::getIconPixmap( "edit_paste" ),
|
||||
tr( "Paste" ),
|
||||
[this](){ contextMenuAction( Paste ); } );
|
||||
|
||||
contextMenu.addSeparator();
|
||||
|
||||
contextMenu.addAction(
|
||||
embed::getIconPixmap( "muted" ),
|
||||
(individualTCO
|
||||
? tr("Mute/unmute (<%1> + middle click)")
|
||||
: tr("Mute/unmute selection (<%1> + middle click)")).arg(UI_CTRL_KEY),
|
||||
[this](){ contextMenuAction( Mute ); } );
|
||||
|
||||
/*contextMenu.addAction( embed::getIconPixmap( "record" ),
|
||||
tr( "Set/clear record" ),
|
||||
m_tco, SLOT( toggleRecord() ) );*/
|
||||
|
||||
contextMenu.addAction(
|
||||
embed::getIconPixmap("flip_x"),
|
||||
tr("Reverse sample"),
|
||||
this,
|
||||
SLOT(reverseSample())
|
||||
);
|
||||
|
||||
contextMenu.addSeparator();
|
||||
|
||||
contextMenu.addAction( embed::getIconPixmap( "colorize" ),
|
||||
tr( "Set clip color" ), this, SLOT( changeClipColor() ) );
|
||||
contextMenu.addAction( embed::getIconPixmap( "colorize" ),
|
||||
tr( "Use track color" ), this, SLOT( useTrackColor() ) );
|
||||
|
||||
constructContextMenu( &contextMenu );
|
||||
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
if( StringPairDrag::processDragEnterEvent( _dee,
|
||||
"samplefile,sampledata" ) == false )
|
||||
{
|
||||
TrackContentObjectView::dragEnterEvent( _dee );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
if( StringPairDrag::decodeKey( _de ) == "samplefile" )
|
||||
{
|
||||
m_tco->setSampleFile( StringPairDrag::decodeValue( _de ) );
|
||||
_de->accept();
|
||||
}
|
||||
else if( StringPairDrag::decodeKey( _de ) == "sampledata" )
|
||||
{
|
||||
m_tco->m_sampleBuffer->loadFromBase64(
|
||||
StringPairDrag::decodeValue( _de ) );
|
||||
m_tco->updateLength();
|
||||
update();
|
||||
_de->accept();
|
||||
Engine::getSong()->setModified();
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackContentObjectView::dropEvent( _de );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton &&
|
||||
_me->modifiers() & Qt::ControlModifier &&
|
||||
_me->modifiers() & Qt::ShiftModifier )
|
||||
{
|
||||
m_tco->toggleRecord();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( _me->button() == Qt::MiddleButton && _me->modifiers() == Qt::ControlModifier )
|
||||
{
|
||||
SampleTCO * sTco = dynamic_cast<SampleTCO*>( getTrackContentObject() );
|
||||
if( sTco )
|
||||
{
|
||||
sTco->updateTrackTcos();
|
||||
}
|
||||
}
|
||||
TrackContentObjectView::mousePressEvent( _me );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::mouseReleaseEvent(QMouseEvent *_me)
|
||||
{
|
||||
if( _me->button() == Qt::MiddleButton && !_me->modifiers() )
|
||||
{
|
||||
SampleTCO * sTco = dynamic_cast<SampleTCO*>( getTrackContentObject() );
|
||||
if( sTco )
|
||||
{
|
||||
sTco->playbackPositionChanged();
|
||||
}
|
||||
}
|
||||
TrackContentObjectView::mouseReleaseEvent( _me );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
QString af = m_tco->m_sampleBuffer->openAudioFile();
|
||||
|
||||
if ( af.isEmpty() ) {} //Don't do anything if no file is loaded
|
||||
else if ( af == m_tco->m_sampleBuffer->audioFile() )
|
||||
{ //Instead of reloading the existing file, just reset the size
|
||||
int length = (int) ( m_tco->m_sampleBuffer->frames() / Engine::framesPerTick() );
|
||||
m_tco->changeLength(length);
|
||||
}
|
||||
else
|
||||
{ //Otherwise load the new file as ususal
|
||||
m_tco->setSampleFile( af );
|
||||
Engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::paintEvent( QPaintEvent * pe )
|
||||
{
|
||||
QPainter painter( this );
|
||||
|
||||
if( !needsUpdate() )
|
||||
{
|
||||
painter.drawPixmap( 0, 0, m_paintPixmap );
|
||||
return;
|
||||
}
|
||||
|
||||
setNeedsUpdate( false );
|
||||
|
||||
if (m_paintPixmap.isNull() || m_paintPixmap.size() != size())
|
||||
{
|
||||
m_paintPixmap = QPixmap(size());
|
||||
}
|
||||
|
||||
QPainter p( &m_paintPixmap );
|
||||
|
||||
bool muted = m_tco->getTrack()->isMuted() || m_tco->isMuted();
|
||||
bool selected = isSelected();
|
||||
|
||||
QLinearGradient lingrad(0, 0, 0, height());
|
||||
QColor c = painter.background().color();
|
||||
if (muted) { c = c.darker(150); }
|
||||
if (selected) { c = c.darker(150); }
|
||||
|
||||
lingrad.setColorAt( 1, c.darker( 300 ) );
|
||||
lingrad.setColorAt( 0, c );
|
||||
|
||||
// paint a black rectangle under the pattern to prevent glitches with transparent backgrounds
|
||||
p.fillRect( rect(), QColor( 0, 0, 0 ) );
|
||||
|
||||
if( gradient() )
|
||||
{
|
||||
p.fillRect( rect(), lingrad );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.fillRect( rect(), c );
|
||||
}
|
||||
|
||||
auto tcoColor = m_tco->hasColor()
|
||||
? (m_tco->usesCustomClipColor()
|
||||
? m_tco->color()
|
||||
: m_tco->getTrack()->color())
|
||||
: painter.pen().brush().color();
|
||||
|
||||
p.setPen(tcoColor);
|
||||
|
||||
if (muted)
|
||||
{
|
||||
QColor penColor = p.pen().brush().color();
|
||||
penColor.setHsv(penColor.hsvHue(), penColor.hsvSaturation() / 4, penColor.value());
|
||||
p.setPen(penColor.darker(250));
|
||||
}
|
||||
if (selected)
|
||||
{
|
||||
p.setPen(p.pen().brush().color().darker(150));
|
||||
}
|
||||
|
||||
const int spacing = TCO_BORDER_WIDTH + 1;
|
||||
const float ppb = fixedTCOs() ?
|
||||
( parentWidget()->width() - 2 * TCO_BORDER_WIDTH )
|
||||
/ (float) m_tco->length().getBar() :
|
||||
pixelsPerBar();
|
||||
|
||||
float nom = Engine::getSong()->getTimeSigModel().getNumerator();
|
||||
float den = Engine::getSong()->getTimeSigModel().getDenominator();
|
||||
float ticksPerBar = DefaultTicksPerBar * nom / den;
|
||||
|
||||
float offset = m_tco->startTimeOffset() / ticksPerBar * pixelsPerBar();
|
||||
QRect r = QRect( TCO_BORDER_WIDTH + offset, spacing,
|
||||
qMax( static_cast<int>( m_tco->sampleLength() * ppb / ticksPerBar ), 1 ), rect().bottom() - 2 * spacing );
|
||||
m_tco->m_sampleBuffer->visualize( p, r, pe->rect() );
|
||||
|
||||
QString name = PathUtil::cleanName(m_tco->m_sampleBuffer->audioFile());
|
||||
paintTextLabel(name, p);
|
||||
|
||||
// disable antialiasing for borders, since its not needed
|
||||
p.setRenderHint( QPainter::Antialiasing, false );
|
||||
|
||||
// inner border
|
||||
p.setPen( c.lighter( 135 ) );
|
||||
p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH,
|
||||
rect().bottom() - TCO_BORDER_WIDTH );
|
||||
|
||||
// outer border
|
||||
p.setPen( c.darker( 200 ) );
|
||||
p.drawRect( 0, 0, rect().right(), rect().bottom() );
|
||||
|
||||
// draw the 'muted' pixmap only if the pattern was manualy muted
|
||||
if( m_tco->isMuted() )
|
||||
{
|
||||
const int spacing = TCO_BORDER_WIDTH;
|
||||
const int size = 14;
|
||||
p.drawPixmap( spacing, height() - ( size + spacing ),
|
||||
embed::getIconPixmap( "muted", size, size ) );
|
||||
}
|
||||
|
||||
if ( m_marker )
|
||||
{
|
||||
p.drawLine(m_markerPos, rect().bottom(), m_markerPos, rect().top());
|
||||
}
|
||||
// recording sample tracks is not possible at the moment
|
||||
|
||||
/* if( m_tco->isRecord() )
|
||||
{
|
||||
p.setFont( pointSize<7>( p.font() ) );
|
||||
|
||||
p.setPen( textShadowColor() );
|
||||
p.drawText( 10, p.fontMetrics().height()+1, "Rec" );
|
||||
p.setPen( textColor() );
|
||||
p.drawText( 9, p.fontMetrics().height(), "Rec" );
|
||||
|
||||
p.setBrush( QBrush( textColor() ) );
|
||||
p.drawEllipse( 4, 5, 4, 4 );
|
||||
}*/
|
||||
|
||||
p.end();
|
||||
|
||||
painter.drawPixmap( 0, 0, m_paintPixmap );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTCOView::reverseSample()
|
||||
{
|
||||
m_tco->sampleBuffer()->setReversed(!m_tco->sampleBuffer()->reversed());
|
||||
Engine::getSong()->setModified();
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//! Split this TCO.
|
||||
/*! \param pos the position of the split, relative to the start of the clip */
|
||||
bool SampleTCOView::splitTCO( const TimePos pos )
|
||||
{
|
||||
setMarkerEnabled( false );
|
||||
|
||||
const TimePos splitPos = m_initialTCOPos + pos;
|
||||
|
||||
//Don't split if we slid off the TCO or if we're on the clip's start/end
|
||||
//Cutting at exactly the start/end position would create a zero length
|
||||
//clip (bad), and a clip the same length as the original one (pointless).
|
||||
if ( splitPos > m_initialTCOPos && splitPos < m_initialTCOEnd )
|
||||
{
|
||||
m_tco->getTrack()->addJournalCheckPoint();
|
||||
m_tco->getTrack()->saveJournallingState( false );
|
||||
|
||||
SampleTCO * rightTCO = new SampleTCO ( *m_tco );
|
||||
|
||||
m_tco->changeLength( splitPos - m_initialTCOPos );
|
||||
|
||||
rightTCO->movePosition( splitPos );
|
||||
rightTCO->changeLength( m_initialTCOEnd - splitPos );
|
||||
rightTCO->setStartTimeOffset( m_tco->startTimeOffset() - m_tco->length() );
|
||||
|
||||
m_tco->getTrack()->restoreJournallingState();
|
||||
return true;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
231
src/gui/SampleTrackView.cpp
Normal file
231
src/gui/SampleTrackView.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* SampleTrackView.cpp
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SampleTrackView.h"
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
#include "embed.h"
|
||||
#include "Engine.h"
|
||||
#include "FxMixerView.h"
|
||||
#include "gui_templates.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "Knob.h"
|
||||
#include "MainWindow.h"
|
||||
#include "SampleTrackWindow.h"
|
||||
#include "StringPairDrag.h"
|
||||
#include "TrackContainerView.h"
|
||||
#include "TrackLabelButton.h"
|
||||
|
||||
|
||||
SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) :
|
||||
TrackView( _t, tcv )
|
||||
{
|
||||
setFixedHeight( 32 );
|
||||
|
||||
m_tlb = new TrackLabelButton(this, getTrackSettingsWidget());
|
||||
m_tlb->setCheckable(true);
|
||||
connect(m_tlb, SIGNAL(clicked( bool )),
|
||||
this, SLOT(showEffects()));
|
||||
m_tlb->setIcon(embed::getIconPixmap("sample_track"));
|
||||
m_tlb->move(3, 1);
|
||||
m_tlb->show();
|
||||
|
||||
m_volumeKnob = new Knob( knobSmall_17, getTrackSettingsWidget(),
|
||||
tr( "Track volume" ) );
|
||||
m_volumeKnob->setVolumeKnob( true );
|
||||
m_volumeKnob->setModel( &_t->m_volumeModel );
|
||||
m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" );
|
||||
|
||||
int settingsWidgetWidth = ConfigManager::inst()->
|
||||
value( "ui", "compacttrackbuttons" ).toInt()
|
||||
? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT
|
||||
: DEFAULT_SETTINGS_WIDGET_WIDTH;
|
||||
m_volumeKnob->move( settingsWidgetWidth - 2 * 24, 2 );
|
||||
m_volumeKnob->setLabel( tr( "VOL" ) );
|
||||
m_volumeKnob->show();
|
||||
|
||||
m_panningKnob = new Knob( knobSmall_17, getTrackSettingsWidget(),
|
||||
tr( "Panning" ) );
|
||||
m_panningKnob->setModel( &_t->m_panningModel );
|
||||
m_panningKnob->setHintText( tr( "Panning:" ), "%" );
|
||||
m_panningKnob->move( settingsWidgetWidth - 24, 2 );
|
||||
m_panningKnob->setLabel( tr( "PAN" ) );
|
||||
m_panningKnob->show();
|
||||
|
||||
m_activityIndicator = new FadeButton(
|
||||
QApplication::palette().color(QPalette::Active, QPalette::Background),
|
||||
QApplication::palette().color(QPalette::Active, QPalette::BrightText),
|
||||
QApplication::palette().color(QPalette::Active, QPalette::BrightText).darker(),
|
||||
getTrackSettingsWidget()
|
||||
);
|
||||
m_activityIndicator->setGeometry(settingsWidgetWidth - 2 * 24 - 11, 2, 8, 28);
|
||||
m_activityIndicator->show();
|
||||
connect(_t, SIGNAL(playingChanged()), this, SLOT(updateIndicator()));
|
||||
|
||||
setModel( _t );
|
||||
|
||||
m_window = new SampleTrackWindow(this);
|
||||
m_window->toggleVisibility(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTrackView::updateIndicator()
|
||||
{
|
||||
if (model()->isPlaying()) { m_activityIndicator->activateOnce(); }
|
||||
else { m_activityIndicator->noteEnd(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SampleTrackView::~SampleTrackView()
|
||||
{
|
||||
if(m_window != NULL)
|
||||
{
|
||||
m_window->setSampleTrackView(NULL);
|
||||
m_window->parentWidget()->hide();
|
||||
}
|
||||
m_window = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//FIXME: This is identical to InstrumentTrackView::createFxMenu
|
||||
QMenu * SampleTrackView::createFxMenu(QString title, QString newFxLabel)
|
||||
{
|
||||
int channelIndex = model()->effectChannelModel()->value();
|
||||
|
||||
FxChannel *fxChannel = Engine::fxMixer()->effectChannel(channelIndex);
|
||||
|
||||
// If title allows interpolation, pass channel index and name
|
||||
if (title.contains("%2"))
|
||||
{
|
||||
title = title.arg(channelIndex).arg(fxChannel->m_name);
|
||||
}
|
||||
|
||||
QMenu *fxMenu = new QMenu(title);
|
||||
|
||||
fxMenu->addAction(newFxLabel, this, SLOT(createFxLine()));
|
||||
fxMenu->addSeparator();
|
||||
|
||||
for (int i = 0; i < Engine::fxMixer()->numChannels(); ++i)
|
||||
{
|
||||
FxChannel * currentChannel = Engine::fxMixer()->effectChannel(i);
|
||||
|
||||
if (currentChannel != fxChannel)
|
||||
{
|
||||
const auto index = currentChannel->m_channelIndex;
|
||||
QString label = tr("FX %1: %2").arg(currentChannel->m_channelIndex).arg(currentChannel->m_name);
|
||||
fxMenu->addAction(label, [this, index](){
|
||||
assignFxLine(index);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return fxMenu;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTrackView::showEffects()
|
||||
{
|
||||
m_window->toggleVisibility(m_window->parentWidget()->isHidden());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackView::modelChanged()
|
||||
{
|
||||
SampleTrack * st = castModel<SampleTrack>();
|
||||
m_volumeKnob->setModel(&st->m_volumeModel);
|
||||
|
||||
TrackView::modelChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTrackView::dragEnterEvent(QDragEnterEvent *dee)
|
||||
{
|
||||
StringPairDrag::processDragEnterEvent(dee, QString("samplefile"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTrackView::dropEvent(QDropEvent *de)
|
||||
{
|
||||
QString type = StringPairDrag::decodeKey(de);
|
||||
QString value = StringPairDrag::decodeValue(de);
|
||||
|
||||
if (type == "samplefile")
|
||||
{
|
||||
int trackHeadWidth = ConfigManager::inst()->value("ui", "compacttrackbuttons").toInt()==1
|
||||
? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT
|
||||
: DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH;
|
||||
|
||||
int xPos = de->pos().x() < trackHeadWidth
|
||||
? trackHeadWidth
|
||||
: de->pos().x();
|
||||
|
||||
TimePos tcoPos = trackContainerView()->fixedTCOs()
|
||||
? TimePos(0)
|
||||
: TimePos(((xPos - trackHeadWidth) / trackContainerView()->pixelsPerBar()
|
||||
* TimePos::ticksPerBar()) + trackContainerView()->currentPosition()
|
||||
).quantize(1.0);
|
||||
|
||||
SampleTCO * sTco = static_cast<SampleTCO*>(getTrack()->createTCO(tcoPos));
|
||||
if (sTco) { sTco->setSampleFile(value); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Create and assign a new FX Channel for this track */
|
||||
void SampleTrackView::createFxLine()
|
||||
{
|
||||
int channelIndex = gui->fxMixerView()->addNewChannel();
|
||||
auto channel = Engine::fxMixer()->effectChannel(channelIndex);
|
||||
|
||||
channel->m_name = getTrack()->name();
|
||||
if (getTrack()->useColor()) { channel->setColor (getTrack()->color()); }
|
||||
|
||||
assignFxLine(channelIndex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Assign a specific FX Channel for this track */
|
||||
void SampleTrackView::assignFxLine(int channelIndex)
|
||||
{
|
||||
model()->effectChannelModel()->setValue(channelIndex);
|
||||
|
||||
gui->fxMixerView()->setCurrentFxLine(channelIndex);
|
||||
}
|
||||
265
src/gui/SampleTrackWindow.cpp
Normal file
265
src/gui/SampleTrackWindow.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* SampleTrackWindow.cpp
|
||||
*
|
||||
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SampleTrackWindow.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QMenu>
|
||||
|
||||
#include "embed.h"
|
||||
#include "gui_templates.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "Knob.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Song.h"
|
||||
#include "TabWidget.h"
|
||||
#include "TrackLabelButton.h"
|
||||
|
||||
|
||||
SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) :
|
||||
QWidget(),
|
||||
ModelView(NULL, this),
|
||||
m_track(tv->model()),
|
||||
m_stv(tv)
|
||||
{
|
||||
// init own layout + widgets
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
QVBoxLayout * vlayout = new QVBoxLayout(this);
|
||||
vlayout->setMargin(0);
|
||||
vlayout->setSpacing(0);
|
||||
|
||||
TabWidget* generalSettingsWidget = new TabWidget(tr("GENERAL SETTINGS"), this);
|
||||
|
||||
QVBoxLayout* generalSettingsLayout = new QVBoxLayout(generalSettingsWidget);
|
||||
|
||||
generalSettingsLayout->setContentsMargins(8, 18, 8, 8);
|
||||
generalSettingsLayout->setSpacing(6);
|
||||
|
||||
QWidget* nameWidget = new QWidget(generalSettingsWidget);
|
||||
QHBoxLayout* nameLayout = new QHBoxLayout(nameWidget);
|
||||
nameLayout->setContentsMargins(0, 0, 0, 0);
|
||||
nameLayout->setSpacing(2);
|
||||
|
||||
// setup line edit for changing sample track name
|
||||
m_nameLineEdit = new QLineEdit;
|
||||
m_nameLineEdit->setFont(pointSize<9>(m_nameLineEdit->font()));
|
||||
connect(m_nameLineEdit, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(textChanged(const QString &)));
|
||||
|
||||
m_nameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
|
||||
nameLayout->addWidget(m_nameLineEdit);
|
||||
|
||||
|
||||
generalSettingsLayout->addWidget(nameWidget);
|
||||
|
||||
|
||||
QGridLayout* basicControlsLayout = new QGridLayout;
|
||||
basicControlsLayout->setHorizontalSpacing(3);
|
||||
basicControlsLayout->setVerticalSpacing(0);
|
||||
basicControlsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QString labelStyleSheet = "font-size: 6pt;";
|
||||
Qt::Alignment labelAlignment = Qt::AlignHCenter | Qt::AlignTop;
|
||||
Qt::Alignment widgetAlignment = Qt::AlignHCenter | Qt::AlignCenter;
|
||||
|
||||
// set up volume knob
|
||||
m_volumeKnob = new Knob(knobBright_26, NULL, tr("Sample volume"));
|
||||
m_volumeKnob->setVolumeKnob(true);
|
||||
m_volumeKnob->setHintText(tr("Volume:"), "%");
|
||||
|
||||
basicControlsLayout->addWidget(m_volumeKnob, 0, 0);
|
||||
basicControlsLayout->setAlignment(m_volumeKnob, widgetAlignment);
|
||||
|
||||
QLabel *label = new QLabel(tr("VOL"), this);
|
||||
label->setStyleSheet(labelStyleSheet);
|
||||
basicControlsLayout->addWidget(label, 1, 0);
|
||||
basicControlsLayout->setAlignment(label, labelAlignment);
|
||||
|
||||
|
||||
// set up panning knob
|
||||
m_panningKnob = new Knob(knobBright_26, NULL, tr("Panning"));
|
||||
m_panningKnob->setHintText(tr("Panning:"), "");
|
||||
|
||||
basicControlsLayout->addWidget(m_panningKnob, 0, 1);
|
||||
basicControlsLayout->setAlignment(m_panningKnob, widgetAlignment);
|
||||
|
||||
label = new QLabel(tr("PAN"),this);
|
||||
label->setStyleSheet(labelStyleSheet);
|
||||
basicControlsLayout->addWidget(label, 1, 1);
|
||||
basicControlsLayout->setAlignment(label, labelAlignment);
|
||||
|
||||
|
||||
basicControlsLayout->setColumnStretch(2, 1);
|
||||
|
||||
|
||||
// setup spinbox for selecting FX-channel
|
||||
m_effectChannelNumber = new FxLineLcdSpinBox(2, NULL, tr("FX channel"), m_stv);
|
||||
|
||||
basicControlsLayout->addWidget(m_effectChannelNumber, 0, 3);
|
||||
basicControlsLayout->setAlignment(m_effectChannelNumber, widgetAlignment);
|
||||
|
||||
label = new QLabel(tr("FX"), this);
|
||||
label->setStyleSheet(labelStyleSheet);
|
||||
basicControlsLayout->addWidget(label, 1, 3);
|
||||
basicControlsLayout->setAlignment(label, labelAlignment);
|
||||
|
||||
generalSettingsLayout->addLayout(basicControlsLayout);
|
||||
|
||||
m_effectRack = new EffectRackView(tv->model()->audioPort()->effects());
|
||||
m_effectRack->setFixedSize(EffectRackView::DEFAULT_WIDTH, 242);
|
||||
|
||||
vlayout->addWidget(generalSettingsWidget);
|
||||
vlayout->addWidget(m_effectRack);
|
||||
|
||||
|
||||
setModel(tv->model());
|
||||
|
||||
QMdiSubWindow * subWin = gui->mainWindow()->addWindowedWidget(this);
|
||||
Qt::WindowFlags flags = subWin->windowFlags();
|
||||
flags |= Qt::MSWindowsFixedSizeDialogHint;
|
||||
flags &= ~Qt::WindowMaximizeButtonHint;
|
||||
subWin->setWindowFlags(flags);
|
||||
|
||||
// Hide the Size and Maximize options from the system menu
|
||||
// since the dialog size is fixed.
|
||||
QMenu * systemMenu = subWin->systemMenu();
|
||||
systemMenu->actions().at(2)->setVisible(false); // Size
|
||||
systemMenu->actions().at(4)->setVisible(false); // Maximize
|
||||
|
||||
subWin->setWindowIcon(embed::getIconPixmap("sample_track"));
|
||||
subWin->setFixedSize(subWin->size());
|
||||
subWin->hide();
|
||||
}
|
||||
|
||||
SampleTrackWindow::~SampleTrackWindow()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::setSampleTrackView(SampleTrackView* tv)
|
||||
{
|
||||
if(m_stv && tv)
|
||||
{
|
||||
m_stv->m_tlb->setChecked(false);
|
||||
}
|
||||
|
||||
m_stv = tv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::modelChanged()
|
||||
{
|
||||
m_track = castModel<SampleTrack>();
|
||||
|
||||
m_nameLineEdit->setText(m_track->name());
|
||||
|
||||
m_track->disconnect(SIGNAL(nameChanged()), this);
|
||||
|
||||
connect(m_track, SIGNAL(nameChanged()),
|
||||
this, SLOT(updateName()));
|
||||
|
||||
m_volumeKnob->setModel(&m_track->m_volumeModel);
|
||||
m_panningKnob->setModel(&m_track->m_panningModel);
|
||||
m_effectChannelNumber->setModel(&m_track->m_effectChannelModel);
|
||||
|
||||
updateName();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::updateName()
|
||||
{
|
||||
setWindowTitle(m_track->name().length() > 25 ? (m_track->name().left(24) + "...") : m_track->name());
|
||||
|
||||
if(m_nameLineEdit->text() != m_track->name())
|
||||
{
|
||||
m_nameLineEdit->setText(m_track->name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::textChanged(const QString& new_name)
|
||||
{
|
||||
m_track->setName(new_name);
|
||||
Engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::toggleVisibility(bool on)
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
show();
|
||||
parentWidget()->show();
|
||||
parentWidget()->raise();
|
||||
}
|
||||
else
|
||||
{
|
||||
parentWidget()->hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::closeEvent(QCloseEvent* ce)
|
||||
{
|
||||
ce->ignore();
|
||||
|
||||
if(gui->mainWindow()->workspace())
|
||||
{
|
||||
parentWidget()->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
m_stv->m_tlb->setFocus();
|
||||
m_stv->m_tlb->setChecked(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::saveSettings(QDomDocument& doc, QDomElement & element)
|
||||
{
|
||||
MainWindow::saveWidgetState(this, element);
|
||||
Q_UNUSED(element)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SampleTrackWindow::loadSettings(const QDomElement& element)
|
||||
{
|
||||
MainWindow::restoreWidgetState(this, element);
|
||||
if(isVisible())
|
||||
{
|
||||
m_stv->m_tlb->setChecked(true);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user