38Pattern::Pattern(
const QString& name,
const QString& info,
const QString& category,
int length,
int denominator )
40 , __denominator( denominator)
43 , __category( category )
48 : __length( other->get_length() )
49 , __denominator( other->get_denominator() )
50 , __name( other->get_name() )
51 , __info( other->get_info() )
52 , __category( other->get_category() )
55 __notes.insert( std::make_pair( it->first,
new Note( it->second ) ) );
66bool Pattern::loadDoc(
const QString& sPatternPath, std::shared_ptr<InstrumentList> pInstrumentList,
XMLDoc* pDoc,
bool bSilent )
72 bool bReadingSuccessful =
true;
75 if ( ! pDoc->
read( sPatternPath,
nullptr ) ) {
76 ERRORLOG( QString(
"Unable to read pattern [%1]" )
77 .arg( sPatternPath ) );
82 WARNINGLOG( QString(
"Pattern [%1] does not validate the current pattern schema. Loading might fail." )
83 .arg( sPatternPath ) );
85 bReadingSuccessful =
false;
89 XMLNode root = pDoc->firstChildElement(
"drumkit_pattern" );
90 if ( root.isNull() ) {
91 ERRORLOG( QString(
"'drumkit_pattern' node not found in [%1]" )
92 .arg( sPatternPath ) );
96 XMLNode pattern_node = root.firstChildElement(
"pattern" );
97 if ( pattern_node.isNull() ) {
98 ERRORLOG( QString(
"'pattern' node not found in [%1]" )
99 .arg( sPatternPath ) );
103 return bReadingSuccessful;
108 INFOLOG( QString(
"Load pattern %1" ).arg( sPatternPath ) );
111 if ( !
loadDoc( sPatternPath, pInstrumentList, &doc,
false ) ) {
116 XMLNode root = doc.firstChildElement(
"drumkit_pattern" );
117 XMLNode pattern_node = root.firstChildElement(
"pattern" );
118 return load_from( &pattern_node, pInstrumentList );
124 node->
read_string(
"name",
nullptr,
false,
false ),
126 node->
read_string(
"category",
"unknown",
false,
true,
true ),
127 node->
read_int(
"size", -1,
false,
false ),
128 node->
read_int(
"denominator", 4,
false,
false )
131 if ( pInstrumentList ==
nullptr ) {
132 ERRORLOG(
"Invalid instrument list provided" );
136 XMLNode note_list_node = node->firstChildElement(
"noteList" );
137 if ( !note_list_node.isNull() ) {
138 XMLNode note_node = note_list_node.firstChildElement(
"note" );
139 while ( !note_node.isNull() ) {
142 if ( pNote !=
nullptr ) {
145 note_node = note_node.nextSiblingElement(
"note" );
152bool Pattern::save_file(
const QString& drumkit_name,
const QString& author,
const License& license,
const QString& pattern_path,
bool overwrite )
const
154 INFOLOG( QString(
"Saving pattern into %1" ).arg( pattern_path ) );
156 ERRORLOG( QString(
"pattern %1 already exists" ).arg( pattern_path ) );
166 return doc.
write( pattern_path );
178 int nId = ( pInstrumentOnly ==
nullptr ? -1 : pInstrumentOnly->get_id() );
182 auto pNote = it->second;
183 if ( pNote !=
nullptr &&
184 ( pInstrumentOnly ==
nullptr ||
185 pNote->get_instrument()->get_id() == nId ) ) {
187 pNote->save_to( ¬e_node );
195 Note* note = it->second;
197 if ( note->
match( instrument, key, octave ) )
return note;
199 if( idx_b==-1 )
return nullptr;
201 Note* note = it->second;
203 if ( note->
match( instrument, key, octave ) )
return note;
205 if( strict )
return nullptr;
207 for (
int n=0; n<idx_b; n++ ) {
209 Note* note = it->second;
211 if ( note->
match( instrument, key, octave ) && ( ( idx_b<=note->get_position()+note->
get_length() ) && idx_b>=note->
get_position() ) )
return note;
220 for( it=
__notes.lower_bound( idx_a ); it!=
__notes.upper_bound( idx_a ); it++ ) {
221 Note* note = it->second;
225 if( idx_b==-1 )
return nullptr;
226 for( it=
__notes.lower_bound( idx_b ); it!=
__notes.upper_bound( idx_b ); it++ ) {
227 Note* note = it->second;
231 if ( strict )
return nullptr;
233 for (
int n=0; n<idx_b; n++ ) {
234 for( it=
__notes.lower_bound( n ); it!=
__notes.upper_bound( n ); it++ ) {
235 Note* note = it->second;
248 if( it->second==note ) {
258 Note* note = it->second;
270 std::list< Note* > slate;
272 Note* note = it->second;
275 if ( !locked && bRequiresLock ) {
279 slate.push_back( note );
288 while ( slate.size() ) {
289 delete slate.front();
297 Note* note = it->second;
310 ( *it0 )->flattened_virtual_patterns_compute();
312 for(
virtual_patterns_cst_it_t it1=( *it0 )->get_flattened_virtual_patterns()->begin(); it1!=( *it0 )->get_flattened_virtual_patterns()->end(); ++it1 ) {
322 pPatternList->
add( *it,
true );
329 pPatternList->
del( *it );
337 if ( (*it)->__length > nMax ) {
361 sOutput = QString(
"%1[Pattern]\n" ).arg( sPrefix )
362 .append( QString(
"%1%2length: %3\n" ).arg( sPrefix ).arg( s ).arg(
__length ) )
363 .append( QString(
"%1%2denominator: %3\n" ).arg( sPrefix ).arg( s ).arg(
__denominator ) )
364 .append( QString(
"%1%2name: %3\n" ).arg( sPrefix ).arg( s ).arg(
__name ) )
365 .append( QString(
"%1%2category: %3\n" ).arg( sPrefix ).arg( s ).arg(
__category ) )
366 .append( QString(
"%1%2info: %3\n" ).arg( sPrefix ).arg( s ).arg(
__info ) )
367 .append( QString(
"%1%2Notes:\n" ).arg( sPrefix ).arg( s ) );
370 if ( it->second !=
nullptr ) {
371 sOutput.append( QString(
"%1" ).arg( it->second->toQString( sPrefix + s + s, bShort ) ) );
375 sOutput.append( QString(
"%1%2Virtual_patterns:\n" ).arg( sPrefix ).arg( s ) );
377 if ( ii !=
nullptr ) {
378 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
382 sOutput.append( QString(
"%1%2Flattened_virtual_patterns:\n" ).arg( sPrefix ).arg( s ) );
384 if ( ii !=
nullptr ) {
385 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
390 sOutput = QString(
"[Pattern]" )
391 .append( QString(
" length: %1" ).arg(
__length ) )
392 .append( QString(
", denominator: %1" ).arg(
__denominator ) )
393 .append( QString(
", name: %1" ).arg(
__name ) )
394 .append( QString(
", category: %1" ).arg(
__category ) )
395 .append( QString(
", info: %1" ).arg(
__info ) )
396 .append( QString(
", [Notes: " ) );
398 if ( it->second !=
nullptr ) {
399 sOutput.append( QString(
"[%2, %3] " )
400 .arg( it->second->get_instrument()->get_name() )
401 .arg( it->second->get_position() ) );
404 sOutput.append(
"]" );
406 sOutput.append(
", Virtual_patterns: {" );
409 if ( ii !=
nullptr ) {
410 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
414 sOutput.append(
"}, Flattened_virtual_patterns: {" );
417 if ( ii !=
nullptr ) {
418 sOutput.append( QString(
"%1" ).arg( ii->toQString( sPrefix + s + s, bShort ) ) );
422 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 QString pattern_xsd_path()
returns the path to the pattern XSD (xml schema definition) file
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
Pattern class is a Note container.
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
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_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
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;
static Pattern * load_file(const QString &pattern_path, std::shared_ptr< InstrumentList > instruments)
load a pattern from a file
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.
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.
static bool loadDoc(const QString &sPatternPath, std::shared_ptr< InstrumentList > pInstrumentList, XMLDoc *pDoc, bool bSilent=false)
Loads the pattern stored in sPatternPath into pDoc and takes care of all the error handling.
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, const QString &schemapath=nullptr, 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