From e863df7171f8a81cc75c511f19b35c492f5ff391 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Tue, 1 Sep 2015 13:26:32 -0400 Subject: [PATCH 1/8] Add ProjectRenderer::getFileExtensionFromFormat. Currently ProjectRenderer has a helper getFileFormatFromExtension, this adds a similar helper getFileExtensionFromFormat. This will, for example, return "ogg" for OggFile. --- include/ProjectRenderer.h | 3 ++- src/core/ProjectRenderer.cpp | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index 08f3a8ab6..394c3b0fd 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -87,8 +87,9 @@ public: static ExportFileFormats getFileFormatFromExtension( const QString & _ext ); - static const FileEncodeDevice fileEncodeDevices[]; + static QString getFileExtensionFromFormat( ExportFileFormats _fmt ); + static const FileEncodeDevice fileEncodeDevices[]; public slots: void startProcessing(); diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index a05ce6c9c..581fb5ba4 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -124,6 +124,15 @@ ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension( +QString ProjectRenderer::getFileExtensionFromFormat( + ExportFileFormats _fmt ) +{ + return fileEncodeDevices[_fmt].m_extension; +} + + + + void ProjectRenderer::startProcessing() { From 1a2263510955ab102d93c829be1c07cb35f8fcf2 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Tue, 1 Sep 2015 13:45:45 -0400 Subject: [PATCH 2/8] Initial implementation of RenderManager. Much of the multi-track rendering logic was intermixed with GUI code in ExportProjectDialog. This creates the RenderManager class to provide rendering logic that could be shared between the CLI and GUI interfaces. --- include/RenderManager.h | 76 +++++++++++++ src/core/CMakeLists.txt | 1 + src/core/RenderManager.cpp | 214 +++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 include/RenderManager.h create mode 100644 src/core/RenderManager.cpp diff --git a/include/RenderManager.h b/include/RenderManager.h new file mode 100644 index 000000000..2bd35d3b6 --- /dev/null +++ b/include/RenderManager.h @@ -0,0 +1,76 @@ +/* + * RenderManager.h - Provides a uniform interface for rendering the project or + * individual tracks for the CLI and GUI. + * + * Copyright (c) 2015 Ryan Roden-Corrent + * + * This file is part of LMMS - http://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 RENDER_MANAGER_H +#define RENDER_MANAGER_H + +#include + +#include "ProjectRenderer.h" + +class RenderManager : public QObject +{ + Q_OBJECT +public: + RenderManager( + const Mixer::qualitySettings & qualitySettings, + const ProjectRenderer::OutputSettings & outputSettings, + ProjectRenderer::ExportFileFormats fmt, + QString outputPath); + + virtual ~RenderManager(); + + /// Export all unmuted tracks into a single file + void renderProject(); + + /// Export all unmuted tracks into individual file + void renderTracks(); + + void abortProcessing(); + +signals: + void progressChanged( int ); + void finished(); + +private slots: + void renderNextTrack(); + void updateConsoleProgress(); + +private: + QString pathForTrack( const Track *track, int num ); + void restoreMutedState(); + + const Mixer::qualitySettings m_qualitySettings; + const ProjectRenderer::OutputSettings m_outputSettings; + ProjectRenderer::ExportFileFormats m_format; + QString m_outputPath; + + ProjectRenderer* m_activeRenderer; + + QVector m_tracksToRender; + QVector m_unmuted; +} ; + +#endif diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index adc6ef3a9..082951d34 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -51,6 +51,7 @@ set(LMMS_SRCS core/ProjectRenderer.cpp core/ProjectVersion.cpp core/RemotePlugin.cpp + core/RenderManager.cpp core/RingBuffer.cpp core/SampleBuffer.cpp core/SamplePlayHandle.cpp diff --git a/src/core/RenderManager.cpp b/src/core/RenderManager.cpp new file mode 100644 index 000000000..2808aa39d --- /dev/null +++ b/src/core/RenderManager.cpp @@ -0,0 +1,214 @@ +/* + * RenderManager - exporting logic common between the CLI and GUI. + * + * Copyright (c) 2015 Ryan Roden-Corrent + * + * This file is part of LMMS - http://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 +#include +#include + +#include "RenderManager.h" +#include "Song.h" +#include "BBTrackContainer.h" +#include "BBTrack.h" +#include "debug.h" + +RenderManager::RenderManager( + const Mixer::qualitySettings & qualitySettings, + const ProjectRenderer::OutputSettings & outputSettings, + ProjectRenderer::ExportFileFormats fmt, + QString outputPath) : + m_qualitySettings(qualitySettings), + m_outputSettings(outputSettings), + m_format(fmt), + m_outputPath(outputPath), + m_activeRenderer(NULL) +{ +} + +RenderManager::~RenderManager() +{ + delete m_activeRenderer; +} + +void RenderManager::abortProcessing() +{ + if ( m_activeRenderer ) { + m_activeRenderer->abortProcessing(); + } + restoreMutedState(); +} + +// Called to render each new track when rendering tracks individually. +void RenderManager::renderNextTrack() +{ + delete m_activeRenderer; + m_activeRenderer = NULL; + + if( m_tracksToRender.isEmpty() ) + { + // nothing left to render + restoreMutedState(); + emit finished(); + } + else + { + // pop the next track from our rendering queue + Track* renderTrack = m_tracksToRender.back(); + m_tracksToRender.pop_back(); + + // mute everything but the track we are about to render + for( auto it = m_unmuted.begin(); it != m_unmuted.end(); ++it ) + { + (*it)->setMuted( (*it) != renderTrack ); + } + + // for multi-render, prefix each output file with a different number + int trackNum = m_tracksToRender.size() + 1; + + // create a renderer for this track + m_activeRenderer = new ProjectRenderer( + m_qualitySettings, + m_outputSettings, + m_format, + pathForTrack(renderTrack, trackNum)); + + if ( m_activeRenderer->isReady() ) + { + // pass progress signals through + connect( m_activeRenderer, SIGNAL( progressChanged( int ) ), + this, SIGNAL( progressChanged( int ) ) ); + + // when it is finished, render the next track + connect( m_activeRenderer, SIGNAL( finished() ), + this, SLOT( renderNextTrack() ) ); + + m_activeRenderer->startProcessing(); + } + else + { + qDebug( "Renderer failed to acquire a file device!" ); + renderNextTrack(); + } + } +} + +// Render the song into individual tracks +void RenderManager::renderTracks() +{ + const TrackContainer::TrackList & tl = Engine::getSong()->tracks(); + + // find all currently unnmuted tracks -- we want to render these. + for( auto 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); + } + } + + const TrackContainer::TrackList t2 = Engine::getBBTrackContainer()->tracks(); + for( auto it = t2.begin(); it != t2.end(); ++it ) + { + Track* tk = (*it); + if ( tk->isMuted() == false ) + { + m_unmuted.push_back(tk); + } + } + + // copy the list of unmuted tracks into our rendering queue. + // we need to remember which tracks were unmuted to restore state at the end. + m_tracksToRender = m_unmuted; + + renderNextTrack(); +} + +// Render the song into a single track +void RenderManager::renderProject() +{ + m_activeRenderer = new ProjectRenderer( + m_qualitySettings, + m_outputSettings, + m_format, + m_outputPath); + + if( m_activeRenderer->isReady() ) + { + // pass progress signals through + connect( m_activeRenderer, SIGNAL( progressChanged( int ) ), + this, SIGNAL( progressChanged( int ) ) ); + + // as we have not queued any tracks, renderNextTrack will just clean up + connect( m_activeRenderer, SIGNAL( finished() ), + this, SLOT( renderNextTrack() ) ); + + m_activeRenderer->startProcessing(); + } + else + { + qDebug( "Renderer failed to acquire a file device!" ); + emit finished(); + } +} + +// Unmute all tracks that were muted while rendering tracks +void RenderManager::restoreMutedState() +{ + while( !m_unmuted.isEmpty() ) + { + Track* restoreTrack = m_unmuted.back(); + m_unmuted.pop_back(); + restoreTrack->setMuted( false ); + } +} + +// Determine the output path for a track when rendering tracks individually +QString RenderManager::pathForTrack(const Track *track, int num) +{ + QString extension = ProjectRenderer::getFileExtensionFromFormat( m_format ); + QString name = track->name(); + name = name.remove(QRegExp("[^a-zA-Z]")); + name = QString( "%1_%2%3" ).arg( num ).arg( name ).arg( extension ); + return QDir(m_outputPath).filePath(name); +} + +void RenderManager::updateConsoleProgress() +{ + if ( m_activeRenderer ) + { + m_activeRenderer->updateConsoleProgress(); + + int totalNum = m_unmuted.size(); + if ( totalNum > 0 ) + { + // we are rendering multiple tracks, append a track counter to the output + int trackNum = totalNum - m_tracksToRender.size(); + fprintf( stderr, "(%d/%d)", trackNum, totalNum ); + } + } +} From c4622614335f36152ed4f05cdc5f94f07b5ee67c Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Wed, 2 Sep 2015 13:00:00 -0400 Subject: [PATCH 3/8] Use RenderManager in ExportProjectDialog. Remove the rendering logic from the gui code in ExportProjectDialog and let RenderManger handle it instead. This is part of an effort to allow the CLI and the GUI to share the same rendering logic, setting the state for a --render-tracks CLI option similiar to the "Export Tracks" GUI option. --- include/ExportProjectDialog.h | 15 +-- src/gui/ExportProjectDialog.cpp | 186 +++++--------------------------- 2 files changed, 32 insertions(+), 169 deletions(-) diff --git a/include/ExportProjectDialog.h b/include/ExportProjectDialog.h index 46ab7fdb2..dfab28561 100644 --- a/include/ExportProjectDialog.h +++ b/include/ExportProjectDialog.h @@ -32,7 +32,7 @@ #include "ui_export_project.h" #include "ProjectRenderer.h" - +#include "RenderManager.h" class ExportProjectDialog : public QDialog, public Ui::ExportProjectDialog { @@ -50,26 +50,17 @@ protected: private slots: void startBtnClicked( void ); void updateTitleBar( int ); - void render(ProjectRenderer* renderer); - void multiRender(); - ProjectRenderer* prepRender(); - void popRender(); void accept(); + void startExport(); private: QString m_fileName; QString m_dirName; QString m_fileExtension; - typedef QVector RenderVector; - RenderVector m_renderers; bool m_multiExport; - typedef QVector TrackVector; - TrackVector m_unmuted; - TrackVector m_unmutedBB; ProjectRenderer::ExportFileFormats m_ft; - TrackVector m_tracksToRender; - ProjectRenderer* m_activeRenderer; + RenderManager* m_renderManager; } ; #endif diff --git a/src/gui/ExportProjectDialog.cpp b/src/gui/ExportProjectDialog.cpp index d81d6b917..23794db80 100644 --- a/src/gui/ExportProjectDialog.cpp +++ b/src/gui/ExportProjectDialog.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "ExportProjectDialog.h" #include "Song.h" @@ -41,10 +42,10 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name, m_fileName( _file_name ), m_fileExtension(), m_multiExport( multi_export ), - m_activeRenderer( NULL ) + m_renderManager( NULL ) { setupUi( this ); - setWindowTitle( tr( "Export project to %1" ).arg( + setWindowTitle( tr( "Export project to %1" ).arg( QFileInfo( _file_name ).fileName() ) ); // get the extension of the chosen file @@ -80,7 +81,6 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name, connect( startButton, SIGNAL( clicked() ), this, SLOT( startBtnClicked() ) ); - } @@ -88,12 +88,7 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name, ExportProjectDialog::~ExportProjectDialog() { - - for( RenderVector::ConstIterator it = m_renderers.begin(); - it != m_renderers.end(); ++it ) - { - delete (*it); - } + delete m_renderManager; } @@ -101,14 +96,12 @@ ExportProjectDialog::~ExportProjectDialog() void ExportProjectDialog::reject() { - for( RenderVector::ConstIterator it = m_renderers.begin(); it != m_renderers.end(); ++it ) - { - (*it)->abortProcessing(); + if( m_renderManager ) { + m_renderManager->abortProcessing(); } - if( m_activeRenderer ) { - m_activeRenderer->abortProcessing(); - } + delete m_renderManager; + m_renderManager = NULL; QDialog::reject(); } @@ -117,24 +110,10 @@ void ExportProjectDialog::reject() void ExportProjectDialog::accept() { - // If more to render, kick off next render job - if( m_renderers.isEmpty() == false ) - { - popRender(); - } - else - { - // If done, then reset mute states - while( m_unmuted.isEmpty() == false ) - { - Track* restoreTrack = m_unmuted.back(); - m_unmuted.pop_back(); - restoreTrack->setMuted( false ); - } + delete m_renderManager; + m_renderManager = NULL; - QDialog::accept(); - - } + QDialog::accept(); } @@ -142,16 +121,8 @@ void ExportProjectDialog::accept() void ExportProjectDialog::closeEvent( QCloseEvent * _ce ) { - for( RenderVector::ConstIterator it = m_renderers.begin(); it != m_renderers.end(); ++it ) - { - if( (*it)->isRunning() ) - { - (*it)->abortProcessing(); - } - } - - if( m_activeRenderer && m_activeRenderer->isRunning() ) { - m_activeRenderer->abortProcessing(); + if( m_renderManager ) { + m_renderManager->abortProcessing(); } QDialog::closeEvent( _ce ); @@ -159,94 +130,8 @@ void ExportProjectDialog::closeEvent( QCloseEvent * _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 - m_activeRenderer = m_renderers.back(); - m_renderers.pop_back(); - render( m_activeRenderer ); -} - - - -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() +void ExportProjectDialog::startExport() { Mixer::qualitySettings qs = Mixer::qualitySettings( @@ -262,38 +147,33 @@ ProjectRenderer* ExportProjectDialog::prepRender() bitrates[ bitrateCB->currentIndex() ], static_cast( depthCB->currentIndex() ) ); + m_renderManager = new RenderManager( qs, os, m_ft, m_fileName ); + Engine::getSong()->setExportLoop( exportLoopCB->isChecked() ); Engine::getSong()->setRenderBetweenMarkers( renderMarkersCB->isChecked() ); - ProjectRenderer* renderer = new ProjectRenderer( qs, os, m_ft, m_fileName ); + connect( m_renderManager, SIGNAL( progressChanged( int ) ), + progressBar, SLOT( setValue( int ) ) ); + connect( m_renderManager, SIGNAL( progressChanged( int ) ), + this, SLOT( updateTitleBar( int ) )) ; + connect( m_renderManager, SIGNAL( finished() ), + this, SLOT( accept() ) ); + connect( m_renderManager, SIGNAL( finished() ), + gui->mainWindow(), SLOT( resetWindowTitle() ) ); - m_renderers.push_back(renderer); - - return renderer; -} - - - -void ExportProjectDialog::render( ProjectRenderer* renderer ) -{ - - if( renderer->isReady() ) + if ( m_multiExport ) { - 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() ), gui->mainWindow(), SLOT( resetWindowTitle() ) ); - - renderer->startProcessing(); + m_renderManager->renderTracks(); } else { - accept(); + m_renderManager->renderProject(); } } + void ExportProjectDialog::startBtnClicked() { m_ft = ProjectRenderer::NumFileFormats; @@ -325,15 +205,7 @@ void ExportProjectDialog::startBtnClicked() updateTitleBar( 0 ); - if (m_multiExport==true) - { - multiRender(); - } - else - { - prepRender(); - popRender(); - } + startExport(); } From 795d42987f8f383ad9ffd6e488c886c6f9a86fe9 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Thu, 3 Sep 2015 12:20:51 -0400 Subject: [PATCH 4/8] Add --render-tracks CLI command. This command allows rendering each track of a song to a different file. It should provide the same functionality as the "Export Tracks" GUI option. Usage could look like: lmms --render-tracks project.mmpz -f ogg -o output/ --- src/core/main.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index d656c2faf..53e767027 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -66,6 +66,7 @@ #include "ImportFilter.h" #include "MainWindow.h" #include "ProjectRenderer.h" +#include "RenderManager.h" #include "DataFile.h" #include "Song.h" @@ -172,6 +173,7 @@ int main( int argc, char * * argv ) bool exitAfterImport = false; bool allowRoot = false; bool renderLoop = false; + bool renderTracks = false; QString fileToLoad, fileToImport, renderOut, profilerOutputFile; // first of two command-line parsing stages @@ -185,6 +187,11 @@ int main( int argc, char * * argv ) { coreOnly = true; } + else if( arg == "--render-tracks" ) + { + coreOnly = true; + renderTracks = true; + } else if( arg == "--allowroot" ) { allowRoot = true; @@ -288,7 +295,7 @@ int main( int argc, char * * argv ) return EXIT_SUCCESS; } - else if( arg == "--render" || arg == "-r" ) + else if( arg == "--render" || arg == "-r" || arg == "--render-tracks" ) { ++i; @@ -301,7 +308,7 @@ int main( int argc, char * * argv ) fileToLoad = QString::fromLocal8Bit( argv[i] ); - renderOut = baseName( fileToLoad ) + "."; + renderOut = baseName( fileToLoad ); } else if( arg == "--loop" || arg == "-l" ) { @@ -319,7 +326,7 @@ int main( int argc, char * * argv ) } - renderOut = baseName( QString::fromLocal8Bit( argv[i] ) ) + "."; + renderOut = baseName( QString::fromLocal8Bit( argv[i] ) ); } else if( arg == "--format" || arg == "-f" ) { @@ -588,9 +595,15 @@ int main( int argc, char * * argv ) Engine::getSong()->setExportLoop( renderLoop ); + // when rendering multiple tracks, renderOut is a directory + // otherwise, it is a file, so we need to append the file extension + if ( !renderTracks ) + { + renderOut = renderOut + ProjectRenderer::getFileExtensionFromFormat(eff); + } + // create renderer - QString extension = ( eff == ProjectRenderer::WaveFile ) ? "wav" : "ogg"; - ProjectRenderer * r = new ProjectRenderer( qs, os, eff, renderOut + extension ); + RenderManager * r = new RenderManager( qs, os, eff, renderOut ); QCoreApplication::instance()->connect( r, SIGNAL( finished() ), SLOT( quit() ) ); @@ -606,7 +619,14 @@ int main( int argc, char * * argv ) } // start now! - r->startProcessing(); + if ( renderTracks ) + { + r->renderTracks(); + } + else + { + r->renderProject(); + } } else // otherwise, start the GUI { From 6b8406241bc754925f91cbfa1187916a330ca1c7 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Thu, 3 Sep 2015 21:32:21 -0400 Subject: [PATCH 5/8] Document --render-tracks in --help and the manpage. --- doc/lmms.1 | 10 ++++++++-- src/core/main.cpp | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/lmms.1 b/doc/lmms.1 index 45b657fc1..dff6d1a35 100644 --- a/doc/lmms.1 +++ b/doc/lmms.1 @@ -42,8 +42,14 @@ LMMS features components such as a Song Editor, a Beat+Bassline Editor, a Piano .SH OPTIONS .IP "\fB\-r, --render\fP \fIproject-file\fP Render given file to either a wav\- or ogg\-file. See \fB\-f\fP for details -.IP "\fB\-o, --output\fP \fIfile\fP -render into \fIfile\fP +.IP "\fB\-r, --render-tracks\fP \fIproject-file\fP +Render each track into a separate wav\- or ogg\-file. See \fB\-f\fP for details +.IP "\fB\-o, --output\fP \fIpath\fP +Render into \fIpath\fP +.br +For --render, this is interpreted as a file path. +.br +For --render-tracks, this is interpreted as a path to an existing directory. .IP "\fB\-f, --format\fP \fIformat\fP Specify format of render-output where \fIformat\fP is either 'wav' or 'ogg' .IP "\fB\-s, --samplerate\fP \fIsamplerate\fP diff --git a/src/core/main.cpp b/src/core/main.cpp index 53e767027..d02f8805f 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -127,7 +127,10 @@ void printHelp() " [ -h ]\n" " [ ]\n\n" "-r, --render Render given project file\n" - "-o, --output Render into \n" + " --render-tracks Render each track to a different file\n" + "-o, --output Render into \n" + " For --render, provide a file path\n" + " For --render-tracks, provide a directory path\n" "-f, --format Specify format of render-output where\n" " Format is either 'wav' or 'ogg'.\n" "-s, --samplerate Specify output samplerate in Hz\n" From ea838c428d33b39226c35c8d2e57f3cec299d0bf Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Fri, 4 Sep 2015 21:48:00 -0400 Subject: [PATCH 6/8] Don't use old naming convention in new methods. Remove the _ prefix from the parameters to the newly added ProjectRenderer::getFileExtensionFromFormat. This naming convention is being phased out. --- include/ProjectRenderer.h | 2 +- src/core/ProjectRenderer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index 394c3b0fd..9c68d578d 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -87,7 +87,7 @@ public: static ExportFileFormats getFileFormatFromExtension( const QString & _ext ); - static QString getFileExtensionFromFormat( ExportFileFormats _fmt ); + static QString getFileExtensionFromFormat( ExportFileFormats fmt ); static const FileEncodeDevice fileEncodeDevices[]; diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index 581fb5ba4..6b44a1d63 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -125,9 +125,9 @@ ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension( QString ProjectRenderer::getFileExtensionFromFormat( - ExportFileFormats _fmt ) + ExportFileFormats fmt ) { - return fileEncodeDevices[_fmt].m_extension; + return fileEncodeDevices[fmt].m_extension; } From d8ce8301b831c2c9065d73b0eb7066fac254fff6 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Fri, 4 Sep 2015 21:52:01 -0400 Subject: [PATCH 7/8] Rename --render-tracks to --rendertracks. Follow convention of avoiding '-' in command names. --- doc/lmms.1 | 2 +- src/core/main.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/lmms.1 b/doc/lmms.1 index dff6d1a35..1b0a1801a 100644 --- a/doc/lmms.1 +++ b/doc/lmms.1 @@ -42,7 +42,7 @@ LMMS features components such as a Song Editor, a Beat+Bassline Editor, a Piano .SH OPTIONS .IP "\fB\-r, --render\fP \fIproject-file\fP Render given file to either a wav\- or ogg\-file. See \fB\-f\fP for details -.IP "\fB\-r, --render-tracks\fP \fIproject-file\fP +.IP "\fB\-r, --rendertracks\fP \fIproject-file\fP Render each track into a separate wav\- or ogg\-file. See \fB\-f\fP for details .IP "\fB\-o, --output\fP \fIpath\fP Render into \fIpath\fP diff --git a/src/core/main.cpp b/src/core/main.cpp index d02f8805f..6078d4653 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -127,10 +127,10 @@ void printHelp() " [ -h ]\n" " [ ]\n\n" "-r, --render Render given project file\n" - " --render-tracks Render each track to a different file\n" + " --rendertracks Render each track to a different file\n" "-o, --output Render into \n" " For --render, provide a file path\n" - " For --render-tracks, provide a directory path\n" + " For --rendertracks, provide a directory path\n" "-f, --format Specify format of render-output where\n" " Format is either 'wav' or 'ogg'.\n" "-s, --samplerate Specify output samplerate in Hz\n" @@ -190,7 +190,7 @@ int main( int argc, char * * argv ) { coreOnly = true; } - else if( arg == "--render-tracks" ) + else if( arg == "--rendertracks" ) { coreOnly = true; renderTracks = true; @@ -298,7 +298,7 @@ int main( int argc, char * * argv ) return EXIT_SUCCESS; } - else if( arg == "--render" || arg == "-r" || arg == "--render-tracks" ) + else if( arg == "--render" || arg == "-r" || arg == "--rendertracks" ) { ++i; From fdb2787ff901325d406b6d42738af65f09927b0e Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Sun, 13 Sep 2015 12:51:02 -0400 Subject: [PATCH 8/8] Support '.' in output directory path. Do not call baseName on the path passed to -o when using the --rendertracks option. This was mangling directories that contained a literal '.' if a '/' was not explicitly specified at the end. Still call baseName for --render as the argument to -o is a file and we need to set the extension (ogg/wav). --- src/core/main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/main.cpp b/src/core/main.cpp index 6078d4653..8ff44e573 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -311,7 +311,7 @@ int main( int argc, char * * argv ) fileToLoad = QString::fromLocal8Bit( argv[i] ); - renderOut = baseName( fileToLoad ); + renderOut = fileToLoad; } else if( arg == "--loop" || arg == "-l" ) { @@ -329,7 +329,7 @@ int main( int argc, char * * argv ) } - renderOut = baseName( QString::fromLocal8Bit( argv[i] ) ); + renderOut = QString::fromLocal8Bit( argv[i] ); } else if( arg == "--format" || arg == "-f" ) { @@ -602,7 +602,8 @@ int main( int argc, char * * argv ) // otherwise, it is a file, so we need to append the file extension if ( !renderTracks ) { - renderOut = renderOut + ProjectRenderer::getFileExtensionFromFormat(eff); + renderOut = baseName( renderOut ) + + ProjectRenderer::getFileExtensionFromFormat(eff); } // create renderer