97 setWindowTitle( tr(
"Export song" ) );
99 exportTypeCombo->addItem(tr(
"Export to a single track"));
100 exportTypeCombo->addItem(tr(
"Export to separate tracks"));
101 exportTypeCombo->addItem(tr(
"Both"));
105 browseBtn->setFixedFontSize( 13 );
106 browseBtn->setSize( QSize( 80, 26 ) );
107 browseBtn->setBorderRadius( 3 );
109 okBtn->setFixedFontSize( 13 );
110 okBtn->setSize( QSize( 80, 26 ) );
111 okBtn->setBorderRadius( 3 );
113 closeBtn->setFixedFontSize( 13 );
114 closeBtn->setBorderRadius( 3 );
115 closeBtn->setSize( QSize( 80, 26 ) );
118 m_pProgressBar->setValue( 0 );
128 formatCombo->addItem(
"FLAC (Free Lossless Audio Codec)" );
130 formatCombo->addItem(
"OPUS (Opus Compressed Audio)" );
132 formatCombo->addItem(
"OGG (Vorbis Compressed Audio)" );
134 formatCombo->addItem(
"MP3 (MP3 Compressed Audio)" );
136 formatCombo->addItem(
"WAV (Waveform Audio)" );
138 formatCombo->addItem(
"AIFF (Audio Interchange File Format)" );
140 formatCombo->addItem(
"AU (Sun/NeXT Audio)" );
142 formatCombo->addItem(
"CAF (Core Audio Format)" );
144 formatCombo->addItem(
"VOC (Creative Voice)" );
146 formatCombo->addItem(
"W64 (Sonic Foundry’s 64 bit RIFF/WAV)" );
153 formatCombo->setCurrentIndex( 0 );
154 connect( formatCombo, SIGNAL(currentIndexChanged(
int)),
157 sampleRateCombo->hide();
158 sampleRateLabel->hide();
159 sampleDepthCombo->hide();
160 sampleDepthLabel->hide();
163 compressionLevelSpinBox->setValue( 0.0 );
170 toggleRubberbandCheckBox->setEnabled(
false );
171 toggleRubberbandCheckBox->setToolTip( tr(
"No sample in the current song uses Rubberband" ) );
176 toggleTimeLineBPMCheckBox->setChecked( pSong->getIsTimelineActivated());
178 connect(toggleTimeLineBPMCheckBox, SIGNAL(toggled(
bool)),
this, SLOT(
toggleTimeLineBPMMode(
bool )));
245 if ( info.suffix().isEmpty() ||
258 QDir qd = QDir( sDirPath );
262 exportNameTxt->setText( sFullPath );
267 for (
const auto [ nnIndex, fformat ] :
m_formatMap ) {
268 if ( fformat == previousFormat ) {
269 formatCombo->setCurrentIndex( nnIndex );
274 compressionLevelSpinBox->setValue(
276 exportTypeCombo->setCurrentIndex(
m_pPreferences->getExportModeIdx() );
278 int nExportSampleRateIdx =
m_pPreferences->getExportSampleRateIdx();
279 if( nExportSampleRateIdx > 0 ) {
280 sampleRateCombo->setCurrentIndex( nExportSampleRateIdx );
282 sampleRateCombo->setCurrentIndex( 0 );
286 int nExportBithDepthIdx =
m_pPreferences->getExportSampleDepthIdx();
287 if( nExportBithDepthIdx > 0 ) {
288 sampleDepthCombo->setCurrentIndex( nExportBithDepthIdx );
290 sampleDepthCombo->setCurrentIndex( 0 );
298 sPath = QDir::homePath();
302 fd.setFileMode(QFileDialog::AnyFile);
304 const auto format =
m_formatMap[ formatCombo->currentIndex() ];
308 fd.setNameFilter(
"Microsoft WAV (*.wav *.WAV)" );
311 fd.setNameFilter(
"Apple AIFF (*.aiff *.AIFF)" );
314 fd.setNameFilter(
"Lossless Flac (*.flac *.FLAC)" );
317 fd.setNameFilter(
"Compressed Ogg/Opus (*.opus *.OPUS)" );
320 fd.setNameFilter(
"Compressed Ogg/Vorbis (*.ogg *.OGG)" );
323 fd.setNameFilter(
"Compressed MPEG Layer 3 (*.mp3 *.MP3)" );
326 fd.setNameFilter(
"Sun/NeXT AU (*.au *.AU)" );
329 fd.setNameFilter(
"Core Audio Format (*.caf *.CAF)" );
332 fd.setNameFilter(
"Creative Voice File (*.voc *.VOC)" );
335 fd.setNameFilter(
"Sonic Foundrys' 64 bit RIFF/WAV (*.w64 *.W64)" );
339 ERRORLOG( QString(
"Unhandle combo index [%1]" )
340 .arg( formatCombo->currentIndex() ) );
344 fd.setDirectory( sPath );
345 fd.setAcceptMode( QFileDialog::AcceptSave );
346 fd.setWindowTitle( tr(
"Export song" ) );
348 QString defaultFilename = exportNameTxt->text();
350 fd.selectFile(defaultFilename);
352 QString sFilename =
"";
354 sFilename = fd.selectedFiles().first();
358 if ( !sFilename.isEmpty() ) {
362 sFilename.append( QString(
".%1" ).arg(
m_sExtension ) );
365 exportNameTxt->setText( sFilename );
401 QFileInfo fileInfo( exportNameTxt->text() );
403 QMessageBox::warning(
this,
"Hydrogen",
404 pCommonStrings->getFileDialogMissingWritePermissions(),
409 int nSampleRate = sampleRateCombo->currentText().toInt();
410 int nSampleDepth = sampleDepthCombo->currentText().toInt();
411 const float fCompressionLevel = compressionLevelSpinBox->value();
415 const auto format =
m_formatMap[ formatCombo->currentIndex() ];
422 nSampleDepth = std::min( 16, nSampleDepth );
431 std::shared_ptr<Song> pSong =
m_pHydrogen->getSong();
432 auto pInstrumentList = pSong->getInstrumentList();
435 if ( pPref->m_bShowExportSongLicenseWarning ) {
437 QMessageBox licenseWarning(
this );
439 auto drumkitContent =
440 pSong->getInstrumentList()->summarizeContent( pSong->getComponents() );
442 bool bHasAttribution =
false;
443 bool bIsCopyleft =
false;
444 QStringList licenses;
446 for (
const auto& ccontent : drumkitContent ) {
447 if ( ccontent->m_license.hasAttribution() ) {
448 sLicense = QString(
"%1 (by %2)" )
449 .arg( ccontent->m_license.getLicenseString() )
450 .arg( ccontent->m_license.getCopyrightHolder() );
451 bHasAttribution =
true;
454 sLicense = ccontent->m_license.getLicenseString();
457 if ( ! licenses.contains( sLicense ) ) {
458 licenses << sLicense;
460 if ( ccontent->m_license.isCopyleft() ) {
465 QString sMsg = QString( tr(
"Your song uses samples of the following license:" ) )
467 for (
const auto& llicense : licenses ) {
468 sMsg.append( QString(
"<li>%1</li>" ).arg( llicense ) );
470 sMsg.append(
"</ul>" );
473 sMsg.append( QString(
"<p>%1</p>" )
474 .arg( pCommonStrings->getLicenseCopyleftWarning() ) );
477 if ( bHasAttribution ) {
478 sMsg.append( QString(
"<p>%1</p>" )
479 .arg( pCommonStrings->getLicenseAttributionWarning() ) );
482 sMsg.append(
"\n" ).append( tr(
"Be sure you satisfy all license conditions and give the required attribution." ) );
484 licenseWarning.setWindowTitle( pCommonStrings->getLicenseWarningWindowTitle() );
485 licenseWarning.setText( sMsg );
486 licenseWarning.setTextFormat( Qt::RichText );
488 licenseWarning.addButton( pCommonStrings->getButtonOk(),
489 QMessageBox::AcceptRole );
491 licenseWarning.addButton( pCommonStrings->getMutableDialog(),
492 QMessageBox::YesRole );
494 licenseWarning.addButton( pCommonStrings->getButtonCancel(),
495 QMessageBox::RejectRole );
496 licenseWarning.exec();
498 if ( licenseWarning.clickedButton() == pMuteButton ) {
499 pPref->m_bShowExportSongLicenseWarning =
false;
501 else if ( licenseWarning.clickedButton() == pRejectButton ) {
511 QString filename = exportNameTxt->text();
516 res = QMessageBox::information(
this,
"Hydrogen", tr(
"The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No );
518 res = QMessageBox::information(
this,
"Hydrogen", tr(
"The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll);
521 if (res == QMessageBox::YesToAll ){
525 if (res == QMessageBox::No ) {
535 for (
auto i = 0; i < pInstrumentList->size(); i++) {
536 pInstrumentList->get(i)->set_currently_exported(
true );
540 nSampleRate, nSampleDepth, fCompressionLevel ) ) {
541 QMessageBox::critical(
this,
"Hydrogen", tr(
"Unable to export song" ) );
551 nSampleRate, nSampleDepth, fCompressionLevel ) ) {
552 QMessageBox::critical(
this,
"Hydrogen", tr(
"Unable to export tracks" ) );
587 std::shared_ptr<Song> pSong =
m_pHydrogen->getSong();
588 QString uniqueInstrumentName;
590 int instrumentOccurence = 0;
591 for(
int i=0; i < pSong->getInstrumentList()->size(); i++ ){
592 if( pSong->getInstrumentList()->get(
m_nInstrument)->get_name() == pInstrument->get_name()){
593 instrumentOccurence++;
597 if(instrumentOccurence >= 2){
598 uniqueInstrumentName = pInstrument->get_name() + QString(
"_") + QString::number( pInstrument->get_id() );
600 uniqueInstrumentName = pInstrument->get_name();
603 return uniqueInstrumentName;
608 std::shared_ptr<Song> pSong =
m_pHydrogen->getSong();
609 auto pInstrumentList = pSong->getInstrumentList();
616 if( !bInstrumentHasNotes ){
629 const QString sSuffix = QString(
".%1" ).arg(
m_sExtension );
630 const QString sTemplateName = exportNameTxt->text();
631 QString sBaseName = sTemplateName;
632 if ( sTemplateName.endsWith( sSuffix, Qt::CaseInsensitive ) ) {
633 sBaseName.chop( sSuffix.size() );
639 if ( sBaseName.isEmpty() || sBaseName.endsWith(
"/" ) ||
640 sBaseName.endsWith(
"\\" ) ) {
643 sExportName = QString(
"%1%2" ).arg( sBaseName )
644 .arg( sInstrumentName );
647 sExportName = QString(
"%1-%2" ).arg( sBaseName )
648 .arg( sInstrumentName );
651 const QString sFileName = QString(
"%1%2" ).arg( sExportName )
654 if ( QFile( sFileName ).exists() ==
true &&
m_bQfileDialog ==
false &&
656 const int nRes = QMessageBox::information(
657 this,
"Hydrogen", tr(
"The file %1 exists. \nOverwrite the existing file?")
659 QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll );
660 if ( nRes == QMessageBox::No ) {
663 if ( nRes == QMessageBox::YesToAll ) {
673 for (
auto i = 0; i < pInstrumentList->size(); i++) {
674 pInstrumentList->get(i)->set_currently_exported(
false );
677 pSong->getInstrumentList()->get(
m_nInstrument)->set_currently_exported(
true );
720 ERRORLOG( QString(
"Invalid index [%1]" ).arg( nIndex ) );
721 okBtn->setIsActive(
false );
725 okBtn->setIsActive(
true );
736 sampleRateCombo->show();
737 sampleRateLabel->show();
738 sampleDepthCombo->show();
739 sampleDepthLabel->show();
740 compressionLevelSpinBox->hide();
741 compressionLevelLabel->hide();
748 sampleRateCombo->hide();
749 sampleRateLabel->hide();
750 sampleDepthCombo->hide();
751 sampleDepthLabel->hide();
752 compressionLevelSpinBox->show();
753 compressionLevelLabel->show();
759 if ( sampleDepthCombo->count() == 4 ) {
760 sampleDepthCombo->removeItem( 3 );
761 sampleDepthCombo->removeItem( 2 );
765 if ( sampleDepthCombo->count() == 2 ) {
766 sampleDepthCombo->addItems( QStringList() <<
"24" <<
"32" );
772 if ( ! exportNameTxt->text().isEmpty() ) {
773 const QString sPreviousFilename = exportNameTxt->text();
774 auto splitty = sPreviousFilename.split(
".");
775 splitty.removeLast();
776 exportNameTxt->setText( QString(
"%1.%2" )