Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0b1ee3c
Add export options in context menus
sakertooth Dec 10, 2025
43413e6
Only implement exporting tracks
sakertooth Dec 10, 2025
f78a6e0
Add file dialog for exporting tracks
sakertooth Dec 11, 2025
0c17ffa
Add new export track mode
sakertooth Dec 11, 2025
5f6c17f
Implement single track export
sakertooth Dec 12, 2025
8c72d9c
Add space
sakertooth Dec 12, 2025
d14eea4
Merge remote-tracking branch 'upstream' into bounce-track
sakertooth Jan 8, 2026
45de87f
Merge remote-tracking branch 'upstream' into bounce-track
sakertooth Jan 16, 2026
1d935c1
Merge remote-tracking branch 'upstream' into bounce-track
sakertooth Jan 28, 2026
3514a49
Merge remote-tracking branch 'upstream' into bounce-track
sakertooth Feb 3, 2026
aedf7ac
Add asserts in RenderManager::renderTrack, iterate only through the t…
sakertooth Feb 3, 2026
dec4aa9
Move export mode back into the dialog
sakertooth Feb 5, 2026
8ce1268
Use setter for track instead of passing it in the constructor
sakertooth Feb 5, 2026
260c835
Fix formatting
sakertooth Feb 5, 2026
22cae77
Refactor RenderManager to use a queue-based system
sakertooth Feb 6, 2026
b5d805e
Add imported exported track checkbox
sakertooth Feb 6, 2026
6db8c5b
Import exported track as a new sample track
sakertooth Feb 6, 2026
b582dfe
Use factory methods for export dialog modes
sakertooth Mar 7, 2026
43881b8
Add assert to ensure we are in single track mode
sakertooth Mar 7, 2026
26829f2
Import exported track only if the dialog was accepted
sakertooth Mar 7, 2026
5415307
Remove use of std::views::filter, use if statement
sakertooth Mar 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/AutomationTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class AutomationTrack : public Track
void saveTrackSpecificSettings(QDomDocument& doc, QDomElement& parent, bool presetMode) override;
void loadTrackSpecificSettings( const QDomElement & _this ) override;

bool isRenderable() override { return false; }

private:
friend class AutomationTrackView;

Expand Down
15 changes: 13 additions & 2 deletions include/ExportProjectDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,24 @@ namespace lmms::gui {
class ExportProjectDialog : public QDialog
{
public:
static ExportProjectDialog* exportProjectDialog(const QString& path);
static ExportProjectDialog* exportTracksDialog(const QString& path);
static ExportProjectDialog* exportTrackDialog(const QString& path, Track* track);

//! @returns `true` if the exported track should be imported as a sample track, `false` otherwise
//! @note only applies when exporting a single track
bool importExportedTrack();

private:
enum class Mode
{
ExportProject,
ExportTracks,
ExportTrack
};

ExportProjectDialog(const QString& path, Mode mode, QWidget* parent = nullptr);
ExportProjectDialog(const QString& path, Mode mode, Track* track = nullptr, QWidget* parent = nullptr);

private:
void accept() override;
void reject() override;
void onFileFormatChanged(int index);
Expand Down Expand Up @@ -82,6 +91,7 @@ class ExportProjectDialog : public QDialog

QCheckBox* m_exportAsLoopBox = nullptr;
QCheckBox* m_exportBetweenLoopMarkersBox = nullptr;
QCheckBox* m_importExportedTrackBox = nullptr;
QLabel* m_loopRepeatLabel = nullptr;
QSpinBox* m_loopRepeatBox = nullptr;
QPushButton* m_startButton = nullptr;
Expand All @@ -90,6 +100,7 @@ class ExportProjectDialog : public QDialog

QString m_path;
Mode m_mode;
Track* m_track = nullptr;
std::unique_ptr<RenderManager> m_renderManager;
};

Expand Down
2 changes: 2 additions & 0 deletions include/InstrumentTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ class LMMS_EXPORT InstrumentTrack : public Track, public MidiEventProcessor

void autoAssignMidiDevice( bool );

bool isRenderable() override { return true; }

signals:
void instrumentChanged();
void midiNoteOn( const lmms::Note& );
Expand Down
2 changes: 2 additions & 0 deletions include/PatternTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class LMMS_EXPORT PatternTrack : public Track
m_disabledTracks.removeAll( _track );
}

