hydrogen 1.2.6
SoundLibraryDatabase.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-2025 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
24
25#include <core/Basics/Drumkit.h>
26#include <core/EventQueue.h>
28
29namespace H2Core
30{
31
36
40
42{
43 for ( const auto& pPatternInfo : m_patternInfoVector ) {
44 INFOLOG( QString( "Name: [%1]" ).arg( pPatternInfo->getName() ) );
45 }
46
47 for ( const auto& sCategory : m_patternCategories ) {
48 INFOLOG( QString( "Category: [%1]" ).arg( sCategory ) );
49 }
50}
51
52bool SoundLibraryDatabase::isPatternInstalled( const QString& sPatternName ) const
53{
54 for ( const auto& pPatternInfo : m_patternInfoVector ) {
55 if ( pPatternInfo->getName() == sPatternName ) {
56 return true;
57 }
58 }
59 return false;
60}
61
63{
64 updatePatterns( false );
65 //updateSongs();
66 updateDrumkits( false );
67
69}
70
71void SoundLibraryDatabase::updateDrumkits( bool bTriggerEvent ) {
72
73 m_drumkitDatabase.clear();
74
75 QStringList drumkitPaths;
76 // system drumkits
77 for ( const auto& sDrumkitName : Filesystem::sys_drumkit_list() ) {
78 drumkitPaths <<
80 }
81 // user drumkits
82 for ( const auto& sDrumkitName : Filesystem::usr_drumkit_list() ) {
83 drumkitPaths <<
85 }
86
87#ifdef H2CORE_HAVE_APPIMAGE
88 // When starting Hydrogen as an AppImage, all drumkits installed via the
89 // package manager are not part of the system drumkit folder of this
90 // instance. Instead, we treat them as custom drumkit.
91 const auto additionalDirs = QStringList()
92 << "/usr/share/hydrogen/data/drumkits"
93 << "/usr/local/share/hydrogen/data/drumkits";
94 for ( const auto& ssDir : additionalDirs ) {
95 if ( Filesystem::dir_exists( ssDir, true ) ) {
96 for ( const auto& ssEntry : QDir( ssDir ).entryList(
97 QDir::Dirs | QDir::Readable | QDir::NoDotAndDotDot ) ) {
98 const auto sFilePath = QString( "%1/%2" ).arg( ssDir )
99 .arg( ssEntry );
100 if ( Filesystem::drumkit_valid( sFilePath ) &&
101 ! m_customDrumkitPaths.contains( sFilePath ) ) {
102 m_customDrumkitPaths << sFilePath;
103 }
104 }
105 }
106 }
107#endif
108
109 // custom drumkits added by the user
110 for ( const auto& sDrumkitPath : m_customDrumkitPaths ) {
111 if ( ! drumkitPaths.contains( sDrumkitPath ) ) {
112 drumkitPaths << sDrumkitPath;
113 }
114 }
115
116 for ( const auto& sDrumkitPath : drumkitPaths ) {
117 auto pDrumkit = Drumkit::load( sDrumkitPath );
118 if ( pDrumkit != nullptr ) {
119 if ( m_drumkitDatabase.find( sDrumkitPath ) !=
120 m_drumkitDatabase.end() ) {
121 ERRORLOG( QString( "A drumkit was already loaded from [%1]. Something went wrong." )
122 .arg( sDrumkitPath ) );
123 continue;
124 }
125 else {
126 INFOLOG( QString( "Drumkit [%1] loaded from [%2]" )
127 .arg( pDrumkit->get_name() )
128 .arg( sDrumkitPath ) );
129 }
130
131 m_drumkitDatabase[ sDrumkitPath ] = pDrumkit;
132 }
133 else {
134 ERRORLOG( QString( "Unable to load drumkit at [%1]" ).arg( sDrumkitPath ) );
135 }
136 }
137
138 if ( bTriggerEvent ) {
140 }
141}
142
143void SoundLibraryDatabase::updateDrumkit( const QString& sDrumkitPath, bool bTriggerEvent ) {
144
145 auto pDrumkit = Drumkit::load( sDrumkitPath );
146 if ( pDrumkit != nullptr ) {
147 m_drumkitDatabase[ sDrumkitPath ] = pDrumkit;
148 }
149 else {
150 ERRORLOG( QString( "Unable to load drumkit at [%1]" ).arg( sDrumkitPath ) );
151 }
152
153 if ( bTriggerEvent ) {
155 }
156}
157
158std::shared_ptr<Drumkit> SoundLibraryDatabase::getDrumkit( const QString& sDrumkit, bool bLoad ) {
159
160 // Convert supplied path or drumkit name into absolute path used
161 // either as ID to retrieve the drumkit from cache or for loading
162 // it from disk in case it is not present yet.
163
164 QString sDrumkitPath;
165 if ( sDrumkit.contains( "/" ) || sDrumkit.contains( "\\" ) ) {
166 // Supplied string is a path to a drumkit
167 sDrumkitPath = sDrumkit;
168 }
169 else {
170 // Supplied string it the name of a drumkit
171 sDrumkitPath = Filesystem::drumkit_path_search( sDrumkit,
173 false );
174 }
175 sDrumkitPath = Filesystem::absolute_path( sDrumkitPath );
176
177 if ( sDrumkitPath.isEmpty() ) {
178 ERRORLOG( QString( "Unable determine drumkit path based on supplied string [%1]" )
179 .arg( sDrumkit ) );
180 return nullptr;
181 }
182
183 if ( m_drumkitDatabase.find( sDrumkitPath ) ==
184 m_drumkitDatabase.end() ) {
185 if ( ! bLoad ) {
186 return nullptr;
187 }
188
189 // Drumkit is not present in database yet. We attempt to load
190 // and add it.
191 auto pDrumkit = Drumkit::load( sDrumkitPath,
192 true, // upgrade
193 nullptr, // check for legacy format
194 false // bSilent
195 );
196 if ( pDrumkit == nullptr ) {
197 return nullptr;
198 }
199
200 m_customDrumkitPaths << sDrumkitPath;
201 m_drumkitDatabase[ sDrumkitPath ] = pDrumkit;
202
203 INFOLOG( QString( "Session Drumkit [%1] loaded from [%2]" )
204 .arg( pDrumkit->get_name() )
205 .arg( sDrumkitPath ) );
206
208
209 return pDrumkit;
210 }
211
212 return m_drumkitDatabase.at( sDrumkitPath );
213}
214
215void SoundLibraryDatabase::updatePatterns( bool bTriggerEvent )
216{
217 m_patternInfoVector.clear();
218 m_patternCategories = QStringList();
219
220 // search drumkit subdirectories within patterns user directory
221 foreach ( const QString& sDrumkit, Filesystem::pattern_drumkits() ) {
223 }
224 // search patterns user directory
226
227 if ( bTriggerEvent ) {
229 }
230}
231
232void SoundLibraryDatabase::loadPatternFromDirectory( const QString& sPatternDir )
233{
234 foreach ( const QString& sName, Filesystem::pattern_list( sPatternDir ) ) {
235 QString sFile = sPatternDir + sName;
236 std::shared_ptr<SoundLibraryInfo> pInfo =
237 std::make_shared<SoundLibraryInfo>();
238
239 if ( pInfo->load( sFile ) ) {
240 INFOLOG( QString( "Pattern [%1] of category [%2] loaded from [%3]" )
241 .arg( pInfo->getName() ).arg( pInfo->getCategory() )
242 .arg( sFile ) );
243
244 m_patternInfoVector.push_back( pInfo );
245
246 if ( ! m_patternCategories.contains( pInfo->getCategory() ) ) {
247 m_patternCategories << pInfo->getCategory();
248 }
249 }
250 }
251}
252
253QString SoundLibraryDatabase::toQString( const QString& sPrefix, bool bShort ) const {
254 QString s = Base::sPrintIndention;
255 QString sOutput;
256 if ( ! bShort ) {
257 sOutput = QString( "%1[SoundLibraryDatabase]\n" ).arg( sPrefix )
258 .append( QString( "%1%2m_drumkitDatabase:\n" ).arg( sPrefix ).arg( s ) );
259 for ( const auto& [ ssPath, ddrumkit ] : m_drumkitDatabase ) {
260 sOutput.append( QString( "%1%2%2%3: %4\n" ).arg( sPrefix ).arg( s )
261 .arg( ssPath ).arg( ddrumkit->toQString( "", true ) ) );
262 }
263 sOutput.append( QString( "%1%2m_patternInfoVector:\n" ).arg( sPrefix ).arg( s ) );
264 for ( const auto& ppatternInfo : m_patternInfoVector ) {
265 sOutput.append( QString( "%3\n" )
266 .arg( ppatternInfo->toQString( sPrefix + s + s, bShort ) ) );
267 }
268 sOutput.append( QString( "%1%2m_patternCategories: %3\n" ).arg( sPrefix ).arg( s )
269 .arg( m_patternCategories.join( ", " ) ) );
270 sOutput.append( QString( "%1%2m_customDrumkitPaths:\n" ).arg( sPrefix ).arg( s ) );
271 for ( const auto& ssCustomPath : m_customDrumkitPaths ) {
272 sOutput.append( QString( "%1%2%2%3\n" ).arg( sPrefix ).arg( s )
273 .arg( ssCustomPath ) );
274 }
275 }
276 else {
277
278 sOutput = QString( "%1[SoundLibraryDatabase]\n" ).arg( sPrefix )
279 .append( QString( "%1%2m_drumkitDatabase:\n" ).arg( sPrefix ).arg( s ) );
280 for ( const auto& eentry : m_drumkitDatabase ) {
281 sOutput.append( QString( "%1%2%2%3\n" ).arg( sPrefix ).arg( s )
282 .arg( eentry.first ) );
283 }
284 sOutput.append( QString( "%1%2m_patternInfoVector:\n" ).arg( sPrefix ).arg( s ) );
285 for ( const auto& ppatternInfo : m_patternInfoVector ) {
286 sOutput.append( QString( "%1%2%2%3\n" ).arg( sPrefix ).arg( s )
287 .arg( ppatternInfo->getPath() ) );
288 }
289 sOutput.append( QString( "%1%2m_patternCategories: %3\n" ).arg( sPrefix ).arg( s )
290 .arg( m_patternCategories.join( ", " ) ) );
291 sOutput.append( QString( "%1%2m_customDrumkitPaths:\n" ).arg( sPrefix ).arg( s ) );
292 for ( const auto& ssCustomPath : m_customDrumkitPaths ) {
293 sOutput.append( QString( "%1%2%2%3\n" ).arg( sPrefix ).arg( s )
294 .arg( ssCustomPath ) );
295 }
296 }
297
298 return sOutput;
299}
300};
#define INFOLOG(x)
Definition Object.h:240
#define ERRORLOG(x)
Definition Object.h:242
static QString sPrintIndention
String used to format the debugging string output of some core classes.
Definition Object.h:127
static std::shared_ptr< Drumkit > load(const QString &dk_dir, bool bUpgrade=true, bool *pLegacyFormatEncountered=nullptr, bool bSilent=false)
Load drumkit information from a directory.
Definition Drumkit.cpp:94
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 bool drumkit_valid(const QString &dk_path)
returns true if the path contains a usable drumkit
static QString absolute_path(const QString &sFilename, bool bSilent=false)
Convert a direct to an absolute path.
static QString usr_drumkits_dir()
returns user drumkits path
static QStringList pattern_list()
returns a list of existing patterns
static QString sys_drumkits_dir()
returns system drumkits path
static QStringList usr_drumkit_list()
returns list of usable user drumkits ( see Filesystem::drumkit_list )
@ stacked
First, looks in the system drumkits and, afterwards, in the user drumkits.
Definition Filesystem.h:63
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 QStringList pattern_drumkits()
returns a list of existing drumkit sub dir into the patterns directory
static bool dir_exists(const QString &path, bool silent=false)
returns true if the given path is a regular directory
static QString patterns_dir()
returns user patterns path
std::map< QString, std::shared_ptr< Drumkit > > m_drumkitDatabase
void updateDrumkits(bool bTriggerEvent=true)
void loadPatternFromDirectory(const QString &path)
bool isPatternInstalled(const QString &sPatternName) const
void updateDrumkit(const QString &sDrumkitPath, bool bTriggerEvent=true)
void updatePatterns(bool bTriggerEvent=true)
QStringList m_customDrumkitPaths
List of drumkits the user supplied via CLI or OSC command but couldn't be found in either the system'...
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
std::vector< std::shared_ptr< SoundLibraryInfo > > m_patternInfoVector
std::shared_ptr< Drumkit > getDrumkit(const QString &sDrumkitPath, bool bLoad=true)
Retrieve a drumkit from the database.
@ EVENT_SOUND_LIBRARY_CHANGED
Definition EventQueue.h:176