38Pattern::Pattern(
const QString& name,
const QString& info,
const QString& category,
int length,
int denominator )
55 __notes.insert( std::make_pair( it->first,
new Note( it->second ) ) );
67 std::shared_ptr<InstrumentList> pInstrumentList,
71 INFOLOG( QString(
"Load pattern %1" ).arg( sPatternPath ) );
79 if ( ! doc.
read( sPatternPath ) ) {
80 ERRORLOG( QString(
"Unable to read pattern [%1]" ).arg( sPatternPath ) );
84 XMLNode rootNode = doc.firstChildElement(
"drumkit_pattern" );
85 if ( rootNode.isNull() ) {
86 ERRORLOG( QString(
"'drumkit_pattern' node not found in [%1]" )
87 .arg( sPatternPath ) );
91 XMLNode patternNode = rootNode.firstChildElement(
"pattern" );
92 if ( patternNode.isNull() ) {
93 ERRORLOG( QString(
"'pattern' node not found in [%1]" )
94 .arg( sPatternPath ) );
100 XMLNode legacyPatternNameNode = patternNode.firstChildElement(
"pattern_name" );
101 if ( ! legacyPatternNameNode.isNull() ) {
107 auto formatVersionNode = patternNode.firstChildElement(
"formatVersion" );
108 if ( ! formatVersionNode.isNull() ) {
109 WARNINGLOG( QString(
"Pattern file [%1] was created with a more recent version of Hydrogen than the current one!" )
110 .arg( sPatternPath ) );
113 return load_from( &patternNode, pInstrumentList );
119 node->
read_string(
"name",
nullptr,
false,
false ),
121 node->
read_string(
"category",
"unknown",
false,
true,
true ),
122 node->
read_int(
"size", -1,
false,
false ),
123 node->
read_int(
"denominator", 4,
false,
false )
126 if ( pInstrumentList ==
nullptr ) {
127 ERRORLOG(
"Invalid instrument list provided" );
131 XMLNode note_list_node = node->firstChildElement(
"noteList" );
132 if ( !note_list_node.isNull() ) {
133 XMLNode note_node = note_list_node.firstChildElement(
"note" );
134 while ( !note_node.isNull() ) {
137 if ( pNote !=
nullptr ) {
140 note_node = note_node.nextSiblingElement(
"note" );
147bool Pattern::save_file(
const QString& drumkit_name,
const QString& author,
const License& license,
const QString& pattern_path,
bool overwrite )
const
149 INFOLOG( QString(
"Saving pattern into %1" ).arg( pattern_path ) );
151 ERRORLOG( QString(
"pattern %1 already exists" ).arg( pattern_path ) );
161 return doc.
write( pattern_path );
173 int nId = ( pInstrumentOnly ==
nullptr ? -1 : pInstrumentOnly->get_id() );
177 auto pNote = it->second;
178 if ( pNote !=
nullptr &&
179 ( pInstrumentOnly ==
nullptr ||
180 pNote->get_instrument()->get_id() == nId ) ) {
182 pNote->save_to( ¬e_node );
190 Note* note = it->second;
192 if ( note->
match( instrument, key, octave ) )
return note;
194 if( idx_b==-1 )
return nullptr;
196 Note* note = it->second;
198 if ( note->
match( instrument, key, octave ) )
return note;
200 if( strict )
return nullptr;
202 for (
int n=0; n<idx_b; n++ ) {
204 Note* note = it->second;
206 if ( note->
match( instrument, key, octave ) && ( ( idx_b<=note->get_position()+note->
get_length() ) && idx_b>=note->
get_position() ) )
return note;
215 for( it=
__notes.lower_bound( idx_a ); it!=
__notes.upper_bound( idx_a ); it++ ) {
216 Note* note = it->second;
220 if( idx_b==-1 )
return nullptr;
221 for( it=
__notes.lower_bound( idx_b ); it!=
__notes.upper_bound( idx_b ); it++ ) {
222 Note* note = it->second;
226 if ( strict )
return nullptr;
228 for (
int n=0; n<idx_b; n++ ) {
229 for( it=
__notes.lower_bound( n ); it!=
__notes.upper_bound( n ); it++ ) {
230 Note* note = it->second;
243 if( it->second==note ) {
253 Note* note = it->second;
265 std::list< Note* > slate;
267 Note* note = it->second;
270 if ( !locked && bRequiresLock ) {
274 slate.push_back( note );
283 while ( slate.size() ) {
284 delete slate.front();
292 if ( bRequiresLock ){
295 std::list< Note* > slate;
297 Note* note = it->second;
299 slate.push_back( note );
302 if ( bRequiresLock ) {
303 pAudioEngine->unlock();
306 while ( slate.size() ) {
307 delete slate.front();
315 Note* note = it->second;
328 ( *it0 )->flattened_virtual_patterns_compute();
330 for(
virtual_patterns_cst_it_t it1=( *it0 )->get_flattened_virtual_patterns()->begin(); it1!=( *it0 )->get_flattened_virtual_patterns()->end(); ++it1 ) {
340 pPatternList->
add( *it,
true );
347 pPatternList->
del( *it );
355 if ( (*it)->__length > nMax ) {
356 nMax = (*it)->__length;
379 sOutput = QString(
"%1[Pattern]\n" ).arg( sPrefix )
380 .append( QString(
"%1%2length: %3\n" ).arg( sPrefix ).arg( s ).arg(
__length ) )
381 .append( QString(
"%1%2denominator: %3\n" ).arg( sPrefix ).arg( s ).arg(
__denominator ) )
382 .append( QString(
"%1%2name: %3\n" ).arg( sPrefix ).arg( s ).arg(
__name ) )
383 .append( QString(
"%1%2category: %3\n" ).arg( sPrefix ).arg( s ).arg(
__category ) )
384 .append( QString(
"%1%2info: %3\n" ).arg( sPrefix ).arg( s ).arg(
__info ) )
385 .append( QString(
"%1%2Notes:\n" ).arg( sPrefix ).arg( s ) );
388 if ( it->second !=
nullptr ) {
389 sOutput.append( QString(
"%1" ).arg( it->second->toQString( sPrefix + s + s, bShort ) ) );
393 sOutput.append( QString(
"%1%2Virtual_patterns:\n" ).arg( sPrefix ).arg( s ) );
395 if ( ii !=
nullptr ) {
396 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
400 sOutput.append( QString(
"%1%2Flattened_virtual_patterns:\n" ).arg( sPrefix ).arg( s ) );
402 if ( ii !=
nullptr ) {
403 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
408 sOutput = QString(
"[Pattern]" )
409 .append( QString(
" length: %1" ).arg(
__length ) )
410 .append( QString(
", denominator: %1" ).arg(
__denominator ) )
411 .append( QString(
", name: %1" ).arg(
__name ) )
412 .append( QString(
", category: %1" ).arg(
__category ) )
413 .append( QString(
", info: %1" ).arg(
__info ) )
414 .append( QString(
", [Notes: " ) );
416 if ( it->second !=
nullptr ) {
417 sOutput.append( QString(
"[%2, %3] " )
418 .arg( it->second->get_instrument()->get_name() )
419 .arg( it->second->get_position() ) );
422 sOutput.append(
"]" );
424 sOutput.append(
", Virtual_patterns: {" );
427 if ( ii !=
nullptr ) {
428 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
432 sOutput.append(
"}, Flattened_virtual_patterns: {" );
435 if ( ii !=
nullptr ) {
436 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
440 sOutput.append(
"}" );
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
#define FOREACH_NOTE_CST_IT_BEGIN_END(_notes, _it)
Iterate over all provided notes in an immutable way.
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
static QString sPrintIndention
String used to format the debugging string output of some core classes.
static bool file_exists(const QString &path, bool silent=false)
returns true if the given path is an existing regular file
static bool file_readable(const QString &path, bool silent=false)
returns true if the given path is an existing readable regular file
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
AudioEngine * getAudioEngine() const
static Pattern * load_drumkit_pattern(const QString &pattern_path, std::shared_ptr< InstrumentList > instrList)
load pattern from a file
Wrapper class to help Hydrogen deal with the license information specified in a drumkit.
QString getLicenseString() const
A note plays an associated instrument with a velocity left and right pan.
int get_position() const
__position accessor
static Note * load_from(XMLNode *node, std::shared_ptr< InstrumentList > instruments, bool bSilent=false)
load a note from an XMLNode
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
void set_just_recorded(bool value)
__just_recorded setter
int get_length() const
__length accessor
bool match(std::shared_ptr< Instrument > instrument, Key key, Octave octave) const
return true if instrument, key and octave matches with internal
PatternList is a collection of patterns.
void add(Pattern *pattern, bool bAddVirtuals=false)
add a pattern to the list
Pattern * del(int idx)
remove the pattern at a given index, does not delete it
QString __name
the name of thepattern
bool save_file(const QString &drumkit_name, const QString &author, const License &license, const QString &pattern_path, bool overwrite=false) const
save a pattern into an xml file
const QString & get_info() const
get the category of the pattern
const QString & get_name() const
set the category of the pattern
const QString & get_category() const
set the length of the pattern
void set_to_old()
mark all notes as old
QString __info
a description of the pattern
void purge_instrument(std::shared_ptr< Instrument > instr, bool bRequiredLock=true)
delete the notes referencing the given instrument The function is thread safe (it locks the audio dat...
bool references(std::shared_ptr< Instrument > instr)
check if this pattern contains a note referencing the given instrument
virtual_patterns_t __virtual_patterns
a list of patterns directly referenced by this one
Pattern(const QString &name="Pattern", const QString &info="", const QString &category="not_categorized", int length=MAX_NOTES, int denominator=4)
constructor
notes_t __notes
a multimap (hash with possible multiple values for one key) of note
static Pattern * load_file(const QString &sPpatternPath, std::shared_ptr< InstrumentList > pInstruments, bool bSilent=false)
load a pattern from a file
static Pattern * load_from(XMLNode *node, std::shared_ptr< InstrumentList > instruments, bool bSilent=false)
load a pattern from an XMLNode
void flattened_virtual_patterns_compute()
compute virtual_pattern_transitive_closure_set based on virtual_pattern_transitive_closure_set virtua...
void remove_note(Note *note)
removes a given note from __notes, it's not deleted
int __length
Determines the accessible range or notes within the pattern.
notes_t::iterator notes_it_t
multimap note const iterator type
int get_length() const
set the denominator of the pattern
void clear(bool bRequiredLock=true)
Erase all notes.
std::set< Pattern * >::iterator begin()
allow iteration of all contained virtual patterns.
const notes_t * get_notes() const
get the virtual pattern set
notes_t::const_iterator notes_cst_it_t
note set type;
void removeFlattenedVirtualPatterns(PatternList *pPatternList)
Add content of __flattened_virtual_patterns into pPatternList.
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
int get_denominator() const
get the note multimap
Note * find_note(int idx_a, int idx_b, std::shared_ptr< Instrument > instrument, bool strict=true) const
search for a note at a given index within __notes which correspond to the given arguments
virtual_patterns_t::const_iterator virtual_patterns_cst_it_t
void save_to(XMLNode *node, const std::shared_ptr< Instrument > instrumentOnly=nullptr) const
save the pattern within the given XMLNode
virtual_patterns_t __flattened_virtual_patterns
the complete list of virtual patterns
QString __category
the category of the pattern
bool isVirtual() const
Whether the pattern holds at least one virtual pattern.
int longestVirtualPatternLength() const
void insert_note(Note *note)
insert a new note within __notes
std::set< Pattern * >::iterator end()
int __denominator
the meter denominator of the pattern used in meter (eg 4/4)
void addFlattenedVirtualPatterns(PatternList *pPatternList)
Add content of __flattened_virtual_patterns into pPatternList.
XMLDoc is a subclass of QDomDocument with read and write methods.
XMLNode set_root(const QString &node_name, const QString &xmlns=nullptr)
create the xml header and root node
bool read(const QString &filepath, bool bSilent=false)
read the content of an xml file
bool write(const QString &filepath)
write itself into a file
XMLNode is a subclass of QDomNode with read and write values methods.
int read_int(const QString &node, int default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads an integer stored into a child node
QString read_string(const QString &node, const QString &default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a string stored into a child node
XMLNode createNode(const QString &name)
create a new XMLNode that has to be appended into de XMLDoc
void write_string(const QString &node, const QString &value)
write a string into a child node
void write_int(const QString &node, const int value)
write an integer into a child node