bool isRenderable() override { return true; }

protected:
inline QString nodeName() const override
{
Expand Down
33 changes: 21 additions & 12 deletions include/RenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define LMMS_RENDER_MANAGER_H

#include <memory>
#include <queue>

#include "ProjectRenderer.h"
#include "OutputSettings.h"
Expand All @@ -40,15 +41,17 @@ class RenderManager : public QObject
{
Q_OBJECT
public:
RenderManager(const OutputSettings& outputSettings, ProjectRenderer::ExportFileFormat fmt, QString outputPath);

RenderManager(const OutputSettings& outputSettings, ProjectRenderer::ExportFileFormat fmt);
~RenderManager() override;

/// Export all unmuted tracks into a single file
void renderProject();
void renderProject(const QString& outputPath);

/// Export all unmuted tracks into individual file
void renderTracks();
void renderTracks(const QString& outputPath);

/// Export a a track into a single file
void renderTrack(Track* track, const QString& outputPath);

void abortProcessing();

Expand All @@ -57,23 +60,29 @@ class RenderManager : public QObject
void finished();

private slots:
void renderNextTrack();
void updateConsoleProgress();

private:
QString pathForTrack( const Track *track, int num );
void restoreMutedState();
struct RenderJob
{
QString path;
std::vector<Track*> tracksToRender;
};

void render( QString outputPath );
void render();
void startRender();
void renderFinished();

void storeMuteStates();
void restoreMuteStates();

const OutputSettings m_outputSettings;
ProjectRenderer::ExportFileFormat m_format;
QString m_outputPath;

std::unique_ptr<ProjectRenderer> m_activeRenderer;

std::vector<Track*> m_tracksToRender;
std::vector<Track*> m_unmuted;
std::queue<RenderJob> m_renderJobQueue;
std::unordered_map<Track*, bool> m_muteStates;
int m_totalRenderJobs = 0;
} ;


Expand Down
2 changes: 2 additions & 0 deletions include/SampleTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class SampleTrack : public Track
m_isPlaying = playing;
}

bool isRenderable() override { return true; }

signals:
void playingChanged();

Expand Down
3 changes: 3 additions & 0 deletions include/Track.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class LMMS_EXPORT Track : public Model, public JournallingObject
virtual void saveTrackSpecificSettings(QDomDocument& doc, QDomElement& parent, bool presetMode) = 0;
virtual void loadTrackSpecificSettings( const QDomElement & element ) = 0;

//! @returns `true` if the track is renderable (i.e., it can be exported to audio), returns `false` otherwise
virtual bool isRenderable() = 0;

// Saving and loading of presets which do not necessarily contain all the track information
void savePreset(QDomDocument & doc, QDomElement & element);
void loadPreset(const QDomElement & element);
Expand Down
5 changes: 4 additions & 1 deletion include/TrackContainerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ class TrackContainerView : public QWidget, public ModelView,

public slots:
void realignTracks();
lmms::gui::TrackView * createTrackView( lmms::Track * _t );

//! Creates a track view for @a t if one doesn't exist already.
//! Otherwise, the already existing track view for @a t is returned.
lmms::gui::TrackView* createTrackView(lmms::Track* _t);
void deleteTrackView( lmms::gui::TrackView * _tv );

void dropEvent( QDropEvent * _de ) override;
Expand Down
1 change: 1 addition & 0 deletions include/TrackOperationsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ private slots:
void recordingOn();
void recordingOff();
void clearTrack();
void exportTrack();

private:
TrackView * m_trackView;
Expand Down
Loading
Loading