23#include <QProgressBar>
64 switch ( interpolateMode ) {
65 case Interpolation::InterpolateMode::Linear:
68 case Interpolation::InterpolateMode::Cosine:
71 case Interpolation::InterpolateMode::Third:
74 case Interpolation::InterpolateMode::Cubic:
77 case Interpolation::InterpolateMode::Hermite:
90 , m_bExporting( false )
91 , m_pHydrogen(
Hydrogen::get_instance() )
96 setWindowTitle( tr(
"Export song" ) );
98 exportTypeCombo->addItem(tr(
"Export to a single track"));
99 exportTypeCombo->addItem(tr(
"Export to separate tracks"));
100 exportTypeCombo->addItem(tr(
"Both"));
104 m_pProgressBar->setValue( 0 );
118 toggleRubberbandCheckBox->setEnabled(
false );
119 toggleRubberbandCheckBox->setToolTip( tr(
"No sample in the current song uses Rubberband" ) );
124 toggleTimeLineBPMCheckBox->setChecked( pSong->getIsTimelineActivated());
126 connect(toggleTimeLineBPMCheckBox, SIGNAL(toggled(
bool)),
this, SLOT(
toggleTimeLineBPMMode(
bool )));
143 pH2App->removeEventListener(
this );
152 if( sDefaultFilename.isEmpty() ){
156 QFileInfo qDefaultFile( sDefaultFilename );
157 sDefaultFilename = qDefaultFile.fileName();
160 sDefaultFilename.replace(
'*',
"_" );
163 return sDefaultFilename;
169 QString sFilename = exportNameTxt->text();
170 QFileInfo info( sFilename );
171 QDir dir = info.absoluteDir();
172 if ( !dir.exists() ) {
198 QDir qd = QDir( sDirPath );
202 exportNameTxt->setText( sFullPath );
209 if( nExportSampleRateIdx > 0 ) {
210 sampleRateCombo->setCurrentIndex( nExportSampleRateIdx );
212 sampleRateCombo->setCurrentIndex( 0 );
217 if( nExportBithDepthIdx > 0 ) {
218 sampleDepthCombo->setCurrentIndex( nExportBithDepthIdx );
220 sampleDepthCombo->setCurrentIndex( 0 );
228 sPath = QDir::homePath();
232 fd.setFileMode(QFileDialog::AnyFile);
234 if( templateCombo->currentIndex() <= 4 ) {
235 fd.setNameFilter(
"Microsoft WAV (*.wav *.WAV)");
236 }
else if ( templateCombo->currentIndex() > 4 && templateCombo->currentIndex() < 8 ) {
237 fd.setNameFilter(
"Apple AIFF (*.aiff *.AIFF)");
238 }
else if ( templateCombo->currentIndex() == 8 ) {
239 fd.setNameFilter(
"Lossless Flac (*.flac *.FLAC)");
240 }
else if ( templateCombo->currentIndex() == 9 ) {
241 fd.setNameFilter(
"Compressed Ogg (*.ogg *.OGG)");
244 fd.setDirectory( sPath );
245 fd.setAcceptMode( QFileDialog::AcceptSave );
246 fd.setWindowTitle( tr(
"Export song" ) );
248 QString defaultFilename = exportNameTxt->text();
250 fd.selectFile(defaultFilename);
252 QString filename =
"";
254 filename = fd.selectedFiles().first();
258 if ( !filename.isEmpty() ) {
265 exportNameTxt->setText(filename);
268 if( filename.endsWith(
".ogg" ) || filename.endsWith(
".OGG" ) ){
269 sampleRateCombo->hide();
270 sampleDepthCombo->hide();
271 sampleRateLable->hide();
272 sampleDepthLable->hide();
280 QString filename = exportNameTxt->text();
281 QFileInfo file( filename );
282 QDir dir = file.dir();
283 if( !dir.exists() ) {
284 QMessageBox::warning(
286 tr(
"Directory %1 does not exist").arg( dir.absolutePath() ),
309 QFileInfo fileInfo( exportNameTxt->text() );
311 QMessageBox::warning(
this,
"Hydrogen",
312 pCommonStrings->getFileDialogMissingWritePermissions(),
319 auto pInstrumentList = pSong->getInstrumentList();
322 if ( pPref->m_bShowExportSongLicenseWarning ) {
324 QMessageBox licenseWarning(
this );
326 auto drumkitContent =
327 pSong->getInstrumentList()->summarizeContent( pSong->getComponents() );
329 bool bHasAttribution =
false;
330 bool bIsCopyleft =
false;
331 QStringList licenses;
333 for (
const auto& ccontent : drumkitContent ) {
334 if ( ccontent->m_license.hasAttribution() ) {
335 sLicense = QString(
"%1 (by %2)" )
336 .arg( ccontent->m_license.getLicenseString() )
337 .arg( ccontent->m_license.getCopyrightHolder() );
338 bHasAttribution =
true;
341 sLicense = ccontent->m_license.getLicenseString();
344 if ( ! licenses.contains( sLicense ) ) {
345 licenses << sLicense;
347 if ( ccontent->m_license.isCopyleft() ) {
352 QString sMsg = QString( tr(
"Your song uses samples of the following license:" ) )
354 for (
const auto& llicense : licenses ) {
355 sMsg.append( QString(
"<li>%1</li>" ).arg( llicense ) );
357 sMsg.append(
"</ul>" );
360 sMsg.append( QString(
"<p>%1</p>" )
361 .arg( pCommonStrings->getLicenseCopyleftWarning() ) );
364 if ( bHasAttribution ) {
365 sMsg.append( QString(
"<p>%1</p>" )
366 .arg( pCommonStrings->getLicenseAttributionWarning() ) );
369 sMsg.append(
"\n" ).append( tr(
"Be sure you satisfy all license conditions and give the required attribution." ) );
371 licenseWarning.setWindowTitle( pCommonStrings->getLicenseWarningWindowTitle() );
372 licenseWarning.setText( sMsg );
373 licenseWarning.setTextFormat( Qt::RichText );
375 licenseWarning.addButton( pCommonStrings->getButtonOk(),
376 QMessageBox::AcceptRole );
378 licenseWarning.addButton( pCommonStrings->getMutableDialog(),
379 QMessageBox::YesRole );
381 licenseWarning.addButton( pCommonStrings->getButtonCancel(),
382 QMessageBox::RejectRole );
383 licenseWarning.exec();
385 if ( licenseWarning.clickedButton() == pMuteButton ) {
386 pPref->m_bShowExportSongLicenseWarning =
false;
388 else if ( licenseWarning.clickedButton() == pRejectButton ) {
398 QString filename = exportNameTxt->text();
403 res = QMessageBox::information(
this,
"Hydrogen", tr(
"The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No );
405 res = QMessageBox::information(
this,
"Hydrogen", tr(
"The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll);
408 if (res == QMessageBox::YesToAll ){
412 if (res == QMessageBox::No ) {
422 for (
auto i = 0; i < pInstrumentList->size(); i++) {
423 pInstrumentList->get(i)->set_currently_exported(
true );
427 sampleDepthCombo->currentText().toInt()) ) {
428 QMessageBox::critical(
this,
"Hydrogen", tr(
"Unable to export song" ) );
447 unsigned nPatterns = pSong->getPatternList()->size();
449 bool bInstrumentHasNotes =
false;
451 for (
unsigned i = 0; i < nPatterns; i++ ) {
452 Pattern *pPattern = pSong->getPatternList()->get( i );
455 Note *pNote = it->second;
459 bInstrumentHasNotes =
true;
465 return bInstrumentHasNotes;
471 QString uniqueInstrumentName;
473 int instrumentOccurence = 0;
474 for(
int i=0; i < pSong->getInstrumentList()->size(); i++ ){
475 if( pSong->getInstrumentList()->get(
m_nInstrument)->get_name() == pInstrument->get_name()){
476 instrumentOccurence++;
480 if(instrumentOccurence >= 2){
481 uniqueInstrumentName = pInstrument->get_name() + QString(
"_") + QString::number( pInstrument->get_id() );
483 uniqueInstrumentName = pInstrument->get_name();
486 return uniqueInstrumentName;
492 auto pInstrumentList = pSong->getInstrumentList();
494 if( m_nInstrument < pInstrumentList->size() ){
499 if( !bInstrumentHasNotes ){
511 QStringList filenameList = exportNameTxt->text().split(
m_sExtension );
514 if( !filenameList.isEmpty() ){
515 firstItem = filenameList.first();
522 int res = QMessageBox::information(
this,
"Hydrogen", tr(
"The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll );
523 if (res == QMessageBox::No )
return;
532 for (
auto i = 0; i < pInstrumentList->size(); i++) {
533 pInstrumentList->get(i)->set_currently_exported(
false );
536 pSong->getInstrumentList()->get(
m_nInstrument)->set_currently_exported(
true );
593 filename = exportNameTxt->text();
594 splitty = filename.split(
".");
595 splitty.removeLast();
596 filename = splitty.join(
"." );
600 sampleRateCombo->show();
601 sampleDepthCombo->show();
602 sampleRateCombo->setCurrentIndex ( 1 );
603 sampleDepthCombo->setCurrentIndex ( 1 );
608 sampleRateCombo->show();
609 sampleDepthCombo->show();
610 sampleRateCombo->setCurrentIndex ( 2 );
611 sampleDepthCombo->setCurrentIndex ( 1 );
616 sampleRateCombo->show();
617 sampleDepthCombo->show();
618 sampleRateCombo->setCurrentIndex ( 2 );
619 sampleDepthCombo->setCurrentIndex ( 2 );
624 sampleRateCombo->show();
625 sampleDepthCombo->show();
626 sampleRateCombo->setCurrentIndex ( 0 );
627 sampleDepthCombo->setCurrentIndex ( 0 );
632 sampleRateCombo->show();
633 sampleDepthCombo->show();
634 sampleRateCombo->setCurrentIndex ( 4 );
635 sampleDepthCombo->setCurrentIndex ( 3 );
640 sampleRateCombo->show();
641 sampleDepthCombo->show();
642 sampleRateCombo->setCurrentIndex ( 1 );
643 sampleDepthCombo->setCurrentIndex ( 1 );
648 sampleRateCombo->show();
649 sampleDepthCombo->show();
650 sampleRateCombo->setCurrentIndex ( 2 );
651 sampleDepthCombo->setCurrentIndex ( 1 );
656 sampleRateCombo->show();
657 sampleDepthCombo->show();
658 sampleRateCombo->setCurrentIndex ( 2 );
659 sampleDepthCombo->setCurrentIndex ( 2 );
664 sampleRateCombo->show();
665 sampleDepthCombo->show();
666 sampleRateCombo->setCurrentIndex ( 2 );
667 sampleDepthCombo->setCurrentIndex ( 2 );
672 sampleRateCombo->hide();
673 sampleDepthCombo->hide();
674 sampleRateLable->hide();
675 sampleDepthLable->hide();
681 sampleRateCombo->show();
682 sampleDepthCombo->show();
683 sampleRateCombo->setCurrentIndex ( 1 );
684 sampleDepthCombo->setCurrentIndex ( 1 );
689 exportNameTxt->setText(filename);
696 QString filename = exportNameTxt->text();
697 if ( ! filename.isEmpty() ) {
698 okBtn->setEnabled(
true);
701 okBtn->setEnabled(
false);
704 if( filename.endsWith(
".ogg" ) || filename.endsWith(
".OGG" ) ){
705 if( templateCombo->currentIndex() != 9 ){
706 templateCombo->setCurrentIndex( 9 );
709 else if( filename.endsWith(
".flac" ) || filename.endsWith(
".FLAC" ) ){
710 sampleRateLable->show();
711 sampleDepthLable->show();
712 if( templateCombo->currentIndex() != 8 ){
713 templateCombo->setCurrentIndex( 8 );
716 else if( filename.endsWith(
".aiff" ) || filename.endsWith(
".AIFF" ) ){
717 sampleRateLable->show();
718 sampleDepthLable->show();
719 if( templateCombo->currentIndex() < 5 || templateCombo->currentIndex() > 7 ){
720 templateCombo->setCurrentIndex( 5 );
723 else if( filename.endsWith(
".wav" ) || filename.endsWith(
".WAV" ) ){
724 sampleRateLable->show();
725 sampleDepthLable->show();
726 if( templateCombo->currentIndex() > 4 ){
727 templateCombo->setCurrentIndex( 0 );
735 m_pProgressBar->setValue( nValue );
736 if ( nValue == 100 ) {
750 if ( nValue < 100 ) {
751 closeBtn->setEnabled(
false);
752 resampleComboBox->setEnabled(
false);
756 closeBtn->setEnabled(
true);
757 resampleComboBox->setEnabled(
true);
803 auto pSongInstrList = pSong->getInstrumentList();
804 assert(pSongInstrList);
805 for (
unsigned nInstr = 0; nInstr < pSongInstrList->size(); ++nInstr ) {
806 auto pInstr = pSongInstrList->get( nInstr );
809 for (
const auto& pCompo : *pInstr->get_components() ) {
811 auto pLayer = pCompo->get_layer( nLayer );
813 auto pSample = pLayer->get_sample();
814 if ( pSample !=
nullptr ) {
815 if( pSample->get_rubberband().use ) {
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
@ EXPORT_TO_SEPARATE_TRACKS
static int interpolateModeToComboBoxIndex(Interpolation::InterpolateMode interpolateMode)
#define FOREACH_NOTE_CST_IT_BEGIN_LENGTH(_notes, _it, _pattern)
Iterate over all accessible notes between position 0 and length of _pattern in an immutable way.
static QString sLastFilename
bool m_bOldTimeLineBPMMode
virtual void progressEvent(int nValue) override
void toggleRubberbandBatchMode(bool toggled)
void setResamplerMode(int index)
void on_templateCombo_currentIndexChanged(int index)
H2Core::Preferences * m_pPreferences
QString createDefaultFilename()
bool m_bOldRubberbandBatchMode
QString findUniqueExportFilenameForInstrument(std::shared_ptr< H2Core::Instrument > pInstrument)
void on_browseBtn_clicked()
bool checkUseOfRubberband()
void closeEvent(QCloseEvent *event) override
void on_exportNameTxt_textChanged(const QString &text)
void on_closeBtn_clicked()
void restoreSettingsFromPreferences()
ExportSongDialog(QWidget *parent)
InterpolateMode m_OldInterpolationMode
bool currentInstrumentHasNotes()
void resampleComboBoIndexChanged(int index)
void toggleTimeLineBPMMode(bool toggled)
void saveSettingsToPreferences()
H2Core::Hydrogen * m_pHydrogen
Custom file dialog checking whether the user has write access to the selected folder before allowing ...
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
Sampler * getSampler() const
const std::shared_ptr< TransportPosition > getTransportPosition() const
static bool dir_writable(const QString &path, bool silent=false)
returns true if the given path is a writable regular directory
static const QString songs_ext
bool startExportSession(int rate, int depth)
std::shared_ptr< Song > getSong() const
Get the current song.
void setIsTimelineActivated(bool bEnabled)
Wrapper around both Song::setIsTimelineActivated (recent) and Preferences::setUseTimelinebpm() (forme...
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
void startExportSong(const QString &filename)
Export a song to a wav file.
AudioEngine * getAudioEngine() const
void recalculateRubberband(float fBpm)
Recalculates all Samples using RubberBand for a specific tempo fBpm.
static int getMaxLayers()
A note plays an associated instrument with a velocity left and right pan.
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
Pattern class is a Note container.
const notes_t * get_notes() const
get the virtual pattern set
std::multimap< int, Note * > notes_t
< multimap note type
Manager for User Preferences File (singleton)
int getExportSampleDepthIdx() const
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setExportTemplateIdx(int nExportTemplateIdx)
int getExportSampleRateIdx() const
int getExportModeIdx() const
void setExportModeIdx(int nExportMode)
int getExportTemplateIdx() const
void setRubberBandBatchMode(int val)
void setExportSampleDepthIdx(int nExportSampleDepthIdx)
void setLastExportSongDirectory(QString sPath)
void setExportSampleRateIdx(int nExportSampleRateIdx)
int getRubberBandBatchMode()
QString getLastExportSongDirectory() const
Interpolation::InterpolateMode getInterpolateMode()
void setInterpolateMode(Interpolation::InterpolateMode mode)
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()