51 WARNINGLOG(
"Using back compatibility code to load instrument component" );
54 if ( pNode->firstChildElement(
"filename" ).isNull() ) {
56 auto pCompo = std::make_shared<InstrumentComponent>( 0 );
58 XMLNode layerNode = pNode->firstChildElement(
"layer" );
60 while ( ! layerNode.isNull() ) {
62 ERRORLOG( QString(
"Layer #%1 >= m_nMaxLayers (%2). This as well as all further layers will be omitted." )
69 drumkitLicense, bSilent );
70 if ( pLayer !=
nullptr ) {
71 pCompo->set_layer( pLayer, nLayer );
74 layerNode = layerNode.nextSiblingElement(
"layer" );
78 ERRORLOG(
"Unable to load instrument component. Neither 'filename', 'instrumentComponent', nor 'layer' node found. Aborting." );
86 QString sFilename = pNode->
read_string(
"filename",
"",
false,
false, bSilent );
89 sFilename = sDrumkitPath +
"/" + sFilename;
92 auto pSample =
Sample::load( sFilename, drumkitLicense );
93 if ( pSample ==
nullptr ) {
98 WARNINGLOG(
"[readSong] Error loading sample: " +
99 sFilename +
" not found. Trying to load a flac..." );
101 sFilename = sFilename.left( sFilename.length() - 4 );
102 sFilename +=
".flac";
105 if ( pSample ==
nullptr ) {
106 ERRORLOG(
"Error loading sample: " + sFilename +
" not found" );
109 auto pCompo = std::make_shared<InstrumentComponent>( 0 );
110 auto pLayer = std::make_shared<InstrumentLayer>( pSample );
111 pCompo->set_layer( pLayer, 0 );
119 WARNINGLOG( QString(
"this code should not be used anymore, it belongs to 0.9.6" ) );
121 WARNINGLOG( QString(
"loading pattern with legacy code" ) );
124 if( !doc.
read( pattern_path ) ) {
127 XMLNode root = doc.firstChildElement(
"drumkit_pattern" );
128 if ( root.isNull() ) {
129 ERRORLOG(
"drumkit_pattern node not found" );
132 XMLNode pattern_node = root.firstChildElement(
"pattern" );
133 if ( pattern_node.isNull() ) {
138 QString sName = pattern_node.
read_string(
"pattern_name",
"",
false,
false );
139 if ( sName.isEmpty() ) {
140 sName = pattern_node.
read_string(
"pattern_name",
"unknown",
false,
false );
142 QString sInfo = pattern_node.
read_string(
"info",
"" );
143 QString sCategory = pattern_node.
read_string(
"category",
"" );
144 int nSize = pattern_node.
read_int(
"size", -1,
false,
false );
147 pPattern =
new Pattern( sName, sInfo, sCategory, nSize, 4 );
149 if ( pInstrumentList ==
nullptr ) {
150 ERRORLOG(
"invalid instrument list provided" );
154 XMLNode note_list_node = pattern_node.firstChildElement(
"noteList" );
156 if ( ! note_list_node.isNull() ) {
158 XMLNode note_node = note_list_node.firstChildElement(
"note" );
160 while ( !note_node.isNull() ) {
161 Note* pNote =
nullptr;
162 unsigned nPosition = note_node.
read_int(
"position", 0 );
163 float fLeadLag = note_node.
read_float(
"leadlag", 0.0 ,
false ,
false);
164 float fVelocity = note_node.
read_float(
"velocity", 0.8f );
165 float fPanL = note_node.
read_float(
"pan_L", 0.5 );
166 float fPanR = note_node.
read_float(
"pan_R", 0.5 );
169 int nLength = note_node.
read_int(
"length", -1,
true );
170 float nPitch = note_node.
read_float(
"pitch", 0.0,
false,
false );
171 float fProbability = note_node.
read_float(
"probability", 1.0 ,
false ,
false );
172 QString sKey = note_node.
read_string(
"key",
"C0",
false,
false );
173 QString nNoteOff = note_node.
read_string(
"note_off",
"false",
false,
false );
174 int instrId = note_node.
read_int(
"instrument", 0,
true );
176 auto instrRef = pInstrumentList->find( instrId );
178 ERRORLOG( QString(
"Instrument with ID: '%1' not found. Note skipped." ).arg( instrId ) );
179 note_node = note_node.nextSiblingElement(
"note" );
184 bool noteoff =
false;
185 if ( nNoteOff ==
"true" ) {
189 pNote =
new Note( instrRef, nPosition, fVelocity, fPan, nLength, nPitch);
196 note_node = note_node.nextSiblingElement(
"note" );
201 XMLNode sequenceListNode = pattern_node.firstChildElement(
"sequenceList" );
203 int sequence_count = 0;
204 XMLNode sequenceNode = sequenceListNode.firstChildElement(
"sequence" );
205 while ( ! sequenceNode.isNull() ) {
208 XMLNode noteListNode = sequenceNode.firstChildElement(
"noteList" );
209 XMLNode noteNode = noteListNode.firstChildElement(
"note" );
210 while ( !noteNode.isNull() ) {
212 int nInstrId = noteNode.
read_int(
"instrument", -1 );
214 auto pInstr = pInstrumentList->find( nInstrId );
215 if ( pInstr ==
nullptr ) {
216 ERRORLOG( QString(
"Unable to retrieve instrument [%1]" )
222 float fPanL = noteNode.
read_float(
"pan_L", 0.5 );
223 float fPanR = noteNode.
read_float(
"pan_R", 0.5 );
230 noteNode.
read_int(
"length", -1,
true ),
231 noteNode.
read_float(
"pitch", 0.0,
false,
false ) );
236 noteNode = noteNode.nextSiblingElement(
"note" );
238 sequenceNode = sequenceNode.nextSiblingElement(
"sequence" );
248 WARNINGLOG( QString(
"this code should not be used anymore, it belongs to 0.9.6" ) );
250 WARNINGLOG( QString(
"loading playlist with legacy code" ) );
253 if( !doc.
read( pl_path ) ) {
256 XMLNode root = doc.firstChildElement(
"playlist" );
257 if ( root.isNull() ) {
258 ERRORLOG(
"playlist node not found" );
261 QFileInfo fileInfo = QFileInfo( pl_path );
262 QString filename = root.
read_string(
"Name",
"",
false,
false );
263 if ( filename.isEmpty() ) {
264 ERRORLOG(
"Playlist has no name, abort" );
270 XMLNode songsNode = root.firstChildElement(
"Songs" );
271 if ( !songsNode.isNull() ) {
272 XMLNode nextNode = songsNode.firstChildElement(
"next" );
273 while ( !nextNode.isNull() ) {
275 QString songPath = nextNode.
read_string(
"song",
"",
false,
false );
276 if ( !songPath.isEmpty() ) {
278 QFileInfo songPathInfo( fileInfo.absoluteDir(), songPath );
279 entry->
filePath = songPathInfo.absoluteFilePath();
280 entry->
fileExists = songPathInfo.isReadable();
283 pPlaylist->
add( entry );
286 nextNode = nextNode.nextSiblingElement(
"next" );
296 std::vector<PatternList*>* pPatternGroupVector =
new std::vector<PatternList*>;
299 WARNINGLOG(
"Using old pattern group vector code for back compatibility" );
302 XMLNode pPatternIDNode = pNode->firstChildElement(
"patternID" );
303 while ( ! pPatternIDNode.isNull() ) {
306 QString sPatId = pPatternIDNode.firstChildElement().text();
309 for (
const auto& ppPat : *pPatternList ) {
310 if ( ppPat !=
nullptr ) {
311 if ( ppPat->get_name() == sPatId ) {
318 if ( pPattern ==
nullptr ) {
320 WARNINGLOG( QString(
"Pattern [%1] not found in patternList." )
323 delete pPatternSequence;
326 pPatternSequence->
add( pPattern );
327 pPatternGroupVector->push_back( pPatternSequence );
330 pPatternIDNode = pPatternIDNode.nextSiblingElement(
"patternID" );
333 return pPatternGroupVector;
337 if ( pFile ==
nullptr ) {
338 ERRORLOG(
"Supplied file not valid" );
342 if ( ! pFile->seek( 0 ) ) {
343 ERRORLOG( QString(
"Unable to move to the beginning of file [%1]. Compatibility check mmight fail." )
344 .arg( pFile->fileName() ) );
347 QString sFirstLine = pFile->readLine();
348 if ( ! sFirstLine.startsWith(
"<?xml" ) ) {
349 WARNINGLOG( QString(
"File [%1] is being read in TinyXML compatibility mode")
350 .arg( pFile->fileName() ) );
359 if ( pFile ==
nullptr ) {
360 ERRORLOG(
"Supplied file not valid" );
364 if ( ! pFile->seek( 0 ) ) {
365 ERRORLOG( QString(
"Unable to move to the beginning of file [%1]. Converting mmight fail." )
366 .arg( pFile->fileName() ) );
369 QString sEncoding = QTextCodec::codecForLocale()->name();
370 if ( sEncoding ==
"System" ) {
374 QByteArray buf = QString(
"<?xml version='1.0' encoding='%1' ?>\n")
378 while ( ! pFile->atEnd() ) {
379 line = pFile->readLine();
384 return std::move( buf );
412 nPos = pString->indexOf(
"&#x" );
413 while ( nPos != -1 ) {
414 if ( isxdigit( pString->at( nPos + 3 ) ) &&
415 isxdigit( pString->at( nPos + 4 ) ) &&
416 pString->at( nPos + 5 ) ==
';' ) {
418 char w1 = pString->at( nPos + 3 );
419 char w2 = pString->at( nPos + 4 );
421 w1 = tolower( w1 ) - 0x30;
427 w2 = tolower( w2 ) - 0x30;
433 char ch = ( w1 << 4 ) | w2;
434 (*pString)[nPos] = ch;
436 pString->remove( nPos, 5 );
438 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 ...
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, const QString &schemapath=nullptr, 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