hydrogen 1.2.3
ExportSongDialog.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2024 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <QProgressBar>
24#include <QLabel>
25
26#include "CommonStrings.h"
27#include "ExportSongDialog.h"
28#include "HydrogenApp.h"
29#include "Mixer/Mixer.h"
30#include "Widgets/FileDialog.h"
31
32#include <core/Basics/Note.h>
33#include <core/Basics/Pattern.h>
40#include <core/Basics/Song.h>
41#include <core/Hydrogen.h>
43#include <core/Timeline.h>
44#include <core/IO/AudioOutput.h>
48#include <core/EventQueue.h>
49
50#include <memory>
51
52#ifdef WIN32
53#include <time.h>
54#endif
55
56using namespace H2Core;
57
59
61{
62 int Index = 0;
63
64 switch ( interpolateMode ) {
65 case Interpolation::InterpolateMode::Linear:
66 Index = 0;
67 break;
68 case Interpolation::InterpolateMode::Cosine:
69 Index = 1;
70 break;
71 case Interpolation::InterpolateMode::Third:
72 Index = 2;
73 break;
74 case Interpolation::InterpolateMode::Cubic:
75 Index = 3;
76 break;
77 case Interpolation::InterpolateMode::Hermite:
78 Index = 4;
79 break;
80 }
81
82 return Index;
83}
84
85// Here we are going to store export filename
87
89 : QDialog(parent)
90 , m_bExporting( false )
91 , m_pHydrogen( Hydrogen::get_instance() )
92 , m_pPreferences( Preferences::get_instance() )
93{
94 setupUi( this );
95 setModal( true );
96 setWindowTitle( tr( "Export song" ) );
97
98 exportTypeCombo->addItem(tr("Export to a single track"));
99 exportTypeCombo->addItem(tr("Export to separate tracks"));
100 exportTypeCombo->addItem(tr("Both"));
101
103
104 m_pProgressBar->setValue( 0 );
105
106 m_bQfileDialog = false;
107 m_bExportTrackouts = false;
108 m_nInstrument = 0;
109 m_sExtension = ".wav";
110 m_bOverwriteFiles = false;
111 m_bOldRubberbandBatchMode = m_pPreferences->getRubberBandBatchMode();
112
113 // use of rubberband batch
114 if( checkUseOfRubberband() ) {
115 toggleRubberbandCheckBox->setChecked( m_bOldRubberbandBatchMode );
116 connect(toggleRubberbandCheckBox, SIGNAL(toggled(bool)), this, SLOT(toggleRubberbandBatchMode( bool )));
117 } else {
118 toggleRubberbandCheckBox->setEnabled( false );
119 toggleRubberbandCheckBox->setToolTip( tr( "No sample in the current song uses Rubberband" ) );
120 }
121
122 // use of timeline
123 auto pSong = H2Core::Hydrogen::get_instance()->getSong();
124 toggleTimeLineBPMCheckBox->setChecked( pSong->getIsTimelineActivated());
125 m_bOldTimeLineBPMMode = pSong->getIsTimelineActivated();
126 connect(toggleTimeLineBPMCheckBox, SIGNAL(toggled(bool)), this, SLOT(toggleTimeLineBPMMode( bool )));
127
128 // use of interpolation mode
129 m_OldInterpolationMode = m_pHydrogen->getAudioEngine()->getSampler()->getInterpolateMode();
130 resampleComboBox->setCurrentIndex( interpolateModeToComboBoxIndex( m_OldInterpolationMode ) );
131 connect(resampleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(resampleComboBoIndexChanged(int)));
132
133 //Load the other settings..
135
136 // Have the dialog find the best size
137 adjustSize();
138}
139
141{
142 if ( auto pH2App = HydrogenApp::get_instance() ) {
143 pH2App->removeEventListener( this );
144 }
145}
146
148{
149 QString sDefaultFilename = m_pHydrogen->getSong()->getFilename();
150
151 // If song is not saved then use song name otherwise use the song filename
152 if( sDefaultFilename.isEmpty() ){
153 sDefaultFilename = m_pHydrogen->getSong()->getName();
154 } else {
155 // extracting filename from full path
156 QFileInfo qDefaultFile( sDefaultFilename );
157 sDefaultFilename = qDefaultFile.fileName();
158 }
159
160 sDefaultFilename.replace( '*', "_" );
161 sDefaultFilename.replace( Filesystem::songs_ext, "" );
162 sDefaultFilename += m_sExtension;
163 return sDefaultFilename;
164}
165
167{
168 // extracting dirname from export box
169 QString sFilename = exportNameTxt->text();
170 QFileInfo info( sFilename );
171 QDir dir = info.absoluteDir();
172 if ( !dir.exists() ) {
173 // very strange if it happens but better to check for it anyway
174 return;
175 }
176
177 // saving filename for this session
178 sLastFilename = info.fileName();
180
181 // saving other options
182 m_pPreferences->setExportModeIdx( exportTypeCombo->currentIndex() );
183 m_pPreferences->setExportTemplateIdx( templateCombo->currentIndex() );
184 m_pPreferences->setExportSampleRateIdx( sampleRateCombo->currentIndex() );
185 m_pPreferences->setExportSampleDepthIdx( sampleDepthCombo->currentIndex() );
186}
187
189{
190 // loading previous directory and filling filename text field
191
192 // loading default filename on a first run and storing it in static field
193 if( sLastFilename.isEmpty() ) {
195 }
196
197 QString sDirPath = m_pPreferences->getLastExportSongDirectory();
198 QDir qd = QDir( sDirPath );
199
200 // joining filepath with dirname
201 QString sFullPath = qd.absoluteFilePath( sLastFilename );
202 exportNameTxt->setText( sFullPath );
203
204 // loading rest of the options
205 templateCombo->setCurrentIndex( m_pPreferences->getExportTemplateIdx() );
206 exportTypeCombo->setCurrentIndex( m_pPreferences->getExportModeIdx() );
207
208 int nExportSampleRateIdx = m_pPreferences->getExportSampleRateIdx();
209 if( nExportSampleRateIdx > 0 ) {
210 sampleRateCombo->setCurrentIndex( nExportSampleRateIdx );
211 } else {
212 sampleRateCombo->setCurrentIndex( 0 );
213 }
214
215
216 int nExportBithDepthIdx = m_pPreferences->getExportSampleDepthIdx();
217 if( nExportBithDepthIdx > 0 ) {
218 sampleDepthCombo->setCurrentIndex( nExportBithDepthIdx );
219 } else {
220 sampleDepthCombo->setCurrentIndex( 0 );
221 }
222}
223
225{
227 if ( ! Filesystem::dir_writable( sPath, false ) ){
228 sPath = QDir::homePath();
229 }
230
231 FileDialog fd(this);
232 fd.setFileMode(QFileDialog::AnyFile);
233
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)");
242 }
243
244 fd.setDirectory( sPath );
245 fd.setAcceptMode( QFileDialog::AcceptSave );
246 fd.setWindowTitle( tr( "Export song" ) );
247
248 QString defaultFilename = exportNameTxt->text();
249
250 fd.selectFile(defaultFilename);
251
252 QString filename = "";
253 if (fd.exec()) {
254 filename = fd.selectedFiles().first();
255 m_bQfileDialog = true;
256 }
257
258 if ( !filename.isEmpty() ) {
259 //this second extension check is mostly important if you leave a dot
260 //without a regular extionsion in a filename
261 if( !filename.endsWith( m_sExtension ) ){
262 filename.append(m_sExtension);
263 }
264
265 exportNameTxt->setText(filename);
266 }
267
268 if( filename.endsWith( ".ogg" ) || filename.endsWith( ".OGG" ) ){
269 sampleRateCombo->hide();
270 sampleDepthCombo->hide();
271 sampleRateLable->hide();
272 sampleDepthLable->hide();
273 }
274
275}
276
278{
279 // check if directory exists otherwise error
280 QString filename = exportNameTxt->text();
281 QFileInfo file( filename );
282 QDir dir = file.dir();
283 if( !dir.exists() ) {
284 QMessageBox::warning(
285 this, "Hydrogen",
286 tr( "Directory %1 does not exist").arg( dir.absolutePath() ),
287 QMessageBox::Ok
288 );
289 return false;
290 }
291
292 return true;
293}
294
296{
297 if ( m_bExporting ) {
298 return;
299 }
300
301 if( !validateUserInput() ) {
302 return;
303 }
304
306
307 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
308
309 QFileInfo fileInfo( exportNameTxt->text() );
310 if ( ! Filesystem::dir_writable( fileInfo.absoluteDir().absolutePath(), false ) ) {
311 QMessageBox::warning( this, "Hydrogen",
312 pCommonStrings->getFileDialogMissingWritePermissions(),
313 QMessageBox::Ok );
314 return;
315 }
316
317 auto pPref = Preferences::get_instance();
318 std::shared_ptr<Song> pSong = m_pHydrogen->getSong();
319 auto pInstrumentList = pSong->getInstrumentList();
320
321 // License related export warnings
322 if ( pPref->m_bShowExportSongLicenseWarning ) {
323
324 QMessageBox licenseWarning( this );
325
326 auto drumkitContent =
327 pSong->getInstrumentList()->summarizeContent( pSong->getComponents() );
328
329 bool bHasAttribution = false;
330 bool bIsCopyleft = false;
331 QStringList licenses;
332 QString sLicense;
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;
339 }
340 else {
341 sLicense = ccontent->m_license.getLicenseString();
342 }
343
344 if ( ! licenses.contains( sLicense ) ) {
345 licenses << sLicense;
346
347 if ( ccontent->m_license.isCopyleft() ) {
348 bIsCopyleft = true;
349 }
350 }
351 }
352 QString sMsg = QString( tr( "Your song uses samples of the following license:" ) )
353 .append( "<ul>" );
354 for ( const auto& llicense : licenses ) {
355 sMsg.append( QString( "<li>%1</li>" ).arg( llicense ) );
356 }
357 sMsg.append( "</ul>" );
358
359 if ( bIsCopyleft ) {
360 sMsg.append( QString( "<p>%1</p>" )
361 .arg( pCommonStrings->getLicenseCopyleftWarning() ) );
362 }
363
364 if ( bHasAttribution ) {
365 sMsg.append( QString( "<p>%1</p>" )
366 .arg( pCommonStrings->getLicenseAttributionWarning() ) );
367 }
368
369 sMsg.append( "\n" ).append( tr( "Be sure you satisfy all license conditions and give the required attribution." ) );
370
371 licenseWarning.setWindowTitle( pCommonStrings->getLicenseWarningWindowTitle() );
372 licenseWarning.setText( sMsg );
373 licenseWarning.setTextFormat( Qt::RichText );
374
375 licenseWarning.addButton( pCommonStrings->getButtonOk(),
376 QMessageBox::AcceptRole );
377 auto pMuteButton =
378 licenseWarning.addButton( pCommonStrings->getMutableDialog(),
379 QMessageBox::YesRole );
380 auto pRejectButton =
381 licenseWarning.addButton( pCommonStrings->getButtonCancel(),
382 QMessageBox::RejectRole );
383 licenseWarning.exec();
384
385 if ( licenseWarning.clickedButton() == pMuteButton ) {
386 pPref->m_bShowExportSongLicenseWarning = false;
387 }
388 else if ( licenseWarning.clickedButton() == pRejectButton ) {
389 return;
390 }
391 }
392
393 m_bOverwriteFiles = false;
394
395 if( exportTypeCombo->currentIndex() == EXPORT_TO_SINGLE_TRACK || exportTypeCombo->currentIndex() == EXPORT_TO_BOTH ){
396 m_bExportTrackouts = false;
397
398 QString filename = exportNameTxt->text();
399 if ( fileInfo.exists() == true && m_bQfileDialog == false ) {
400
401 int res;
402 if( exportTypeCombo->currentIndex() == EXPORT_TO_SINGLE_TRACK ){
403 res = QMessageBox::information( this, "Hydrogen", tr( "The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No );
404 } else {
405 res = QMessageBox::information( this, "Hydrogen", tr( "The file %1 exists. \nOverwrite the existing file?").arg(filename), QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll);
406 }
407
408 if (res == QMessageBox::YesToAll ){
409 m_bOverwriteFiles = true;
410 }
411
412 if (res == QMessageBox::No ) {
413 return;
414 }
415 }
416
417 if( exportTypeCombo->currentIndex() == EXPORT_TO_BOTH ){
418 m_bExportTrackouts = true;
419 }
420
421 /* arm all tracks for export */
422 for (auto i = 0; i < pInstrumentList->size(); i++) {
423 pInstrumentList->get(i)->set_currently_exported( true );
424 }
425
426 if ( ! m_pHydrogen->startExportSession( sampleRateCombo->currentText().toInt(),
427 sampleDepthCombo->currentText().toInt()) ) {
428 QMessageBox::critical( this, "Hydrogen", tr( "Unable to export song" ) );
429 return;
430 }
431 m_pHydrogen->startExportSong( filename );
432 return;
433 }
434
435 if( exportTypeCombo->currentIndex() == EXPORT_TO_SEPARATE_TRACKS ){
436 m_bExportTrackouts = true;
437 m_pHydrogen->startExportSession(sampleRateCombo->currentText().toInt(), sampleDepthCombo->currentText().toInt());
438 exportTracks();
439 return;
440 }
441
442}
443
445{
446 std::shared_ptr<Song> pSong = m_pHydrogen->getSong();
447 unsigned nPatterns = pSong->getPatternList()->size();
448
449 bool bInstrumentHasNotes = false;
450
451 for ( unsigned i = 0; i < nPatterns; i++ ) {
452 Pattern *pPattern = pSong->getPatternList()->get( i );
453 const Pattern::notes_t* notes = pPattern->get_notes();
454 FOREACH_NOTE_CST_IT_BEGIN_LENGTH(notes,it,pPattern) {
455 Note *pNote = it->second;
456 assert( pNote );
457
458 if( pNote->get_instrument()->get_id() == pSong->getInstrumentList()->get(m_nInstrument)->get_id() ){
459 bInstrumentHasNotes = true;
460 break;
461 }
462 }
463 }
464
465 return bInstrumentHasNotes;
466}
467
468QString ExportSongDialog::findUniqueExportFilenameForInstrument( std::shared_ptr<Instrument> pInstrument )
469{
470 std::shared_ptr<Song> pSong = m_pHydrogen->getSong();
471 QString uniqueInstrumentName;
472
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++;
477 }
478 }
479
480 if(instrumentOccurence >= 2){
481 uniqueInstrumentName = pInstrument->get_name() + QString("_") + QString::number( pInstrument->get_id() );
482 } else {
483 uniqueInstrumentName = pInstrument->get_name();
484 }
485
486 return uniqueInstrumentName;
487}
488
490{
491 std::shared_ptr<Song> pSong = m_pHydrogen->getSong();
492 auto pInstrumentList = pSong->getInstrumentList();
493
495
496 //if a instrument contains no notes we jump to the next instrument
497 bool bInstrumentHasNotes = currentInstrumentHasNotes();
498
499 if( !bInstrumentHasNotes ){
500 if( m_nInstrument == pInstrumentList->size() -1 ){
501 m_bExportTrackouts = false;
502 m_nInstrument = 0;
503 return;
504 } else {
506 exportTracks();
507 return;
508 }
509 }
510
511 QStringList filenameList = exportNameTxt->text().split( m_sExtension );
512
513 QString firstItem;
514 if( !filenameList.isEmpty() ){
515 firstItem = filenameList.first();
516 }
517 QString newItem = firstItem + "-" + findUniqueExportFilenameForInstrument( pInstrumentList->get( m_nInstrument ) );
518
519 QString filename = newItem.append( m_sExtension );
520
521 if ( QFile( filename ).exists() == true && m_bQfileDialog == false && !m_bOverwriteFiles) {
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;
524 if (res == QMessageBox::YesToAll ) m_bOverwriteFiles = true;
525 }
526
527 if( m_nInstrument > 0 ){
528 m_pHydrogen->stopExportSong();
529 m_bExporting = false;
530 }
531
532 for (auto i = 0; i < pInstrumentList->size(); i++) {
533 pInstrumentList->get(i)->set_currently_exported( false );
534 }
535
536 pSong->getInstrumentList()->get(m_nInstrument)->set_currently_exported( true );
537
538 m_pHydrogen->startExportSong( filename );
539
540 if(! (m_nInstrument == pInstrumentList->size()) ){
542 }
543 }
544
545}
546
547void ExportSongDialog::closeEvent( QCloseEvent *event ) {
548 UNUSED( event );
549 closeExport();
550}
556
557 m_pHydrogen->stopExportSong();
558 m_pHydrogen->stopExportSession();
559
560 m_bExporting = false;
561
562 if( m_pPreferences->getRubberBandBatchMode() ){
563 m_pHydrogen->getAudioEngine()->lock( RIGHT_HERE );
564 m_pHydrogen->recalculateRubberband( m_pHydrogen->getAudioEngine()->getTransportPosition()->getBpm() );
565 m_pHydrogen->getAudioEngine()->unlock();
566 }
567 m_pPreferences->setRubberBandBatchMode( m_bOldRubberbandBatchMode );
568 m_pHydrogen->setIsTimelineActivated( m_bOldTimeLineBPMMode );
569
570 m_pHydrogen->getAudioEngine()->getSampler()->setInterpolateMode( m_OldInterpolationMode );
571 accept();
572}
573
574
576{
589
590 QString filename;
591 QStringList splitty;
592
593 filename = exportNameTxt->text();
594 splitty = filename.split(".");
595 splitty.removeLast();
596 filename = splitty.join( "." );
597
598 switch ( index ) {
599 case 0:
600 sampleRateCombo->show();
601 sampleDepthCombo->show();
602 sampleRateCombo->setCurrentIndex ( 1 ); //44100hz
603 sampleDepthCombo->setCurrentIndex ( 1 ); //16bit
604 filename += ".wav";
605 m_sExtension = ".wav";
606 break;
607 case 1:
608 sampleRateCombo->show();
609 sampleDepthCombo->show();
610 sampleRateCombo->setCurrentIndex ( 2 ); //48000hz
611 sampleDepthCombo->setCurrentIndex ( 1 ); //16bit
612 filename += ".wav";
613 m_sExtension = ".wav";
614 break;
615 case 2:
616 sampleRateCombo->show();
617 sampleDepthCombo->show();
618 sampleRateCombo->setCurrentIndex ( 2 ); //48000hz
619 sampleDepthCombo->setCurrentIndex ( 2 ); //24bit
620 filename += ".wav";
621 m_sExtension = ".wav";
622 break;
623 case 3:
624 sampleRateCombo->show();
625 sampleDepthCombo->show();
626 sampleRateCombo->setCurrentIndex ( 0 ); //22050hz
627 sampleDepthCombo->setCurrentIndex ( 0 ); //8bit
628 filename += ".wav";
629 m_sExtension = ".wav";
630 break;
631 case 4:
632 sampleRateCombo->show();
633 sampleDepthCombo->show();
634 sampleRateCombo->setCurrentIndex ( 4 ); //96000hz
635 sampleDepthCombo->setCurrentIndex ( 3 ); //32bit
636 filename += ".wav";
637 m_sExtension = ".wav";
638 break;
639 case 5:
640 sampleRateCombo->show();
641 sampleDepthCombo->show();
642 sampleRateCombo->setCurrentIndex ( 1 ); //44100hz
643 sampleDepthCombo->setCurrentIndex ( 1 ); //16bit
644 filename += ".aiff";
645 m_sExtension = ".aiff";
646 break;
647 case 6:
648 sampleRateCombo->show();
649 sampleDepthCombo->show();
650 sampleRateCombo->setCurrentIndex ( 2 ); //48000hz
651 sampleDepthCombo->setCurrentIndex ( 1 ); //16bit
652 filename += ".aiff";
653 m_sExtension = ".aiff";
654 break;
655 case 7:
656 sampleRateCombo->show();
657 sampleDepthCombo->show();
658 sampleRateCombo->setCurrentIndex ( 2 ); //48000hz
659 sampleDepthCombo->setCurrentIndex ( 2 ); //24bit
660 filename += ".aiff";
661 m_sExtension = ".aiff";
662 break;
663 case 8:
664 sampleRateCombo->show();
665 sampleDepthCombo->show();
666 sampleRateCombo->setCurrentIndex ( 2 ); //48000hz
667 sampleDepthCombo->setCurrentIndex ( 2 ); //24bit
668 filename += ".flac";
669 m_sExtension = ".flac";
670 break;
671 case 9:
672 sampleRateCombo->hide();
673 sampleDepthCombo->hide();
674 sampleRateLable->hide();
675 sampleDepthLable->hide();
676 filename += ".ogg";
677 m_sExtension = ".ogg";
678 break;
679
680 default:
681 sampleRateCombo->show();
682 sampleDepthCombo->show();
683 sampleRateCombo->setCurrentIndex ( 1 ); //44100hz
684 sampleDepthCombo->setCurrentIndex ( 1 ); //16bit
685 filename += ".wav";
686 m_sExtension = ".wav";
687 }
688
689 exportNameTxt->setText(filename);
690
691}
692
693
695{
696 QString filename = exportNameTxt->text();
697 if ( ! filename.isEmpty() ) {
698 okBtn->setEnabled(true);
699 }
700 else {
701 okBtn->setEnabled(false);
702 }
703
704 if( filename.endsWith( ".ogg" ) || filename.endsWith( ".OGG" ) ){
705 if( templateCombo->currentIndex() != 9 ){
706 templateCombo->setCurrentIndex( 9 );//ogg
707 }
708 }
709 else if( filename.endsWith( ".flac" ) || filename.endsWith( ".FLAC" ) ){
710 sampleRateLable->show();
711 sampleDepthLable->show();
712 if( templateCombo->currentIndex() != 8 ){
713 templateCombo->setCurrentIndex( 8 );//flac
714 }
715 }
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 );//aiff
721 }
722 }
723 else if( filename.endsWith( ".wav" ) || filename.endsWith( ".WAV" ) ){
724 sampleRateLable->show();
725 sampleDepthLable->show();
726 if( templateCombo->currentIndex() > 4 ){
727 templateCombo->setCurrentIndex( 0 );//wav
728
729 }
730 }
731}
732
734{
735 m_pProgressBar->setValue( nValue );
736 if ( nValue == 100 ) {
737
738 m_bExporting = false;
739
740 if( m_nInstrument == Hydrogen::get_instance()->getSong()->getInstrumentList()->size()){
741 m_nInstrument = 0;
742 m_bExportTrackouts = false;
743 }
744
745 if( m_bExportTrackouts ){
746 exportTracks();
747 }
748 }
749
750 if ( nValue < 100 ) {
751 closeBtn->setEnabled(false);
752 resampleComboBox->setEnabled(false);
753
754 }else
755 {
756 closeBtn->setEnabled(true);
757 resampleComboBox->setEnabled(true);
758 }
759}
760
762{
763 m_pPreferences->setRubberBandBatchMode(toggled);
764}
765
767{
768 m_pHydrogen->setIsTimelineActivated( toggled );
769}
770
775
777{
778 switch ( index ){
779 case 0:
780 m_pHydrogen->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Linear );
781 break;
782 case 1:
783 m_pHydrogen->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Cosine );
784 break;
785 case 2:
786 m_pHydrogen->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Third );
787 break;
788 case 3:
789 m_pHydrogen->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Cubic );
790 break;
791 case 4:
792 m_pHydrogen->getAudioEngine()->getSampler()->setInterpolateMode( Interpolation::InterpolateMode::Hermite );
793 break;
794 }
795}
796
798{
799 std::shared_ptr<Song> pSong = m_pHydrogen->getSong();
800 assert(pSong);
801
802 if(pSong){
803 auto pSongInstrList = pSong->getInstrumentList();
804 assert(pSongInstrList);
805 for ( unsigned nInstr = 0; nInstr < pSongInstrList->size(); ++nInstr ) {
806 auto pInstr = pSongInstrList->get( nInstr );
807 assert( pInstr );
808 if ( pInstr ){
809 for ( const auto& pCompo : *pInstr->get_components() ) {
810 for ( int nLayer = 0; nLayer < InstrumentComponent::getMaxLayers(); nLayer++ ) {
811 auto pLayer = pCompo->get_layer( nLayer );
812 if ( pLayer ) {
813 auto pSample = pLayer->get_sample();
814 if ( pSample != nullptr ) {
815 if( pSample->get_rubberband().use ) {
816 return true;
817 }
818 }
819 }
820 }
821 }
822 }
823 }
824 }
825 return false;
826}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:59
@ EXPORT_TO_BOTH
@ EXPORT_TO_SEPARATE_TRACKS
@ EXPORT_TO_SINGLE_TRACK
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.
Definition Pattern.h:285
static QString sLastFilename
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()
QString findUniqueExportFilenameForInstrument(std::shared_ptr< H2Core::Instrument > pInstrument)
void closeEvent(QCloseEvent *event) override
void on_exportNameTxt_textChanged(const QString &text)
void restoreSettingsFromPreferences()
ExportSongDialog(QWidget *parent)
InterpolateMode m_OldInterpolationMode
void resampleComboBoIndexChanged(int index)
void toggleTimeLineBPMMode(bool toggled)
H2Core::Hydrogen * m_pHydrogen
Custom file dialog checking whether the user has write access to the selected folder before allowing ...
Definition FileDialog.h:33
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
Definition Filesystem.h:87
Hydrogen Audio Engine.
Definition Hydrogen.h:54
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
A note plays an associated instrument with a velocity left and right pan.
Definition Note.h:102
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
Definition Note.h:500
Pattern class is a Note container.
Definition Pattern.h:46
const notes_t * get_notes() const
get the virtual pattern set
Definition Pattern.h:355
std::multimap< int, Note * > notes_t
< multimap note type
Definition Pattern.h:50
Manager for User Preferences File (singleton)
Definition Preferences.h:78
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setLastExportSongDirectory(QString sPath)
QString getLastExportSongDirectory() const
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
#define UNUSED(v)
Definition Globals.h:42