50 WARNINGLOG(
"Using back compatibility code to load instrument component" );
53 if ( pNode->firstChildElement(
"filename" ).isNull() ) {
55 auto pCompo = std::make_shared<InstrumentComponent>( 0 );
57 XMLNode layerNode = pNode->firstChildElement(
"layer" );
59 while ( ! layerNode.isNull() ) {
61 ERRORLOG( QString(
"Layer #%1 >= m_nMaxLayers (%2). This as well as all further layers will be omitted." )
68 drumkitLicense, bSilent );
69 if ( pLayer !=
nullptr ) {
70 pCompo->set_layer( pLayer, nLayer );
73 layerNode = layerNode.nextSiblingElement(
"layer" );
77 ERRORLOG(
"Unable to load instrument component. Neither 'filename', 'instrumentComponent', nor 'layer' node found. Aborting." );
85 QString sFilename = pNode->
read_string(
"filename",
"",
false,
false, bSilent );
88 sFilename = sDrumkitPath +
"/" + sFilename;
91 auto pSample =
Sample::load( sFilename, drumkitLicense );
92 if ( pSample ==
nullptr ) {
97 WARNINGLOG(
"[readSong] Error loading sample: " +
98 sFilename +
" not found. Trying to load a flac..." );
100 sFilename = sFilename.left( sFilename.length() - 4 );
101 sFilename +=
".flac";
104 if ( pSample ==
nullptr ) {
105 ERRORLOG(
"Error loading sample: " + sFilename +
" not found" );
108 auto pCompo = std::make_shared<InstrumentComponent>( 0 );
109 auto pLayer = std::make_shared<InstrumentLayer>( pSample );
110 pCompo->set_layer( pLayer, 0 );
118 WARNINGLOG( QString(
"this code should not be used anymore, it belongs to 0.9.6" ) );
120 WARNINGLOG( QString(
"loading pattern with legacy code" ) );
123 if( !doc.
read( pattern_path ) ) {
126 XMLNode root = doc.firstChildElement(
"drumkit_pattern" );
127 if ( root.isNull() ) {
128 ERRORLOG(
"drumkit_pattern node not found" );
131 XMLNode pattern_node = root.firstChildElement(
"pattern" );
132 if ( pattern_node.isNull() ) {
137 QString sName = pattern_node.
read_string(
"pattern_name",
"",
false,
false );
138 if ( sName.isEmpty() ) {
139 sName = pattern_node.
read_string(
"pattern_name",
"unknown",
false,
false );
141 QString sInfo = pattern_node.
read_string(
"info",
"" );
142 QString sCategory = pattern_node.
read_string(
"category",
"" );
143 int nSize = pattern_node.
read_int(
"size", -1,
false,
false );
146 pPattern =
new Pattern( sName, sInfo, sCategory, nSize, 4 );
148 if ( pInstrumentList ==
nullptr ) {
149 ERRORLOG(
"invalid instrument list provided" );
153 XMLNode note_list_node = pattern_node.firstChildElement(
"noteList" );
155 if ( ! note_list_node.isNull() ) {
157 XMLNode note_node = note_list_node.firstChildElement(
"note" );
159 while ( !note_node.isNull() ) {
160 Note* pNote =
nullptr;
161 unsigned nPosition = note_node.
read_int(
"position", 0 );
162 float fLeadLag = note_node.
read_float(
"leadlag", 0.0 ,
false ,
false);
163 float fVelocity = note_node.
read_float(
"velocity", 0.8f );
164 float fPanL = note_node.
read_float(
"pan_L", 0.5 );
165 float fPanR = note_node.
read_float(
"pan_R", 0.5 );
168 int nLength = note_node.
read_int(
"length", -1,
true );
169 float nPitch = note_node.
read_float(
"pitch", 0.0,
false,
false );
170 float fProbability = note_node.
read_float(
"probability", 1.0 ,
false ,
false );
171 QString sKey = note_node.
read_string(
"key",
"C0",
false,
false );
172 QString nNoteOff = note_node.
read_string(
"note_off",
"false",
false,
false );
173 int instrId = note_node.
read_int(
"instrument", 0,
true );
175 auto instrRef = pInstrumentList->find( instrId );
177 ERRORLOG( QString(
"Instrument with ID: '%1' not found. Note skipped." ).arg( instrId ) );
178 note_node = note_node.nextSiblingElement(
"note" );
183 bool noteoff =
false;
184 if ( nNoteOff ==
"true" ) {
188 pNote =
new Note( instrRef, nPosition, fVelocity, fPan, nLength, nPitch);
195 note_node = note_node.nextSiblingElement(
"note" );
200 XMLNode sequenceListNode = pattern_node.firstChildElement(
"sequenceList" );
202 int sequence_count = 0;
203 XMLNode sequenceNode = sequenceListNode.firstChildElement(
"sequence" );
204 while ( ! sequenceNode.isNull() ) {
207 XMLNode noteListNode = sequenceNode.firstChildElement(
"noteList" );
208 XMLNode noteNode = noteListNode.firstChildElement(
"note" );
209 while ( !noteNode.isNull() ) {
211 int nInstrId = noteNode.
read_int(
"instrument", -1 );
213 auto pInstr = pInstrumentList->find( nInstrId );
214 if ( pInstr ==
nullptr ) {
215 ERRORLOG( QString(
"Unable to retrieve instrument [%1]" )
221 float fPanL = noteNode.
read_float(
"pan_L", 0.5 );
222 float fPanR = noteNode.
read_float(
"pan_R", 0.5 );
229 noteNode.
read_int(
"length", -1,
true ),
230 noteNode.
read_float(
"pitch", 0.0,
false,
false ) );
235 noteNode = noteNode.nextSiblingElement(
"note" );
237 sequenceNode = sequenceNode.nextSiblingElement(
"sequence" );
247 WARNINGLOG( QString(
"this code should not be used anymore, it belongs to 0.9.6" ) );
249 WARNINGLOG( QString(
"loading playlist with legacy code" ) );
252 if( !doc.
read( pl_path ) ) {
255 XMLNode root = doc.firstChildElement(
"playlist" );
256 if ( root.isNull() ) {
257 ERRORLOG(
"playlist node not found" );
260 QFileInfo fileInfo = QFileInfo( pl_path );
261 QString filename = root.
read_string(
"Name",
"",
false,
false );
262 if ( filename.isEmpty() ) {
268 XMLNode songsNode = root.firstChildElement(
"Songs" );
269 if ( !songsNode.isNull() ) {
270 XMLNode nextNode = songsNode.firstChildElement(
"next" );
271 while ( !nextNode.isNull() ) {
273 QString songPath = nextNode.
read_string(
"song",
"",
false,
false );
274 if ( !songPath.isEmpty() ) {
276 QFileInfo songPathInfo( fileInfo.absoluteDir(), songPath );
277 entry->
filePath = songPathInfo.absoluteFilePath();
278 entry->
fileExists = songPathInfo.isReadable();
281 pPlaylist->
add( entry );
284 nextNode = nextNode.nextSiblingElement(
"next" );
294 std::vector<PatternList*>* pPatternGroupVector =
new std::vector<PatternList*>;
297 WARNINGLOG(
"Using old pattern group vector code for back compatibility" );
300 XMLNode pPatternIDNode = pNode->firstChildElement(
"patternID" );
301 while ( ! pPatternIDNode.isNull() ) {
304 QString sPatId = pPatternIDNode.firstChildElement().text();
307 for (
const auto& ppPat : *pPatternList ) {
308 if ( ppPat !=
nullptr ) {
309 if ( ppPat->get_name() == sPatId ) {
316 if ( pPattern ==
nullptr ) {
318 WARNINGLOG( QString(
"Pattern [%1] not found in patternList." )
321 delete pPatternSequence;
324 pPatternSequence->
add( pPattern );
325 pPatternGroupVector->push_back( pPatternSequence );
328 pPatternIDNode = pPatternIDNode.nextSiblingElement(
"patternID" );
331 return pPatternGroupVector;
335 if ( pFile ==
nullptr ) {
336 ERRORLOG(
"Supplied file not valid" );
340 if ( ! pFile->seek( 0 ) ) {
341 ERRORLOG( QString(
"Unable to move to the beginning of file [%1]. Compatibility check mmight fail." )
342 .arg( pFile->fileName() ) );
345 QString sFirstLine = pFile->readLine();
346 if ( ! sFirstLine.startsWith(
"<?xml" ) ) {
347 WARNINGLOG( QString(
"File [%1] is being read in TinyXML compatibility mode")
348 .arg( pFile->fileName() ) );
357 if ( pFile ==
nullptr ) {
358 ERRORLOG(
"Supplied file not valid" );
362 if ( ! pFile->seek( 0 ) ) {
363 ERRORLOG( QString(
"Unable to move to the beginning of file [%1]. Converting mmight fail." )
364 .arg( pFile->fileName() ) );
368 QByteArray buf =
"<?xml version='1.0' ?>\n";
370 while ( ! pFile->atEnd() ) {
371 line = pFile->readLine();
376 return std::move( buf );
404 nPos = pString->indexOf(
"&#x" );
405 while ( nPos != -1 ) {
406 if ( isxdigit( pString->at( nPos + 3 ) ) &&
407 isxdigit( pString->at( nPos + 4 ) ) &&
408 pString->at( nPos + 5 ) ==
';' ) {
410 char w1 = pString->at( nPos + 3 );
411 char w2 = pString->at( nPos + 4 );
413 w1 = tolower( w1 ) - 0x30;
419 w2 = tolower( w2 ) - 0x30;
425 char ch = ( w1 << 4 ) | w2;
426 (*pString)[nPos] = ch;
428 pString->remove( nPos, 5 );
430 nPos = pString->indexOf(
"&#x" );
static bool file_exists(const QString &path, bool silent=false)
returns true if the given path is an existing regular file
static int getMaxLayers()
static std::shared_ptr< InstrumentLayer > load_from(XMLNode *pNode, const QString &sDrumkitPath, const License &drumkitLicense=License(), bool bSilent=false)
load an instrument layer from an XMLNode
static void convertStringFromTinyXML(QByteArray *pString)
Convert (in-place) an XML escape sequence into a literal byte, rather than the character it actually ...
static Pattern * load_drumkit_pattern(const QString &pattern_path, std::shared_ptr< InstrumentList > instrList)
load pattern from a file
static bool checkTinyXMLCompatMode(QFile *pFile, bool bSilent=false)
static std::vector< PatternList * > * loadPatternGroupVector(XMLNode *pNode, PatternList *pPatternList, bool bSilent=false)
static QByteArray convertFromTinyXML(QFile *pFile, bool bSilent=false)
static Playlist * load_playlist(Playlist *pl, const QString &pl_path)
load playlist from a file
static std::shared_ptr< InstrumentComponent > loadInstrumentComponent(XMLNode *pNode, const QString &sDrumkitPath, const License &drumkitLicense, bool bSilent=false)
Backward compatibility code to load an InstrumentComponent from an Instrument which itself did not co...
Wrapper class to help Hydrogen deal with the license information specified in a drumkit.
A note plays an associated instrument with a velocity left and right pan.
void set_lead_lag(float value)
__lead_lag setter
void set_key_octave(const QString &str)
parse str and set __key and __octave
void set_probability(float value)
void set_note_off(bool value)
__note_off setter
PatternList is a collection of patterns.
void add(Pattern *pattern, bool bAddVirtuals=false)
add a pattern to the list
Pattern class is a Note container.
void insert_note(Note *note)
insert a new note within __notes
void setFilename(const QString &filename)
static std::shared_ptr< Sample > load(const QString &filepath, const License &license=License())
static float getRatioPan(float fPan_L, float fPan_R)
This function is used to load old version files (v<=1.1).
XMLDoc is a subclass of QDomDocument with read and write methods.
bool read(const QString &filepath, bool bSilent=false)
read the content of an xml 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
bool read_bool(const QString &node, bool default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a boolean 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
float read_float(const QString &node, float default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads a float stored into a child node
bool version_older_than(int major, int minor, int patch)
return true of the current version is older than the given values