1 /*
2  * Hydrogen
3  * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4  *
5  * http://www.hydrogen-music.org
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY, without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 #include "AudioFileBrowser.h"
24 #include "../HydrogenApp.h"
25 #include "InstrumentEditor/InstrumentEditor.h"
26 #include "SampleWaveDisplay.h"
27 #include "../Widgets/Button.h"
28 #include "../Skin.h"
29 
30 #include <hydrogen/Preferences.h>
31 #include <hydrogen/basics/sample.h>
32 #include <hydrogen/audio_engine.h>
33 
34 #include <QModelIndex>
35 #include <QTreeWidget>
36 #include <QMessageBox>
37 
38 using namespace H2Core;
39 using namespace std;
40 
41 const char* AudioFileBrowser::__class_name = "AudioFileBrowser";
42 
AudioFileBrowser(QWidget * pParent,bool bAllowMultiSelect,bool bShowInstrumentManipulationControls)43 AudioFileBrowser::AudioFileBrowser ( QWidget* pParent, bool bAllowMultiSelect, bool bShowInstrumentManipulationControls)
44 		: QDialog ( pParent )
45 		, Object ( __class_name )
46 {
47 	setupUi ( this );
48 	INFOLOG ( "INIT" );
49 	setWindowTitle ( tr ( "Audio File Browser" ) );
50 	setFixedSize ( width(), height() );
51 
52 	m_bAllowMultiSelect = bAllowMultiSelect;
53 	m_bShowInstrumentManipulationControls = bShowInstrumentManipulationControls;
54 
55 	m_pDirModel = new QDirModel();
56 	m_pDirModel->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
57 	m_pDirModel->setNameFilters( QStringList() << "*.ogg" << "*.OGG" << "*.wav" << "*.WAV" << "*.flac"<< "*.FLAC" << "*.aiff" << "*.AIFF"<< "*.au" << "*.AU" );
58 	m_pDirModel->setSorting( QDir::DirsFirst |QDir::Name );
59 	m_ModelIndex = m_pDirModel->index( QDir::currentPath() );
60 
61 	m_pPlayBtn->setEnabled( false );
62 	m_pStopBtn->setEnabled( false );
63 	openBTN->setEnabled( false );
64 
65 	m_pTree = new QTreeView( treeView );
66 	m_pTree->setModel( m_pDirModel );
67 	m_pTree->resize( 799, 310 );
68 	m_pTree->header()->resizeSection( 0, 405 );
69 	m_pTree->setAlternatingRowColors( true );
70 	m_pTree->setRootIndex( m_pDirModel->index( Preferences::get_instance()->__lastsampleDirectory ) );
71 
72 	pathLineEdit->setText( Preferences::get_instance()->__lastsampleDirectory );
73 	m_pSampleFilename = "";
74 	m_pSelectedFile << "false" << "false";
75 
76 	m_sEmptySampleFilename = Filesystem::empty_sample_path();
77 
78 	m_pPathUptoolButton->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/go-up.png"));
79 	m_pPathUptoolButton->setToolTip( QString("Parent Folder"));
80 	m_pPathHometoolButton->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/go-home.png"));
81 	m_pPathHometoolButton->setToolTip( QString("Home"));
82 
83 	m_pPlayBtn->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/player_play.png"));
84 	m_pPlayBtn->setToolTip( QString("Play selected"));
85 	m_pStopBtn->setIcon( QIcon( Skin::getImagePath() + "/audiFileBrowser/player_stop.png"));
86 	m_pStopBtn->setToolTip( QString("Stop"));
87 
88 	m_pSampleWaveDisplay = new SampleWaveDisplay( waveformview );
89 	m_pSampleWaveDisplay->updateDisplay( m_sEmptySampleFilename );
90 	m_pSampleWaveDisplay->move( 3, 3 );
91 
92 	playSamplescheckBox->setChecked( Preferences::get_instance()->__playsamplesonclicking );
93 	//get the kde or gnome environment variable for mouse double or single clicking
94 	m_SingleClick = false;
95 	getEnvironment();
96 
97 	if( !m_bShowInstrumentManipulationControls ) {
98 		useNameCheckBox->hide();
99 		autoVelCheckBox->hide();
100 	}
101 
102 	connect( m_pTree, SIGNAL( clicked( const QModelIndex&) ), SLOT( clicked( const QModelIndex& ) ) );
103 	connect( m_pTree, SIGNAL( doubleClicked( const QModelIndex&) ), SLOT( doubleClicked( const QModelIndex& ) ) );
104 	connect( pathLineEdit, SIGNAL( returnPressed() ), SLOT( updateModelIndex() ) );
105 }
106 
107 
108 
~AudioFileBrowser()109 AudioFileBrowser::~AudioFileBrowser()
110 {
111 	Sample *pNewSample = Sample::load( m_sEmptySampleFilename );
112 	AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, 100 );
113 	INFOLOG ( "DESTROY" );
114 }
115 
116 
isFileSupported(QString filename)117 bool AudioFileBrowser::isFileSupported( QString filename )
118 {
119 	if 	(
120 		( filename.endsWith( ".ogg" ) ) ||
121 		( filename.endsWith( ".OGG" ) ) ||
122 		( filename.endsWith( ".wav" ) ) ||
123 		( filename.endsWith( ".WAV" ) ) ||
124 		( filename.endsWith( ".au" ) ) ||
125 		( filename.endsWith( ".AU" ) ) ||
126 		( filename.endsWith( ".aiff" ) ) ||
127 		( filename.endsWith( ".AIFF" ) ) ||
128 		( filename.endsWith( ".flac" ) ) ||
129 		( filename.endsWith( ".FLAC" ) )
130 		){
131 			return true;
132 		} else {
133 			return false;
134 		}
135 }
136 
137 
getEnvironment()138 void AudioFileBrowser::getEnvironment()
139 {
140 	QString desktopSession  = getenv("DESKTOP_SESSION");
141 //kde
142 	if( desktopSession == "kde" ) {
143 		QFile envfile( QDir::homePath() + "/.kde/share/config/kdeglobals");
144 
145 		if ( !envfile.open(QIODevice::ReadOnly | QIODevice::Text) ) {
146 			return;
147 		}
148 
149 		QTextStream envin( &envfile );
150 		while ( !envin.atEnd() ) {
151 			QString envLine = envin.readLine();
152 			if( envLine == QString("SingleClick=true" ) ) {
153 				m_SingleClick = true;
154 				break;
155 			}
156 		}
157 	}
158 
159 //for gnome, xfce and all others we use double click as default
160 }
161 
162 
163 
keyPressEvent(QKeyEvent * ev)164 void AudioFileBrowser::keyPressEvent (QKeyEvent *ev)
165 {
166 	if( ev->modifiers()==Qt::ControlModifier && m_bAllowMultiSelect) {
167 		m_pTree->setSelectionMode( QAbstractItemView::MultiSelection );
168 		openBTN->setEnabled( true );
169 	}
170 }
171 
172 
173 
keyReleaseEvent(QKeyEvent * ev)174 void AudioFileBrowser::keyReleaseEvent (QKeyEvent *ev)
175 {
176 	m_pTree->setSelectionMode( QAbstractItemView::SingleSelection );
177 }
178 
179 
180 
updateModelIndex()181 void AudioFileBrowser::updateModelIndex()
182 {
183 	QString toRemove;
184 	QString newPath = pathLineEdit->text();
185 
186 	if( QDir( newPath ).exists() ) {
187 		m_pTree->setRootIndex( m_pDirModel->index( newPath ) );
188 	} else {
189 		toRemove = newPath.section( '/', -1 );
190 //		QMessageBox::information ( this, "Hydrogen", newpath + toremove);
191 		newPath.replace( toRemove, "" );
192 		m_pTree->setRootIndex( m_pDirModel->index( newPath ) );
193 	}
194 }
195 
196 
197 
clicked(const QModelIndex & index)198 void AudioFileBrowser::clicked( const QModelIndex& index )
199 {
200 	QString path = m_pDirModel->filePath( index );
201 
202 	if( m_SingleClick ) {
203 		browseTree( index );
204 	}
205 
206 	if( isFileSupported( path ) ) {
207 		browseTree( index );
208 	}
209 }
210 
211 
212 
doubleClicked(const QModelIndex & index)213 void AudioFileBrowser::doubleClicked( const QModelIndex& index )
214 {
215 	if(!m_SingleClick) {
216 		browseTree( index );
217 	}
218 }
219 
220 
221 
browseTree(const QModelIndex & index)222 void AudioFileBrowser::browseTree( const QModelIndex& index )
223 {
224 
225 	QString path = m_pDirModel->filePath( index );
226 	pathLineEdit->setText( path );
227 	m_pSampleWaveDisplay->updateDisplay( m_sEmptySampleFilename );
228 
229 	updateModelIndex(); //with this you have a navigation like konqueror
230 
231 	if ( m_pDirModel->isDir( index ) ){
232 		m_pPlayBtn->setEnabled( false );
233 		openBTN->setEnabled( false );
234 		return;
235 	}
236 
237 	QString name = path.section( '/', -1 );
238 
239 	QString path2 = path;
240 	QString onlyPath = path;
241 	if ( name != "" ){
242 		onlyPath = path.replace( name, "" );
243 	}
244 
245 	name = name.left( '.' );
246 
247 	QString message = "Name: " + name;
248 	pathLineEdit->setText( onlyPath );
249 
250 	QStringList path2List = path2.split("/");
251 	QString fleTxt = path2List.last();
252 
253 	QApplication::setOverrideCursor(Qt::WaitCursor);
254 
255 	if( isFileSupported( path2 ) )
256 	{
257 
258 		filelineedit->setText( fleTxt );
259 		Sample *pNewSample = Sample::load( path2 );
260 
261 		if ( pNewSample ) {
262 			m_pNBytesLable->setText( tr( "Size: %1 bytes" ).arg( pNewSample->get_size() / 2 ) );
263 			m_pSamplerateLable->setText( tr( "Samplerate: %1" ).arg( pNewSample->get_sample_rate() ) );
264 			float sec = ( float )( pNewSample->get_frames() / (float)pNewSample->get_sample_rate() );
265 			QString qsec;
266 			qsec = QString::asprintf( "%2.2f", sec );
267 			m_pLengthLable->setText( tr( "Sample length: " ) + qsec + tr( " s" ) );
268 
269 			delete pNewSample;
270 			m_pSampleFilename = path2;
271 
272 			m_pSampleWaveDisplay->updateDisplay( path2 );
273 			m_pPlayBtn->setEnabled( true );
274 			openBTN->setEnabled( true );
275 
276 			//important this will only working correct if m_pSampleWaveDisplay->updateDisplay( file )
277 			//is ready with painting the wav file. else the playing sample get crackled sound!!
278 			if (playSamplescheckBox->isChecked()){
279 				if ( sec <= 600.00){
280 					on_m_pPlayBtn_clicked();
281 				}else
282 				{
283 					QMessageBox::information ( this, "Hydrogen", tr( "Please do not preview samples which are longer than 10 minutes!" )  );
284 				}
285 			}
286 			m_pNameLabel->setText( message );
287 		} else {
288 			openBTN->setEnabled( false );
289 			QMessageBox::information ( this, "Hydrogen", tr( "Unable to load that sample file." )  );
290 		}
291 
292 	}else{
293 		m_pNameLabel->setText( tr( "Name:"));
294 		m_pNBytesLable->setText( tr( "Size:" ) );
295 		m_pSamplerateLable->setText( tr( "Samplerate:" ) );
296 		m_pLengthLable->setText( tr( "Sample length:" ) );
297 		m_pSampleWaveDisplay->updateDisplay( m_sEmptySampleFilename );
298 		m_pPlayBtn->setEnabled( false );
299 		m_pStopBtn->setEnabled( false );
300 		openBTN->setEnabled( false );
301 		m_pSampleFilename = "";
302 	}
303 	QApplication::restoreOverrideCursor();
304 }
305 
306 
307 
on_m_pPlayBtn_clicked()308 void AudioFileBrowser::on_m_pPlayBtn_clicked()
309 {
310 
311 	if( QFile( m_pSampleFilename ).exists() == false ) {
312 		return;
313 	}
314 
315 	m_pStopBtn->setEnabled( true );
316 
317 	Sample *pNewSample = Sample::load( m_pSampleFilename );
318 	if ( pNewSample ) {
319 		assert(pNewSample->get_sample_rate() != 0);
320 
321 		int length = ( ( pNewSample->get_frames() / pNewSample->get_sample_rate() + 1) * 100 );
322 		AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, length );
323 	}
324 }
325 
326 
327 
on_m_pStopBtn_clicked()328 void AudioFileBrowser::on_m_pStopBtn_clicked()
329 {
330 	Sample *pNewSample = Sample::load( m_sEmptySampleFilename );
331 	AudioEngine::get_instance()->get_sampler()->preview_sample( pNewSample, 100 );
332 	m_pStopBtn->setEnabled( false );
333 }
334 
335 
336 
on_cancelBTN_clicked()337 void AudioFileBrowser::on_cancelBTN_clicked()
338 {
339 	Preferences::get_instance()->__lastsampleDirectory = pathLineEdit->text();
340 	m_pSelectedFile << "false" << "false" << "";
341 	reject();
342 }
343 
344 
345 
on_openBTN_clicked()346 void AudioFileBrowser::on_openBTN_clicked()
347 {
348 	if( m_pTree->selectionModel()->selectedRows().size() > 0) {
349 		QList<QModelIndex>::iterator i;
350 		QList<QModelIndex> list = m_pTree->selectionModel()->selectedRows();
351 
352 		for (i = list.begin(); i != list.end(); ++i) {
353 			QString path2 = (*i).data().toString();
354 			if( isFileSupported( path2 ) ){
355 				QString path = pathLineEdit->text();
356 
357 				if(! path.endsWith("/")) {
358 					path = path + "/";
359 				}
360 
361 				QString act_filename = path + path2;
362 				m_pSelectedFile << act_filename ;
363 			}
364 		}
365 	}
366 
367 	Preferences::get_instance()->__lastsampleDirectory = pathLineEdit->text();
368 	accept();
369 }
370 
371 
372 
on_playSamplescheckBox_clicked()373 void AudioFileBrowser::on_playSamplescheckBox_clicked()
374 {
375 	Preferences::get_instance()->__playsamplesonclicking = playSamplescheckBox->isChecked();
376 }
377 
378 
379 
getSelectedFiles()380 QStringList AudioFileBrowser::getSelectedFiles()
381 {
382 	if ( useNameCheckBox->isChecked() ) {
383 		m_pSelectedFile[0] = "true";
384 	}
385 	if ( autoVelCheckBox->isChecked() ) {
386 		m_pSelectedFile[1] = "true";
387 	}
388 	return m_pSelectedFile;
389 }
390 
391 
392 
on_m_pPathHometoolButton_clicked()393 void AudioFileBrowser::on_m_pPathHometoolButton_clicked()
394 {
395 
396 	QString path = pathLineEdit->text();
397 	QStringList pathlist = path.split("/");
398 
399 	while( path != QDir::rootPath() ){
400 
401 		if( pathlist.isEmpty () ) {
402 			break;
403 		}
404 
405 		pathlist.removeLast();
406 		QString updir = pathlist.join("/");
407 
408 		pathLineEdit->setText( updir );
409 		m_pTree->setRootIndex( m_pDirModel->index( updir ) );
410 		m_pTree->collapse( m_pDirModel->index( updir  ) );
411 		m_pTree->setExpanded( m_pDirModel->index(updir), false  );
412 		path = pathLineEdit->text();
413 	}
414 
415 	pathLineEdit->setText( QDir::homePath() );
416 	m_pTree->setRootIndex( m_pDirModel->index( QDir::homePath() ) );
417 
418 	m_pTree->collapse( m_pDirModel->index( QDir::homePath())  );
419 }
420 
421 
422 
on_m_pPathUptoolButton_clicked()423 void AudioFileBrowser::on_m_pPathUptoolButton_clicked()
424 {
425 	QString path = pathLineEdit->text();
426 	QStringList pathlist = path.split("/");
427 
428 	if( pathlist.isEmpty () ) {
429 		return;
430 	}
431 
432 	if( path.endsWith( "/" ) ) {
433 		pathlist.removeLast();
434 		QString tmpupdir = pathlist.join("/");
435 		m_pTree->setRootIndex( m_pDirModel->index( tmpupdir ) );
436 		m_pTree->collapse( m_pDirModel->index( tmpupdir  ) );
437 		m_pTree->setExpanded( m_pDirModel->index( tmpupdir ), false  );
438 	}
439 
440 	pathlist.removeLast();
441 
442 	QString updir = pathlist.join("/");
443 	if ( updir == "" ) {
444 		pathLineEdit->setText( QString("/") );
445 	} else {
446 		pathLineEdit->setText( updir );
447 	}
448 
449 	m_pTree->setRootIndex( m_pDirModel->index( updir ) );
450 	m_pTree->collapse( m_pDirModel->index( updir  ) );
451 	m_pTree->setExpanded( m_pDirModel->index(updir), false  );
452 }
453 
454 
455 
on_hiddenCB_clicked()456 void AudioFileBrowser::on_hiddenCB_clicked()
457 {
458 	if ( hiddenCB->isChecked() ) {
459 		m_pDirModel->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden );
460 	} else {
461 		m_pDirModel->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
462 		m_pTree->setRootIndex( m_pDirModel->index( pathLineEdit->text() ) );
463 	}
464 }
465