hydrogen 1.2.3
Filesystem.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 <core/Basics/Drumkit.h>
24#include <core/config.h>
25#include <core/EventQueue.h>
27#include <core/Hydrogen.h>
29
30#include <QtCore/QDir>
31#include <QtCore/QFile>
32#include <QtCore/QFileInfo>
33#include <QtCore/QCoreApplication>
34#include <QDateTime>
35
36#ifdef H2CORE_HAVE_OSC
37#include <core/NsmClient.h>
38#endif
39
40// directories
41#define LOCAL_DATA_PATH "data/"
42#define CACHE "cache/"
43#define DEMOS "demo_songs/"
44#define DOC "doc/"
45#define DRUMKITS "drumkits/"
46#define I18N "i18n/"
47#define IMG "img/"
48#define PATTERNS "patterns/"
49#define PLAYLISTS "playlists/"
50#define PLUGINS "plugins/"
51#define REPOSITORIES "repositories/"
52#define SCRIPTS "scripts/"
53#define SONGS "songs/"
54#define THEMES "themes/"
55#define TMP "hydrogen/"
56#define XSD "xsd/"
57
58
59// files
61#define CLICK_SAMPLE "click.wav"
62#define EMPTY_SAMPLE "emptySample.wav"
63#define DEFAULT_SONG "DefaultSong"
64#define EMPTY_SONG_BASE "emptySong"
65#define USR_CONFIG "hydrogen.conf"
66#define SYS_CONFIG "hydrogen.default.conf"
67#define LOG_FILE "hydrogen.log"
68#define DRUMKIT_XML "drumkit.xml"
69#define DRUMKIT_XSD "drumkit.xsd"
70#define DRUMPAT_XSD "drumkit_pattern.xsd"
71#define DRUMKIT_DEFAULT_KIT "GMRockKit"
72#define PLAYLIST_XSD "playlist.xsd"
73
74#define AUTOSAVE "autosave"
75
76#define UNTITLED_SONG "Untitled Song"
77#define UNTITLED_PLAYLIST "untitled.h2playlist"
78
79// filters
80#define PATTERN_FILTER "*.h2pattern"
81#define PLAYLIST_FILTER "*.h2playlist"
82#define SONG_FILTER "*.h2song"
83#define THEME_FILTER "*.h2theme"
84
85namespace H2Core
86{
87
88Logger* Filesystem::__logger = nullptr;
89
90const QString Filesystem::scripts_ext = ".sh";
91const QString Filesystem::songs_ext = ".h2song";
92const QString Filesystem::themes_ext = ".h2theme";
93const QString Filesystem::patterns_ext = ".h2pattern";
94const QString Filesystem::playlist_ext = ".h2playlist";
95const QString Filesystem::drumkit_ext = ".h2drumkit";
96const QString Filesystem::scripts_filter_name = "Hydrogen Scripts (*.sh)";
97const QString Filesystem::songs_filter_name = "Hydrogen Songs (*.h2song)";
98const QString Filesystem::themes_filter_name = "Hydrogen Theme (*.h2theme)";
99const QString Filesystem::patterns_filter_name = "Hydrogen Patterns (*.h2pattern)";
100const QString Filesystem::playlists_filter_name = "Hydrogen Playlists (*.h2playlist)";
101
105
106#ifdef Q_OS_MACX
107 QString Filesystem::__usr_log_path =QDir::homePath().append( "/Library/Application Support/Hydrogen/" LOG_FILE );
108#elif WIN32
109 QString Filesystem::__usr_log_path = QDir::homePath().append( "/.hydrogen/" LOG_FILE );
110#else
111 QString Filesystem::__usr_log_path = QDir::homePath().append( "/" H2_USR_PATH "/" LOG_FILE);
112#endif
113
114
116
118
119/* TODO QCoreApplication is not instantiated */
120bool Filesystem::bootstrap( Logger* logger, const QString& sys_path )
121{
122 if( __logger==nullptr && logger!=nullptr ) {
124 } else {
125 return false;
126 }
127
128#ifdef Q_OS_MACX
129#ifdef H2CORE_HAVE_BUNDLE
130 // Bundle: Prepare hydrogen to use path names which are used in app bundles: http://en.wikipedia.org/wiki/Application_Bundle
131 __sys_data_path = QCoreApplication::applicationDirPath().append( "/../Resources/data/" ) ;
132#else
133 __sys_data_path = QCoreApplication::applicationDirPath().append( "/data/" ) ;
134#endif
135 __usr_data_path = QDir::homePath().append( "/Library/Application Support/Hydrogen/data/" );
136 __usr_cfg_path = QDir::homePath().append( "/Library/Application Support/Hydrogen/" USR_CONFIG );
137#elif WIN32
138 __sys_data_path = QCoreApplication::applicationDirPath().append( "/data/" ) ;
139 __usr_data_path = QDir::homePath().append( "/.hydrogen/data/" ) ;
140 __usr_cfg_path = QDir::homePath().append( "/.hydrogen/" USR_CONFIG ) ;
141#else
142#ifdef H2CORE_HAVE_APPIMAGE
143 __sys_data_path = absolute_path( QCoreApplication::applicationDirPath().append( "/../share/hydrogen/data/" ) ) ;
144#else
145 __sys_data_path = H2_SYS_PATH "/data/";
146#endif
147 __usr_data_path = QDir::homePath().append( "/" H2_USR_PATH "/data/" );
148 __usr_cfg_path = QDir::homePath().append( "/" H2_USR_PATH "/" USR_CONFIG );
149#endif
150 if( sys_path!=nullptr ) __sys_data_path = sys_path;
151
152 if( !dir_readable( __sys_data_path ) ) {
153 __sys_data_path = QCoreApplication::applicationDirPath().append( "/" LOCAL_DATA_PATH );
154 ERRORLOG( QString( "will use local data path : %1" ).arg( __sys_data_path ) );
155 }
156
157 char* ladspaPath = getenv( "LADSPA_PATH" );
158 if ( ladspaPath ) {
159 INFOLOG( "Found LADSPA_PATH environment variable" );
160 QString sLadspaPath = QString::fromLocal8Bit( ladspaPath );
161 int pos;
162 while ( ( pos = sLadspaPath.indexOf( ":" ) ) != -1 ) {
163 QString sPath = sLadspaPath.left( pos );
164 __ladspa_paths << QFileInfo(sPath).canonicalFilePath();
165 sLadspaPath = sLadspaPath.mid( pos + 1, sLadspaPath.length() );
166 }
167 __ladspa_paths << QFileInfo( sLadspaPath ).canonicalFilePath();
168 } else {
169#ifdef Q_OS_MACX
170 __ladspa_paths << QFileInfo( QCoreApplication::applicationDirPath(), "/../Resources/plugins" ).canonicalFilePath();
171 __ladspa_paths << QFileInfo( "/Library/Audio/Plug-Ins/LADSPA/" ).canonicalFilePath();
172 __ladspa_paths << QFileInfo( QDir::homePath(), "/Library/Audio/Plug-Ins/LADSPA" ).canonicalFilePath();
173#else
174 __ladspa_paths << QFileInfo( "/usr/lib/ladspa" ).canonicalFilePath();
175 __ladspa_paths << QFileInfo( "/usr/local/lib/ladspa" ).canonicalFilePath();
176 __ladspa_paths << QFileInfo( "/usr/lib64/ladspa" ).canonicalFilePath();
177 __ladspa_paths << QFileInfo( "/usr/local/lib64/ladspa" ).canonicalFilePath();
178#endif
179 }
180 __ladspa_paths.sort();
181 __ladspa_paths.removeDuplicates();
182 if ( !__ladspa_paths.isEmpty() && __ladspa_paths.at( 0 ).isEmpty() ) {
183 __ladspa_paths.removeFirst();
184 }
185 // we want this first
187 __ladspa_paths.removeDuplicates();
188
189 bool ret = check_sys_paths();
190 ret &= check_usr_paths();
191 info();
192 return ret;
193}
194
195bool Filesystem::check_permissions( const QString& path, const int perms, bool silent )
196{
197 QFileInfo fi( path );
198 if( ( perms & is_file ) && ( perms & is_writable ) && !fi.exists() ) {
199 QFileInfo folder( path.left( path.lastIndexOf( "/" ) ) );
200 if( !folder.isDir() ) {
201 if( !silent ) {
202 ERRORLOG( QString( "%1 is not a directory" ).arg( folder.fileName() ) );
203 }
204 return false;
205 }
206 if( !folder.isWritable() ) {
207 if( !silent ) {
208 ERRORLOG( QString( "%1 is not writable" ).arg( folder.fileName() ) );
209 }
210 return false;
211 }
212 return true;
213 }
214 if( ( perms & is_dir ) && !fi.isDir() ) {
215 if( !silent ) {
216 ERRORLOG( QString( "%1 is not a directory" ).arg( path ) );
217 }
218 return false;
219 }
220 if( ( perms & is_file ) && !fi.isFile() ) {
221 if( !silent ) {
222 ERRORLOG( QString( "%1 is not a file" ).arg( path ) );
223 }
224 return false;
225 }
226 if( ( perms & is_readable ) && !fi.isReadable() ) {
227 if( !silent ) {
228 ERRORLOG( QString( "%1 is not readable" ).arg( path ) );
229 }
230 return false;
231 }
232 if( ( perms & is_writable ) && !fi.isWritable() ) {
233 if( !silent ) {
234 ERRORLOG( QString( "%1 is not writable" ).arg( path ) );
235 }
236 return false;
237 }
238 if( ( perms & is_executable ) && !fi.isExecutable() ) {
239 if( !silent ) {
240 ERRORLOG( QString( "%1 is not executable" ).arg( path ) );
241 }
242 return false;
243 }
244 return true;
245}
246
247bool Filesystem::file_exists( const QString& path, bool silent )
248{
249 return check_permissions( path, is_file, silent );
250}
251bool Filesystem::file_readable( const QString& path, bool silent )
252{
253 return check_permissions( path, is_file|is_readable, silent );
254}
255bool Filesystem::file_writable( const QString& path, bool silent )
256{
257 return check_permissions( path, is_file|is_readable|is_writable, silent );
258}
259bool Filesystem::file_executable( const QString& path, bool silent )
260{
261 return check_permissions( path, is_file|is_executable, silent );
262}
263bool Filesystem::dir_exists( const QString& path, bool silent )
264{
265 return check_permissions( path, is_dir, silent );
266}
267bool Filesystem::dir_readable( const QString& path, bool silent )
268{
269 return check_permissions( path, is_dir|is_readable|is_executable, silent );
270}
271bool Filesystem::dir_writable( const QString& path, bool silent )
272{
273 return check_permissions( path, is_dir|is_writable, silent );
274}
275
276bool Filesystem::mkdir( const QString& path )
277{
278 if ( !QDir( "/" ).mkpath( QDir( path ).absolutePath() ) ) {
279 ERRORLOG( QString( "unable to create directory : %1" ).arg( path ) );
280 return false;
281 }
282 return true;
283}
284
285bool Filesystem::path_usable( const QString& path, bool create, bool silent )
286{
287 if ( !QDir( path ).exists() ) {
288 if ( !silent ) {
289 INFOLOG( QString( "create user directory : %1" ).arg( path ) );
290 }
291 if ( create && !QDir( "/" ).mkpath( path ) ) {
292 ERRORLOG( QString( "unable to create user directory : %1" ).arg( path ) );
293 return false;
294 }
295 }
296 return dir_readable( path, silent ) && dir_writable( path, silent );
297}
298
299bool Filesystem::write_to_file( const QString& dst, const QString& content )
300{
301 if ( !file_writable( dst ) ) {
302 ERRORLOG( QString( "unable to write to %1" ).arg( dst ) );
303 return false;
304 }
305 QFile file( dst );
306 if ( !file.open( QIODevice::WriteOnly ) ) {
307 ERRORLOG( QString( "unable to write to %1" ).arg( dst ) );
308 return false;
309 }
310 file.write( content.toUtf8().data() );
311 file.close();
312
313 return true;
314}
315
316bool Filesystem::file_copy( const QString& src, const QString& dst, bool overwrite, bool bSilent )
317{
318 if( !overwrite && file_exists( dst, true ) ) {
319 WARNINGLOG( QString( "do not overwrite %1 with %2 as it already exists" ).arg( dst ).arg( src ) );
320 return true;
321 }
322 if ( !file_readable( src ) ) {
323 ERRORLOG( QString( "unable to copy %1 to %2, %1 is not readable" ).arg( src ).arg( dst ) );
324 return false;
325 }
326 if ( !file_writable( dst ) ) {
327 ERRORLOG( QString( "unable to copy %1 to %2, %2 is not writable" ).arg( src ).arg( dst ) );
328 return false;
329 }
330 if ( ! bSilent ) {
331 INFOLOG( QString( "copy %1 to %2" ).arg( src ).arg( dst ) );
332 }
333
334 // Since QFile::copy does not overwrite, we have to make sure the
335 // destination does not exist.
336 if ( overwrite && file_exists( dst, true ) ) {
337 rm( dst, true, bSilent );
338 }
339
340 return QFile::copy( src, dst );
341}
342
343bool Filesystem::rm( const QString& path, bool recursive, bool bSilent )
344{
345 if ( check_permissions( path, is_file, true ) ) {
346 QFile file( path );
347 bool ret = file.remove();
348 if( !ret ) {
349 ERRORLOG( QString( "unable to remove file %1" ).arg( path ) );
350 }
351 return ret;
352 }
353 if ( !check_permissions( path, is_dir, true ) ) {
354 ERRORLOG( QString( "%1 is neither a file nor a directory ?!?!" ).arg( path ) );
355 return false;
356 }
357 if ( !recursive ) {
358 QDir dir;
359 bool ret = dir.rmdir( path );
360 if( !ret ) {
361 ERRORLOG( QString( "unable to remove dir %1 without recursive argument, maybe it is not empty?" ).arg( path ) );
362 }
363 return ret;
364 }
365 return rm_fr( path, bSilent );
366}
367
368bool Filesystem::rm_fr( const QString& path, bool bSilent )
369{
370 if ( ! bSilent ) {
371 INFOLOG( QString( "Removing [%1] recursively" ).arg( path ) );
372 }
373
374 bool ret = true;
375 QDir dir( path );
376 QFileInfoList entries = dir.entryInfoList( QDir::NoDotAndDotDot | QDir::AllEntries );
377 for ( int idx = 0; ( ( idx < entries.size() ) && ret ); idx++ ) {
378 QFileInfo entryInfo = entries[idx];
379 if ( entryInfo.isDir() && !entryInfo.isSymLink() ) {
380 ret = rm_fr( entryInfo.absoluteFilePath(), bSilent );
381 } else {
382 QFile file( entryInfo.absoluteFilePath() );
383 if ( !file.remove() ) {
384 ERRORLOG( QString( "unable to remove %1" ).arg( entryInfo.absoluteFilePath() ) );
385 ret = false;
386 }
387 }
388 }
389 if ( !dir.rmdir( dir.absolutePath() ) ) {
390 ERRORLOG( QString( "unable to remove %1" ).arg( dir.absolutePath() ) );
391 ret = false;
392 }
393 return ret;
394}
395
397{
398 bool ret = true;
399 if( !dir_readable( __sys_data_path ) ) ret = false;
400 if( !file_readable( click_file_path() ) ) ret = false;
401 if( !dir_readable( demos_dir() ) ) ret = false;
402 /* if( !dir_readable( doc_dir() ) ) ret = false; */ // FIXME
403 if( !dir_readable( sys_drumkits_dir() ) ) ret = false;
404 if( !file_readable( empty_sample_path() ) ) ret = false;
405 if( !file_readable( sys_config_path() ) ) ret = false;
406 if( !dir_readable( i18n_dir() ) ) ret = false;
407 if( !dir_readable( img_dir() ) ) ret = false;
408 if( !dir_readable( sys_theme_dir() ) ) ret = false;
409 if( !dir_readable( xsd_dir() ) ) ret = false;
410 if( !file_readable( pattern_xsd_path() ) ) ret = false;
411 if( !file_readable( drumkit_xsd_path() ) ) ret = false;
412 if( !file_readable( playlist_xsd_path() ) ) ret = false;
413
414 if ( ret ) {
415 INFOLOG( QString( "system wide data path %1 is usable." ).arg( __sys_data_path ) );
416 }
417
418 return ret;
419}
420
421
423{
424 bool ret = true;
425 if( !path_usable( tmp_dir() ) ) ret = false;
426 if( !path_usable( __usr_data_path ) ) ret = false;
427 if( !path_usable( cache_dir() ) ) ret = false;
428 if( !path_usable( repositories_cache_dir() ) ) ret = false;
429 if( !path_usable( usr_drumkits_dir() ) ) ret = false;
430 if( !path_usable( patterns_dir() ) ) ret = false;
431 if( !path_usable( playlists_dir() ) ) ret = false;
432 if( !path_usable( plugins_dir() ) ) ret = false;
433 if( !path_usable( scripts_dir() ) ) ret = false;
434 if( !path_usable( songs_dir() ) ) ret = false;
435 if( file_exists( empty_song_path(), true ) ) ret = false;
436 if( !path_usable( usr_theme_dir() ) ) ret = false;
437 if( !file_writable( usr_config_path() ) ) ret = false;
438
439 if ( ret ) {
440 INFOLOG( QString( "user path %1 is usable." ).arg( __usr_data_path ) );
441 }
442
443 return ret;
444}
445
447{
448 return __sys_data_path;
449}
451{
452 return __usr_data_path;
453}
454
456{
457 return __ladspa_paths;
458}
459
460// FILES
466{
467 return __usr_cfg_path;
468}
473
475 return DEFAULT_SONG;
476}
477
479 QString sPathBase( __usr_data_path + EMPTY_SONG_BASE );
480 QString sPath( sPathBase + Filesystem::songs_ext );
481
482 int nIterations = 0;
483 while ( file_exists( sPath, true ) ) {
484 sPath = sPathBase + QString::number( nIterations ) + Filesystem::songs_ext;
485 ++nIterations;
486
487 if ( nIterations > 1000 ) {
488 ERRORLOG( "That's a bit much. Something is wrong in here." );
491 }
492 }
493
494 return sPath;
495}
496
498{
499 return UNTITLED_SONG;
500}
515{
516 return DRUMKIT_XSD;
517}
519{
520 return xsd_dir() + DRUMKIT_XSD;
521}
523{
524 return xsd_dir() + DRUMPAT_XSD;
525}
527{
528 return xsd_dir() + PLAYLIST_XSD;
529}
531{
532 return __usr_log_path;
533}
534
535// DIRS
537{
538 return __sys_data_path + IMG;
539}
541{
542 return __sys_data_path + DOC;
543}
545{
546 return __sys_data_path + I18N;
547}
549{
550 return __usr_data_path + SCRIPTS;
551}
553{
554 return __usr_data_path + SONGS;
555}
557{
558 return __usr_data_path + THEMES;
559}
561{
562 return __sys_data_path + THEMES;
563}
564QString Filesystem::song_path( const QString& sg_name )
565{
566 return QString( songs_dir() + sg_name + songs_ext );
567}
569{
570 return __usr_data_path + PATTERNS;
571}
572QString Filesystem::patterns_dir( const QString& dk_name )
573{
574 return __usr_data_path + PATTERNS + dk_name + "/";
575}
576QString Filesystem::pattern_path( const QString& dk_name, const QString& p_name )
577{
578 if ( dk_name.isEmpty() ) {
579 return patterns_dir() + p_name + patterns_ext;
580 } else {
581 return patterns_dir( dk_name ) + p_name + patterns_ext;
582 }
583}
585{
586 return __usr_data_path + PLUGINS;
587}
589{
590 return __sys_data_path + DRUMKITS;
591}
593{
594 return __usr_data_path + DRUMKITS;
595}
597{
598 return __usr_data_path + PLAYLISTS;
599}
600QString Filesystem::playlist_path( const QString& pl_name )
601{
602 return patterns_dir() + pl_name + playlist_ext;
603}
605{
606 return __usr_data_path + CACHE;
607}
613{
614 return __sys_data_path + DEMOS;
615}
617{
618 return __sys_data_path + XSD;
619}
621{
622 return xsd_dir() + "legacy";
623}
625{
626 return QDir::tempPath() + "/" + TMP;
627}
628QString Filesystem::tmp_file_path( const QString &base )
629{
630 // Ensure template base will produce a valid filename
631 QString validBase = base;
632 validBase.remove( QRegExp( "[^a-zA-Z0-9._]" ) );
633
634 QFileInfo f( validBase );
635 QString templateName( tmp_dir() + "/" );
636 if ( f.suffix().isEmpty() ) {
637 templateName += validBase.left( 20 );
638 } else {
639 templateName += f.completeBaseName().left( 20 ) + "-XXXXXX." + f.suffix();
640 }
641 QTemporaryFile file( templateName);
642 file.setAutoRemove( false );
643 file.open();
644 file.close();
645 return file.fileName();
646}
647
648// DRUMKITS
649QStringList Filesystem::drumkit_list( const QString& path )
650{
651 QStringList ok;
652 QStringList possible = QDir( path ).entryList( QDir::Dirs | QDir::Readable | QDir::NoDotAndDotDot );
653 foreach ( const QString& dk, possible ) {
654 if ( drumkit_valid( path + dk ) ) {
655 ok << dk;
656 } else {
657 ERRORLOG( QString( "drumkit %1 is not usable" ).arg( dk ) );
658 }
659 }
660 return ok;
661}
663 QString sDefaultPath = sys_drumkits_dir() + DRUMKIT_DEFAULT_KIT;
664
665 // GMRockKit does not exist at system-level? Let's pick another
666 // one.
667 if ( ! drumkit_valid( sDefaultPath ) ) {
668 for ( const auto& sDrumkitName : Filesystem::sys_drumkit_list() ) {
669 if ( drumkit_valid( Filesystem::sys_drumkits_dir() + sDrumkitName ) ) {
670 sDefaultPath = Filesystem::sys_drumkits_dir() + sDrumkitName;
671 break;
672 }
673 }
674 }
675
676 // There is no drumkit at system-level? Let's pick one from user-space.
677 if ( ! drumkit_valid( sDefaultPath ) ) {
678 for ( const auto& sDrumkitName : Filesystem::usr_drumkit_list() ) {
679 if ( drumkit_valid( Filesystem::usr_drumkits_dir() + sDrumkitName ) ) {
680 sDefaultPath = Filesystem::usr_drumkits_dir() + sDrumkitName;
681 break;
682 }
683 }
684 }
685
686 return sDefaultPath;
687}
688
690{
691 return drumkit_list( sys_drumkits_dir() ) ;
692}
694{
695 return drumkit_list( usr_drumkits_dir() ) ;
696}
697
698QString Filesystem::prepare_sample_path( const QString& fname )
699{
700 int idx = get_basename_idx_under_drumkit( fname );
701 if ( idx >= 0 ) {
702 return fname.midRef( idx ).toString();
703 }
704 return fname;
705}
706
707bool Filesystem::file_is_under_drumkit( const QString& fname )
708{
709 return get_basename_idx_under_drumkit( fname ) != -1;
710}
711
713{
714 if( fname.startsWith( usr_drumkits_dir() ) )
715 {
716 int start = usr_drumkits_dir().size();
717 int index = fname.indexOf( "/", start );
718 QString dk_name = fname.midRef( start , index - start).toString();
719 if ( usr_drumkit_list().contains( dk_name ) ) {
720 return index + 1;
721 }
722 }
723
724 if( fname.startsWith( sys_drumkits_dir() ) )
725 {
726 int start = sys_drumkits_dir().size();
727 int index = fname.indexOf( "/", start);
728 QString dk_name = fname.midRef( start, index - start).toString();
729 if ( sys_drumkit_list().contains( dk_name ) ) {
730 return index + 1;
731 }
732 }
733
734 return -1;
735}
736
737
738bool Filesystem::drumkit_exists( const QString& dk_name )
739{
740 if( usr_drumkit_list().contains( dk_name ) ) return true;
741 return sys_drumkit_list().contains( dk_name );
742}
743QString Filesystem::drumkit_usr_path( const QString& dk_name )
744{
745 return usr_drumkits_dir() + dk_name;
746}
747QString Filesystem::drumkit_path_search( const QString& dk_name, Lookup lookup, bool bSilent )
748{
749
750#ifdef H2CORE_HAVE_OSC
751 // When under session management the drumkit can also be located
752 // in - apart from the user and system path - a particular session
753 // folder. If it couldn't be found in there (or the found drumkit
754 // does not match `dk_name`), the session folder is skipped and
755 // the user and system paths will be traversed instead.
756 if ( Hydrogen::get_instance()->isUnderSessionManagement() ) {
757
758 QString sDrumkitPath = QString( "%1/%2" )
759 .arg( NsmClient::get_instance()->getSessionFolderPath() )
760 .arg( "drumkit" );
761
762 // If the path is symbolic link, dereference it.
763 QFileInfo drumkitPathInfo( sDrumkitPath );
764 if ( drumkitPathInfo.isSymLink() ) {
765 sDrumkitPath = drumkitPathInfo.symLinkTarget();
766 }
767
768 // Check whether the local drumkit does hold the right
769 // drumkit (using its name).
770 QString sDrumkitXMLPath = QString( "%1/%2" )
771 .arg( sDrumkitPath ).arg( "drumkit.xml" );
772
773 QString sSessionDrumkitName( "seemsLikeTheKitCouldNotBeRetrievedFromTheDatabase" );
774 auto pSoundLibraryDatabase = Hydrogen::get_instance()->getSoundLibraryDatabase();
775 if ( pSoundLibraryDatabase != nullptr ) {
776 auto pDrumkit = pSoundLibraryDatabase->getDrumkit( sDrumkitPath );
777 if ( pDrumkit != nullptr ) {
778 sSessionDrumkitName = pDrumkit->get_name();
779 }
780 }
781
782 if ( dk_name == sSessionDrumkitName ) {
783 // The local drumkit seems legit.
784 return sDrumkitPath;
785 }
786 else if ( ! bSilent ) {
787 NsmClient::printError( QString( "Local drumkit [%1] name [%2] and the one stored in .h2song file [%3] do not match!" )
788 .arg( sDrumkitXMLPath )
789 .arg( sSessionDrumkitName )
790 .arg( dk_name ) );
791 }
792 }
793
794#endif
795
796 if ( lookup == Lookup::stacked || lookup == Lookup::user ) {
797 if ( usr_drumkit_list().contains( dk_name ) ){
798 return usr_drumkits_dir() + dk_name;
799 }
800 }
801
802 if ( lookup == Lookup::stacked || lookup == Lookup::system ) {
803 if( sys_drumkit_list().contains( dk_name ) ){
804 return sys_drumkits_dir() + dk_name;
805 }
806 }
807
808 if ( ! bSilent ) {
809 ERRORLOG( QString( "drumkit [%1] not found using lookup type [%2]" )
810 .arg( dk_name )
811 .arg( static_cast<int>(lookup)));
812 }
813
814 return QString("");
815}
816
817QString Filesystem::drumkit_dir_search( const QString& dk_name, Lookup lookup )
818{
819 if ( lookup == Lookup::user || lookup == Lookup::stacked ) {
820 if ( usr_drumkit_list().contains( dk_name ) ) {
821 return usr_drumkits_dir();
822 }
823 }
824 if ( lookup == Lookup::system || lookup == Lookup::stacked ) {
825 if( sys_drumkit_list().contains( dk_name ) ) {
826 return sys_drumkits_dir();
827 }
828 }
829 ERRORLOG( QString( "drumkit %1 not found with lookup mode [%2]" )
830 .arg( dk_name ).arg( static_cast<int>(lookup) ) );
831 return "";
832}
833bool Filesystem::drumkit_valid( const QString& dk_path )
834{
835#ifdef H2CORE_HAVE_OSC
836 auto pHydrogen = Hydrogen::get_instance();
837 if ( pHydrogen != nullptr &&
838 pHydrogen->isUnderSessionManagement() ) {
839
840 // Explicit handling for relative drumkit paths supported in
841 // the session management.
842 QFileInfo info( dk_path );
843 if ( info.isRelative() ) {
844 QString sAbsoluteDrumkitPath = QString( "%1%2" )
845 .arg( NsmClient::get_instance()->getSessionFolderPath() )
846 // remove the leading dot indicating that the path is relative.
847 .arg( dk_path.right( dk_path.size() - 1 ) );
848
849 QFileInfo infoAbs( sAbsoluteDrumkitPath );
850 if ( infoAbs.isSymLink() ) {
851 sAbsoluteDrumkitPath = infoAbs.symLinkTarget();
852 }
853
854 return file_readable( sAbsoluteDrumkitPath + "/" +
855 DRUMKIT_XML, true );
856 }
857 }
858#endif
859
860 return file_readable( dk_path + "/" + DRUMKIT_XML, true);
861}
862QString Filesystem::drumkit_file( const QString& dk_path )
863{
864 return dk_path + "/" + DRUMKIT_XML;
865}
866
868 return DRUMKIT_XML;
869}
870
871QString Filesystem::drumkit_backup_path( const QString& dk_path ) {
872 return dk_path + "." +
873 QDateTime::currentDateTime().toString( "yyyy-MM-dd_hh-mm-ss" ) + ".bak";
874}
875
876// PATTERNS
878{
879 return QDir( patterns_dir() ).entryList( QDir::Dirs | QDir::Readable | QDir::NoDotAndDotDot );
880}
881
883{
884 return pattern_list( patterns_dir() );
885}
886
887QStringList Filesystem::pattern_list( const QString& path)
888{
889 return QDir( path ).entryList( QStringList( PATTERN_FILTER ), QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
890}
891
892// SONGS
894{
895 return QDir( songs_dir() ).entryList( QStringList( SONG_FILTER ), QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
896}
897
899{
900 QStringList result;
901 foreach ( const QString& str, song_list() ) {
902 if ( !str.contains( AUTOSAVE ) ) {
903 result += str;
904 }
905 }
906 return result;
907}
908
909bool Filesystem::song_exists( const QString& sg_name )
910{
911 return QDir( songs_dir() ).exists( sg_name );
912}
913
914bool Filesystem::isSongPathValid( const QString& sSongPath, bool bCheckExistance ) {
915
916 QFileInfo songFileInfo = QFileInfo( sSongPath );
917
918 if ( !songFileInfo.isAbsolute() ) {
919 ERRORLOG( QString( "Error: Unable to handle path [%1]. Please provide an absolute file path!" )
920 .arg( sSongPath.toLocal8Bit().data() ));
921 return false;
922 }
923
924 if ( songFileInfo.exists() ) {
925 if ( !songFileInfo.isReadable() ) {
926 ERRORLOG( QString( "Unable to handle path [%1]. You must have permissions to read the file!" )
927 .arg( sSongPath.toLocal8Bit().data() ));
928 return false;
929 }
930 if ( !songFileInfo.isWritable() ) {
931 WARNINGLOG( QString( "You don't have permissions to write to the Song found in path [%1]. It will be opened as read-only (no autosave)." )
932 .arg( sSongPath.toLocal8Bit().data() ));
934 }
935 } else if ( bCheckExistance ) {
936 ERRORLOG( QString( "Provided song [%1] does not exist" ).arg( sSongPath ) );
937 return false;
938 }
939
940 if ( songFileInfo.suffix() != "h2song" ) {
941 ERRORLOG( QString( "Unable to handle path [%1]. The provided file must have the suffix '.h2song'!" )
942 .arg( sSongPath.toLocal8Bit().data() ));
943 return false;
944 }
945
946 return true;
947}
948
949QString Filesystem::validateFilePath( const QString& sPath ) {
950
951 // Ensure the name will be a valid filename
952 QString sValidName( sPath );
953 sValidName.replace( " ", "_" );
954 sValidName.remove( QRegExp( "[^a-zA-Z0-9_-]" ) );
955
956 return sValidName;
957}
958
960{
961 return QDir( sys_theme_dir() ).entryList( QStringList( THEME_FILTER ), QDir::Files | QDir::Readable | QDir::NoDotAndDotDot ) +
962 QDir( usr_theme_dir() ).entryList( QStringList( THEME_FILTER ), QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
963}
964
965// PLAYLISTS
967{
968 return QDir( playlists_dir() ).entryList( QStringList( PLAYLIST_FILTER ), QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
969}
970
972{
973 INFOLOG( QString( "Tmp dir : %1" ).arg( tmp_dir() ) );
974 // SYS
975 INFOLOG( QString( "Click file : %1" ).arg( click_file_path() ) );
976 INFOLOG( QString( "Empty song : %1" ).arg( empty_song_path() ) );
977 INFOLOG( QString( "Demos dir : %1" ).arg( demos_dir() ) );
978 INFOLOG( QString( "Documentation dir : %1" ).arg( doc_dir() ) ); // FIXME must be created even if no doc deployed
979 INFOLOG( QString( "System drumkit dir : %1" ).arg( sys_drumkits_dir() ) );
980 INFOLOG( QString( "Empty sample : %1" ).arg( empty_sample_path() ) );
981 INFOLOG( QString( "Default config : %1" ).arg( sys_config_path() ) );
982 INFOLOG( QString( "Internationalization dir : %1" ).arg( i18n_dir() ) );
983 INFOLOG( QString( "Images dir : %1" ).arg( img_dir() ) );
984 // new_tutorial
985 INFOLOG( QString( "XSD dir : %1" ).arg( xsd_dir() ) );
986 INFOLOG( QString( "drumkit pattern XSD : %1" ).arg( pattern_xsd_path() ) );
987 INFOLOG( QString( "drumkit XSD : %1" ).arg( drumkit_xsd_path() ) );
988 INFOLOG( QString( "drumkit XSD : %1" ).arg( playlist_xsd_path() ) );
989 // USR
990 INFOLOG( QString( "User config : %1" ).arg( usr_config_path() ) ); // FIXME
991 INFOLOG( QString( "User Click file : %1" ).arg( usr_click_file_path() ) );
992 INFOLOG( QString( "Cache dir : %1" ).arg( cache_dir() ) );
993 INFOLOG( QString( "Reporitories Cache dir : %1" ).arg( repositories_cache_dir() ) );
994 INFOLOG( QString( "User drumkit dir : %1" ).arg( usr_drumkits_dir() ) );
995 INFOLOG( QString( "Patterns dir : %1" ).arg( patterns_dir() ) );
996 INFOLOG( QString( "Playlist dir : %1" ).arg( playlists_dir() ) );
997 INFOLOG( QString( "Plugins dir : %1" ).arg( plugins_dir() ) );
998 INFOLOG( QString( "Scripts dir : %1" ).arg( scripts_dir() ) );
999 INFOLOG( QString( "Songs dir : %1" ).arg( songs_dir() ) );
1000}
1001
1002QString Filesystem::absolute_path( const QString& sFilename, bool bSilent ) {
1003 if ( QFile( sFilename ).exists() ) {
1004 return QFileInfo( sFilename ).absoluteFilePath();
1005 }
1006 else if ( ! bSilent ) {
1007 ___ERRORLOG( QString( "File [%1] not found" ).arg( sFilename ) );
1008 }
1009
1010 return QString();
1011}
1012
1013QString Filesystem::ensure_session_compatibility( const QString& sPath ) {
1014#ifdef H2CORE_HAVE_OSC
1015 auto pHydrogen = Hydrogen::get_instance();
1016 if ( pHydrogen != nullptr &&
1017 pHydrogen->isUnderSessionManagement() ) {
1018
1019 QFileInfo info( sPath );
1020 if ( info.isRelative() ) {
1021 return QString( "%1%2" )
1022 .arg( NsmClient::get_instance()->getSessionFolderPath() )
1023 // remove the leading dot indicating that the path is relative.
1024 .arg( sPath.right( sPath.size() - 1 ) );
1025 }
1026 }
1027#endif
1028
1029 return sPath;
1030}
1031
1033 const QString sAbsolutePath = absolute_path( sPath );
1034 if ( sAbsolutePath.contains( Filesystem::sys_drumkits_dir() ) ) {
1035 return DrumkitType::System;
1036 }
1037 else if ( sAbsolutePath.contains( Filesystem::usr_drumkits_dir() ) ) {
1038 return DrumkitType::User;
1039 }
1040 else {
1041 if ( dir_writable( sAbsolutePath, true ) ) {
1043 } else {
1045 }
1046 }
1047}
1048
1050 const QDir legacyDir( xsd_legacy_dir() );
1051
1052 const QStringList legacyDirSubfolders =
1053 legacyDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot,
1054 QDir::Name | QDir::Reversed );
1055
1056 QStringList drumkitXSDs;
1057 for ( const auto& ffolder : legacyDirSubfolders ) {
1058 const QDir folder( legacyDir.filePath( ffolder ) );
1059
1060 if ( folder.exists( drumkit_xsd() ) ) {
1061 drumkitXSDs << folder.filePath( drumkit_xsd() );
1062 }
1063 }
1064
1065 return std::move( drumkitXSDs );
1066}
1067
1068QString Filesystem::rerouteDrumkitPath( const QString& sDrumkitPath ) {
1069#ifdef H2CORE_HAVE_APPIMAGE
1070
1071 if ( sDrumkitPath.isEmpty() ) {
1072 ERRORLOG( "Can not reroute empty drumkit paths" );
1073 return "";
1074 }
1075
1076 // Since the path to a system kits of a previously mounted image
1077 // does most probably not exist anymore we can _not_ use
1078 // Filesystem::absolute_path in here.
1079 const QString sAbsolutePath = QDir( sDrumkitPath ).absolutePath();
1080 QString sResult = sAbsolutePath;
1081
1082 // Might be different ones depending on the mounting point of the
1083 // system.
1084 const QStringList systemPrefixes = { "/tmp" };
1085
1086 // Check whether the kit is a system drumkit from a previous
1087 // AppImage session.
1088 bool bIsForeignSystemKit = false;
1089 for ( const auto& ssPrefix : systemPrefixes ) {
1090 if ( sAbsolutePath.startsWith( ssPrefix ) &&
1091 ! sAbsolutePath.contains( Filesystem::sys_data_path() ) ) {
1092 bIsForeignSystemKit = true;
1093 }
1094 }
1095
1096 if ( bIsForeignSystemKit ) {
1097 const QStringList pathComponents = sAbsolutePath.split( "/" );
1098 if ( pathComponents.size() > 2 ) {
1099 const QString sNewPath = QString( "%1%2/%3" )
1101 .arg( pathComponents[ pathComponents.size() - 2 ] )
1102 .arg( pathComponents[ pathComponents.size() - 1 ] );
1103
1104 INFOLOG( QString( "Rerouting system kit: [%1] -> [%2]" )
1105 .arg( sDrumkitPath )
1106 .arg( Filesystem::absolute_path( sNewPath ) ) );
1107
1108 sResult = Filesystem::absolute_path( sNewPath );
1109 }
1110 else {
1111 ERRORLOG( QString( "Unable to replace drumkit path [%1]" )
1112 .arg( sDrumkitPath ) );
1113 }
1114 }
1115
1116 return sResult;
1117#else
1118 return sDrumkitPath;
1119#endif
1120}
1121};
1122
1123/* vim: set softtabstop=4 noexpandtab: */
#define AUTOSAVE
#define CLICK_SAMPLE
Sound of metronome beat.
#define DRUMKITS
#define IMG
#define REPOSITORIES
#define XSD
#define DRUMKIT_DEFAULT_KIT
#define CACHE
#define DEFAULT_SONG
#define TMP
#define PLAYLIST_FILTER
#define SONG_FILTER
#define PATTERNS
#define LOG_FILE
#define EMPTY_SONG_BASE
#define THEMES
#define I18N
#define SCRIPTS
#define SYS_CONFIG
#define DRUMPAT_XSD
#define PLAYLIST_XSD
#define PLAYLISTS
#define LOCAL_DATA_PATH
#define UNTITLED_PLAYLIST
#define DRUMKIT_XSD
#define PATTERN_FILTER
#define PLUGINS
#define DRUMKIT_XML
#define DOC
#define USR_CONFIG
#define SONGS
#define THEME_FILTER
#define UNTITLED_SONG
#define DEMOS
#define EMPTY_SAMPLE
#define INFOLOG(x)
Definition Object.h:237
#define WARNINGLOG(x)
Definition Object.h:238
#define ERRORLOG(x)
Definition Object.h:239
#define ___ERRORLOG(x)
Definition Object.h:257
static Logger * logger()
return the logger instance
Definition Object.h:103
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
static QStringList song_list()
returns a list of existing songs
static QString __usr_cfg_path
the path to the user config file
Definition Filesystem.h:535
static bool file_copy(const QString &src, const QString &dst, bool overwrite=false, bool bSilent=false)
copy a source file to a destination
static QString scripts_dir()
returns user scripts path
static const QString patterns_filter_name
Definition Filesystem.h:96
static QString playlist_xsd_path()
returns the path to the playlist pattern XSD (xml schema definition) file
static QString validateFilePath(const QString &sPath)
Takes an arbitrary path, replaces white spaces by underscores and removes all characters apart from l...
static QString demos_dir()
returns system demos path
static QString song_path(const QString &sg_name)
returns user song path, add file extension
static QString ensure_session_compatibility(const QString &sPath)
If Hydrogen is under session management, we support for paths relative to the session folder.
static QString sys_data_path()
returns system data path
static bool dir_readable(const QString &path, bool silent=false)
returns true if the given path is a readable regular directory
static QString cache_dir()
returns user cache path
static const QString patterns_ext
Definition Filesystem.h:89
static bool drumkit_exists(const QString &dk_name)
returns true if the drumkit exists within usable system or user drumkits
static bool check_usr_paths()
returns true if the user path is consistent
static const QString scripts_filter_name
Definition Filesystem.h:95
static bool file_executable(const QString &path, bool silent=false)
returns true if the given path is an existing executable regular file
static bool isSongPathValid(const QString &sSongPath, bool bCheckExistance=false)
Checks the path pointing to a .h2song.
static bool drumkit_valid(const QString &dk_path)
returns true if the path contains a usable drumkit
static QString playlist_path(const QString &pl_name)
returns user playlist path, add file extension
static QStringList drumkit_list(const QString &path)
static bool check_permissions(const QString &path, const int perms, bool silent)
static QString usr_config_path()
returns user config path
static QString songs_dir()
returns user songs path
static QString pattern_xsd_path()
returns the path to the pattern XSD (xml schema definition) file
static const QString themes_ext
Definition Filesystem.h:92
static QString playlists_dir()
returns user playlist path
static DrumkitType determineDrumkitType(const QString &sPath)
static QString usr_click_file_path()
returns click file path from user directory if exists, otherwise from system
static QString empty_sample_path()
returns system empty sample file path
static QStringList playlist_list()
returns a list of existing playlists
static QString absolute_path(const QString &sFilename, bool bSilent=false)
Convert a direct to an absolute path.
static QString plugins_dir()
returns user plugins path
static bool file_writable(const QString &path, bool silent=false)
returns true if the given path is a possibly writable file (may exist or not)
static QStringList theme_list()
static QString usr_drumkits_dir()
returns user drumkits path
static QString untitled_song_name()
returns untitled song name
static bool check_sys_paths()
returns true if the system path is consistent
static QStringList ladspa_paths()
returns user ladspa paths
static QStringList drumkit_xsd_legacy_paths()
static QStringList pattern_list()
returns a list of existing patterns
static QString sys_drumkits_dir()
returns system drumkits path
static bool rm(const QString &path, bool recursive=false, bool bSilent=false)
remove a path
static QString drumkit_backup_path(const QString &dk_path)
Create a backup path from a drumkit path.
static QStringList song_list_cleared()
returns a list of existing songs, excluding the autosaved one
static QString usr_theme_dir()
static QString drumkit_xsd_path()
returns the path to the drumkit XSD (xml schema definition) file
static QString doc_dir()
returns documentation path
static const QString scripts_ext
Definition Filesystem.h:88
static QStringList usr_drumkit_list()
returns list of usable user drumkits ( see Filesystem::drumkit_list )
static QString repositories_cache_dir()
returns user repository cache path
static bool file_is_under_drumkit(const QString &fname)
Checks if the given filepath is under an existing user or system drumkit path, not the existence of t...
static QString prepare_sample_path(const QString &fname)
Returns the basename if the given path is under an existing user or system drumkit path,...
static bool rm_fr(const QString &path, bool bSilent=false)
recursively remove a path
static bool dir_writable(const QString &path, bool silent=false)
returns true if the given path is a writable regular directory
static int get_basename_idx_under_drumkit(const QString &fname)
Returns the index of the basename if the given path is under an existing user or system drumkit path,...
static QString img_dir()
returns gui image path
static QString rerouteDrumkitPath(const QString &sDrumkitPath)
Reroutes stored drumkit paths pointing to a temporary AppImage system data folder to the current AppI...
static bool file_exists(const QString &path, bool silent=false)
returns true if the given path is an existing regular file
static QString __usr_data_path
the path to the user files
Definition Filesystem.h:534
static QString empty_song_path()
Provides the full path to the current empty song.
Lookup
Whenever a drumkit is loaded by name a collision between a user and a system drumkit carrying the sam...
Definition Filesystem.h:53
@ system
Only search the system drumkits.
@ stacked
First, looks in the system drumkits and, afterwards, in the user drumkits.
@ user
Only search the user drumkits.
static QString drumkit_dir_search(const QString &dk_name, Lookup lookup)
returns the directory holding the named drumkit searching within user then system drumkits
static QString m_sPreferencesOverwritePath
If this variable is non-empty, its content will be used as an alternative to store and load the prefe...
Definition Filesystem.h:496
static QString click_file_path()
Returns a string containing the path to the click.wav file used in the metronome.
static QStringList sys_drumkit_list()
returns list of usable system drumkits ( see Filesystem::drumkit_list )
static QString drumkit_path_search(const QString &dk_name, Lookup lookup=Lookup::stacked, bool bSilent=false)
Returns the path to a H2Core::Drumkit folder.
static const QString playlists_filter_name
Definition Filesystem.h:97
static QString sys_config_path()
returns system config path
static bool mkdir(const QString &path)
create a path
static QString drumkit_file(const QString &dk_path)
returns the path to the xml file within a supposed drumkit path
static QStringList pattern_drumkits()
returns a list of existing drumkit sub dir into the patterns directory
static QString __sys_data_path
Path to the system files set in Filesystem::bootstrap().
Definition Filesystem.h:533
static bool bootstrap(Logger *logger, const QString &sys_path=nullptr)
check user and system filesystem usability
static QString pattern_path(const QString &dk_name, const QString &p_name)
returns user patterns path, add file extension
static QString __usr_log_path
the path to the log file
Definition Filesystem.h:536
static bool write_to_file(const QString &dst, const QString &content)
writes to a file
static Logger * __logger
a pointer to the logger
Definition Filesystem.h:488
static const QString playlist_ext
Definition Filesystem.h:90
static QString i18n_dir()
returns internationalization path
static const QString songs_filter_name
Definition Filesystem.h:93
static QString xsd_legacy_dir()
static QString tmp_dir()
returns temp path
DrumkitType
Determines were to find a kit and whether it is writable by the current user.
Definition Filesystem.h:70
@ SessionReadWrite
Kit was loaded via a NSM session, OSC command, or CLI option, only persist for the current Hydrogen s...
@ User
Kit was installed by the user, is automatically loaded, and most probably writable.
@ System
Kit was installed with Hydrogen, is automatically loaded, and most probably readonly.
@ SessionReadOnly
Kit was loaded via a NSM session, OSC command, or CLI option, only persist for the current Hydrogen s...
static void info()
send current settings information to logger with INFO severity
static QString usr_data_path()
returns user data path
static QString log_file_path()
returns the full path (including filename) of the logfile
static QString drumkit_usr_path(const QString &dk_name)
returns path for a drumkit within user drumkit path
static const QString drumkit_ext
Definition Filesystem.h:91
static const QString themes_filter_name
Definition Filesystem.h:94
static const QString songs_ext
Definition Filesystem.h:87
static QString sys_theme_dir()
static bool path_usable(const QString &path, bool create=true, bool silent=false)
returns true if the path is a readable and writable regular directory, create if it not exists
static QString drumkit_xml()
Returns filename and extension of the expected drumkit file.
static QString drumkit_xsd()
returns the drumkit XSD (xml schema definition) name
static QString tmp_file_path(const QString &base)
touch a temporary file under tmp_dir() and return it's path.
static QString default_song_name()
Default option to offer the user when saving an empty song to disk.
static QString xsd_dir()
returns system xsd path
static bool song_exists(const QString &sg_name)
returns true if the song file exists
static QStringList __ladspa_paths
paths to laspa plugins
Definition Filesystem.h:537
static QString untitled_playlist_file_name()
returns untitled playlist file name
static bool file_readable(const QString &path, bool silent=false)
returns true if the given path is an existing readable regular file
static bool dir_exists(const QString &path, bool silent=false)
returns true if the given path is a regular directory
static QString drumkit_default_kit()
static QString patterns_dir()
returns user patterns path
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
SoundLibraryDatabase * getSoundLibraryDatabase() const
Definition Hydrogen.h:94
Class for writing logs to the console.
Definition Logger.h:42
std::shared_ptr< Drumkit > getDrumkit(const QString &sDrumkitPath, bool bLoad=true)
Retrieve a drumkit from the database.
static void printError(const QString &msg)
Custom function to print a colored error message.
static NsmClient * get_instance()
Definition NsmClient.h:84
#define H2_SYS_PATH
Path of the configuration files of Hydrogen in the system.
Definition config.dox:29
#define H2_USR_PATH
Path of the configuration files of Hydrogen in the user home.
Definition config.dox:24
@ EVENT_UPDATE_SONG
Event triggering HydrogenApp::updateSongEvent() whenever the Song was changed outside of the GUI,...
Definition EventQueue.h:128