root/branches/jackMidi/libs/hydrogen/src/local_file_mgr.cpp @ 826

Revision 826, 42.7 KB (checked in by gabriel@…, 4 years ago)

Merge rev 594:682 from trunk

Conflicts:

Sconstruct

Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22
23#include "config.h"
24#include "version.h"
25
26
27#include <hydrogen/adsr.h>
28#include <hydrogen/data_path.h>
29#include <hydrogen/hydrogen.h>
30#include <hydrogen/h2_exception.h>
31#include <hydrogen/instrument.h>
32#include <hydrogen/LocalFileMng.h>
33#include <hydrogen/note.h>
34#include <hydrogen/Pattern.h>
35#include <hydrogen/Preferences.h>
36#include <hydrogen/Song.h>
37#include <hydrogen/SoundLibrary.h>
38#include <hydrogen/sample.h>
39#include <hydrogen/fx/Effects.h>
40
41
42#include <cstdlib>
43#include <cassert>
44#include <sys/stat.h>
45
46#include <QDir>
47#include <QApplication>
48
49#include "xml/tinyxml.h"
50
51#include <algorithm>
52//#include <cstdio>
53//#include <vector>
54
55namespace H2Core
56{
57
58LocalFileMng::LocalFileMng()
59                : Object( "LocalFileMng" )
60{
61//      infoLog("INIT");
62}
63
64
65
66LocalFileMng::~LocalFileMng()
67{
68//      infoLog("DESTROY");
69}
70
71
72QString LocalFileMng::getDrumkitNameForPattern( const QString& patternDir )
73{
74        QString patternInfoFile = patternDir;
75
76        TiXmlDocument doc( patternInfoFile.toAscii() );
77        doc.LoadFile();
78
79        TiXmlNode* rootNode;    // root element
80        if ( !( rootNode = doc.FirstChild( "drumkit_pattern" ) ) ) {
81                ERRORLOG( "Error reading Pattern: Pattern_drumkit_infonode not found " + patternDir); return NULL;
82        }
83
84
85        QString sDrumkitName( LocalFileMng::readXmlString( rootNode,"pattern_for_drumkit", "" ) );
86        return sDrumkitName;
87       
88}
89
90
91QString LocalFileMng::getCategoryFromPatternName( const QString& patternPathName )
92{
93        QString sCatrgory = patternPathName;
94        TiXmlDocument doc( sCatrgory.toAscii() );
95        doc.LoadFile();
96
97
98        TiXmlNode* rootNode;    // root element
99        if ( !( rootNode = doc.FirstChild( "drumkit_pattern" ) ) ) {
100                ERRORLOG( "Error reading Pattern: Pattern_drumkit_info node not found ");
101                 return NULL;
102        }
103
104        TiXmlNode* patternNode = rootNode->FirstChild( "pattern" );
105        QString sCategoryName( LocalFileMng::readXmlString( patternNode,"category", "" ) );
106
107        return sCategoryName;
108       
109}
110
111QString LocalFileMng::getPatternNameFromPatternDir( const QString& patternDirName)
112{
113        QString sDir = patternDirName;
114        TiXmlDocument doc( sDir.toAscii() );
115        doc.LoadFile();
116
117
118        TiXmlNode* rootNode;    // root element
119        if ( !( rootNode = doc.FirstChild( "drumkit_pattern" ) ) ) {
120                ERRORLOG( "Error reading Pattern: Pattern_drumkit_info node not found ");
121                 return NULL;
122        }
123
124        TiXmlNode* patternNode = rootNode->FirstChild( "pattern" );
125        QString sPatternName( LocalFileMng::readXmlString( patternNode,"pattern_name", "" ) );
126
127        return sPatternName;
128       
129}
130
131
132Pattern* LocalFileMng::loadPattern( const QString& directory )
133{
134
135        InstrumentList* instrList = Hydrogen::get_instance()->getSong()->get_instrument_list();
136        Pattern *pPattern = NULL;
137        QString patternInfoFile = directory;
138
139        QFile check( patternInfoFile );
140        if (check.exists() == false) {
141                ERRORLOG( QString("Load Pattern: Data file %1 not found." ).arg( patternInfoFile ) );
142                return NULL;
143        }
144
145
146        TiXmlDocument doc( patternInfoFile.toAscii() );
147        doc.LoadFile();
148
149        // root element
150        TiXmlNode* rootNode;    // root element
151        if ( !( rootNode = doc.FirstChild( "drumkit_pattern" ) ) ) {
152                ERRORLOG( "Error reading Pattern: Pattern_drumkit_infonode not found" ); return NULL;
153        }
154
155        TiXmlNode* patternNode = rootNode->FirstChild( "pattern" );
156
157        QString sName( LocalFileMng::readXmlString( patternNode,"pattern_name", "" ) );
158        QString sCategory( LocalFileMng::readXmlString( patternNode,"category", "" ) );
159
160        int nSize = -1;
161        nSize = LocalFileMng::readXmlInt( patternNode, "size",nSize ,false,false );
162        pPattern = new Pattern( sName, sCategory, nSize );
163
164
165
166        TiXmlNode* pNoteListNode = patternNode->FirstChild( "noteList" );
167        if ( pNoteListNode )
168        {
169                // new code  :)
170                for ( TiXmlNode* noteNode = pNoteListNode->FirstChild( "note" ); noteNode; noteNode = noteNode->NextSibling( "note" ) )
171                {
172                        Note* pNote = NULL;
173                        unsigned nPosition = LocalFileMng::readXmlInt( noteNode, "position", 0 );
174                        float fLeadLag = LocalFileMng::readXmlFloat( noteNode, "leadlag", 0.0 );
175                        float fVelocity = LocalFileMng::readXmlFloat( noteNode, "velocity", 0.8f );
176                        float fPan_L = LocalFileMng::readXmlFloat( noteNode, "pan_L", 0.5 );
177                        float fPan_R = LocalFileMng::readXmlFloat( noteNode, "pan_R", 0.5 );
178                        int nLength = LocalFileMng::readXmlInt( noteNode, "length", -1, true );
179                        float nPitch = LocalFileMng::readXmlFloat( noteNode, "pitch", 0.0, false, false );
180                        QString sKey = LocalFileMng::readXmlString( noteNode, "key", "C0", false, false );
181
182                        QString instrId = LocalFileMng::readXmlString( noteNode, "instrument", "" );
183
184                        Instrument *instrRef = NULL;
185                        // search instrument by ref
186                        for ( unsigned i = 0; i < instrList->get_size(); i++ ) { Instrument *instr = instrList->get( i );
187                                if ( instrId == instr->get_id() ) {
188                                        instrRef = instr;
189                                        break;
190                                }
191                        }
192                        if ( !instrRef ) {
193                                ERRORLOG( QString( "Instrument with ID: '%1' not found. Note skipped." ).arg( instrId ) );
194                                continue;
195                        }
196                        //assert( instrRef );
197
198                        pNote = new Note( instrRef, nPosition, fVelocity, fPan_L, fPan_R, nLength, nPitch, Note::stringToKey( sKey ) );
199                        pNote->set_leadlag(fLeadLag);
200                        pPattern->note_map.insert( std::make_pair( pNote->get_position(),pNote ) );
201                }
202        }
203
204        return pPattern;
205
206}
207
208
209int LocalFileMng::savePattern( Song *song , int selectedpattern , const QString& patternname, const QString& realpatternname, int mode)
210{
211        //int mode = 1 save, int mode = 2 save as
212        // INSTRUMENT NODE
213
214        Instrument *instr = song->get_instrument_list()->get( 0 );
215        assert( instr );
216
217        Pattern *pat = song->get_pattern_list()->get( selectedpattern );
218
219        QString sPatternDir = Preferences::getInstance()->getDataDirectory() + "patterns/" +  instr->get_drumkit_name();
220
221        INFOLOG( "[savePattern]" + sPatternDir );
222
223        // check if the directory exists
224        QDir dir( sPatternDir );
225        QDir dirPattern( sPatternDir );
226        if ( !dir.exists() ) {
227                dir.mkdir( sPatternDir );// create the drumkit directory
228        }
229
230        QString sPatternXmlFilename = "";
231        // create the drumkit.xml file
232        switch ( mode ){
233                case 1: //save
234                        sPatternXmlFilename = sPatternDir + "/" + QString( patternname + QString( ".h2pattern" ));
235                        break;
236                case 2: //save as
237                        sPatternXmlFilename = patternname;
238                        break;
239                default:
240                        WARNINGLOG( "Pattern Save unknown status");
241                        break;
242
243        }
244
245//test if the file exists
246        QFile testfile( sPatternXmlFilename );
247        if ( testfile.exists() && mode == 1)
248                return 1;
249
250        TiXmlDocument doc( sPatternXmlFilename.toAscii() );
251
252        TiXmlElement rootNode( "drumkit_pattern" );
253        //LIB_ID just in work to get better usability
254        //writeXmlString( &rootNode, "LIB_ID", "in_work" );
255        writeXmlString( &rootNode, "pattern_for_drumkit", instr->get_drumkit_name() );
256
257
258        // pattern
259        TiXmlElement patternNode( "pattern" );
260        LocalFileMng::writeXmlString( &patternNode, "pattern_name", realpatternname );
261        LocalFileMng::writeXmlString( &patternNode, "category", pat->get_category() );
262        writeXmlString( &patternNode, "size", to_string( pat->get_lenght() ) );
263
264                TiXmlElement noteListNode( "noteList" );
265                std::multimap <int, Note*>::iterator pos;
266                for ( pos = pat->note_map.begin(); pos != pat->note_map.end(); ++pos ) {
267                        Note *pNote = pos->second;
268                        assert( pNote );
269
270                        TiXmlElement noteNode( "note" );
271                        writeXmlString( &noteNode, "position", to_string( pNote->get_position() ) );
272                        writeXmlString( &noteNode, "leadlag", to_string( pNote->get_leadlag() ) );
273                        writeXmlString( &noteNode, "velocity", to_string( pNote->get_velocity() ) );
274                        writeXmlString( &noteNode, "pan_L", to_string( pNote->get_pan_l() ) );
275                        writeXmlString( &noteNode, "pan_R", to_string( pNote->get_pan_r() ) );
276                        writeXmlString( &noteNode, "pitch", to_string( pNote->get_pitch() ) );
277
278                        writeXmlString( &noteNode, "key", Note::keyToString( pNote->m_noteKey ) );
279
280                        writeXmlString( &noteNode, "length", to_string( pNote->get_lenght() ) );
281                        writeXmlString( &noteNode, "instrument", pNote->get_instrument()->get_id() );
282                        noteListNode.InsertEndChild( noteNode );
283                }
284                patternNode.InsertEndChild( noteListNode );
285
286        rootNode.InsertEndChild( patternNode );
287
288        doc.InsertEndChild( rootNode );
289        doc.SaveFile();
290
291        QFile anotherTestfile( sPatternXmlFilename );
292        if ( ! anotherTestfile.exists() )
293                return 1;
294
295        return 0; // ok
296}
297
298
299
300
301void LocalFileMng::fileCopy( const QString& sOrigFilename, const QString& sDestFilename )
302{
303        // TODO: use QT copy functions
304
305        INFOLOG( sOrigFilename + " --> " + sDestFilename );
306
307        if ( sOrigFilename == sDestFilename ) {
308                return;
309        }
310
311        FILE *inputFile = fopen( sOrigFilename.toAscii(), "rb" );
312        if ( inputFile == NULL ) {
313                ERRORLOG( "Error opening " + sOrigFilename );
314                return;
315        }
316
317        FILE *outputFile = fopen( sDestFilename.toAscii(), "wb" );
318        if ( outputFile == NULL ) {
319                ERRORLOG( "Error opening " + sDestFilename );
320                return;
321        }
322
323        const int bufferSize = 512;
324        char buffer[ bufferSize ];
325        while ( feof( inputFile ) == 0 ) {
326                size_t read = fread( buffer, sizeof( char ), bufferSize, inputFile );
327                fwrite( buffer, sizeof( char ), read, outputFile );
328        }
329
330        fclose( inputFile );
331        fclose( outputFile );
332}
333
334
335
336std::vector<QString> LocalFileMng::getSongList()
337{
338        std::vector<QString> list;
339        QString sDirectory = Preferences::getInstance()->getDataDirectory()  + "/songs/";
340
341        QDir dir( sDirectory );
342
343        if ( !dir.exists() ) {
344                ERRORLOG( QString( "[getSongList] Directory %1 not found" ).arg( sDirectory ) );
345        } else {
346                QFileInfoList fileList = dir.entryInfoList();
347                dir.setFilter( QDir::Dirs );
348                for ( int i = 0; i < fileList.size(); ++i ) {
349                        QString sFile = fileList.at( i ).fileName();
350
351                        if ( ( sFile == "." ) || ( sFile == ".." ) || ( sFile == "CVS" )  || ( sFile == ".svn" ) ) {
352                                continue;
353                        }
354
355                        list.push_back( sFile.left( sFile.indexOf( "." ) ) );
356                }
357        }
358
359        return list;
360}
361
362int LocalFileMng::getPatternList( const QString&  sPatternDir)
363{
364        std::vector<QString> list;
365        QDir dir( sPatternDir );
366
367        if ( !dir.exists() ) {
368                ERRORLOG( QString( "[getPatternList] Directory %1patterns not found" ).arg( sPatternDir ) );
369        } else {
370                dir.setFilter( QDir::Files );
371                QFileInfoList fileList = dir.entryInfoList();
372               
373                for ( int i = 0; i < fileList.size(); ++i ) {
374                        QString sFile = sPatternDir + "/" + fileList.at( i ).fileName();
375                       
376                        if( sFile.endsWith(".h2pattern") ){
377                                list.push_back( sFile/*.left( sFile.indexOf( "." ) )*/ );
378                        }
379                }
380        }
381        mergeAllPatternList( list );
382        return 0;
383}
384
385
386std::vector<QString> LocalFileMng::getAllPatternName()
387{
388        std::vector<QString> alllist;
389
390        for (uint i = 0; i < m_allPatternList.size(); ++i) {
391                QString patternInfoFile =  m_allPatternList[i];
392
393
394                TiXmlDocument doc( patternInfoFile.toAscii() );
395                doc.LoadFile();
396
397                TiXmlNode* rootNode;    // root element
398                if ( !( rootNode = doc.FirstChild( "drumkit_pattern" ) ) ) {
399                        ERRORLOG( "Error reading Pattern: Pattern_drumkit_info node not found ");
400                }else{
401                        TiXmlNode* patternNode = rootNode->FirstChild( "pattern" );
402
403                        QString sPatternName( LocalFileMng::readXmlString( patternNode,"pattern_name", "" ) );
404                        alllist.push_back(sPatternName);
405                }
406
407        }
408        return alllist;
409}
410
411
412
413std::vector<QString> LocalFileMng::getAllCategoriesFromPattern()
414{
415        Preferences *pPref = H2Core::Preferences::getInstance();
416        std::list<QString>::const_iterator cur_testpatternCategories;
417
418        std::vector<QString> categorylist;
419        for (uint i = 0; i < m_allPatternList.size(); ++i) {
420                QString patternInfoFile =  m_allPatternList[i];
421               
422                TiXmlDocument doc( patternInfoFile.toAscii() );
423                doc.LoadFile();
424
425                TiXmlNode* rootNode;    // root element
426                if ( !( rootNode = doc.FirstChild( "drumkit_pattern" ) ) ) {
427                        ERRORLOG( "Error reading Pattern: Pattern_drumkit_info node not found ");
428                }else{
429                        TiXmlNode* patternNode = rootNode->FirstChild( "pattern" );
430                        QString sCategoryName( LocalFileMng::readXmlString( patternNode,"category", "" ) );
431
432
433                        if ( sCategoryName != "" ){
434                                bool test = true;
435                                for (uint i = 0; i < categorylist.size(); ++i){
436                                        if ( sCategoryName == categorylist[i] ){
437                                                test = false;
438                                        }
439                                }
440                                 if (test == true){
441                                        categorylist.push_back(sCategoryName);
442
443                                        //this merge new categories to user categories list
444                                        bool test2 = true;
445                                        for( cur_testpatternCategories = pPref->m_patternCategories.begin(); cur_testpatternCategories != pPref->m_patternCategories.end(); ++cur_testpatternCategories ){
446                                                if ( sCategoryName == *cur_testpatternCategories ){
447                                                        test2 = false;
448                                                }
449                                        }
450                               
451                                        if (test2 == true ) {
452                                                pPref->m_patternCategories.push_back( sCategoryName );
453                                        }
454                                }
455                        }
456                }
457        }
458
459        std::sort(categorylist.begin(), categorylist.end());
460        return categorylist;
461}
462
463
464
465std::vector<QString> LocalFileMng::getPatternsForDrumkit( const QString& sDrumkit )
466{
467        std::vector<QString> list;
468
469        QDir dir( Preferences::getInstance()->getDataDirectory() + "/patterns/" + sDrumkit );
470
471        if ( !dir.exists() ) {
472                INFOLOG( QString( "No patterns for drumkit '%1'." ).arg( sDrumkit ) );
473        } else {
474                QFileInfoList fileList = dir.entryInfoList();
475                dir.setFilter( QDir::Dirs );
476                for ( int i = 0; i < fileList.size(); ++i ) {
477                        QString sFile = fileList.at( i ).fileName();
478
479                        if ( ( sFile == "." ) || ( sFile == ".." ) || ( sFile == "CVS" )  || ( sFile == ".svn" ) ) {
480                                continue;
481                        }
482
483                        list.push_back( sFile.left( sFile.indexOf( "." ) ) );
484                }
485        }
486
487        return list;
488}
489
490
491
492std::vector<QString> LocalFileMng::getDrumkitsFromDirectory( QString sDirectory )
493{
494        /*
495                returns a list of all drumkits in the given directory
496        */
497
498        std::vector<QString> list;
499
500        QDir dir( sDirectory );
501        if ( !dir.exists() ) {
502                ERRORLOG( QString( "[getDrumkitList] Directory %1 not found" ).arg( sDirectory ) );
503        } else {
504                QFileInfoList fileList = dir.entryInfoList();
505                dir.setFilter( QDir::Dirs );
506                for ( int i = 0; i < fileList.size(); ++i ) {
507                        QString sFile = fileList.at( i ).fileName();
508                        if ( ( sFile == "." ) || ( sFile == ".." ) || ( sFile == "CVS" )  || ( sFile == ".svn" ) ||
509                        (sFile =="songs" ) || ( sFile == "patterns" )  || (sFile == "drumkits" || sFile == "playlists" ) || (sFile == "scripts" )) {
510                                continue;
511                        }
512                        if(! sDirectory.endsWith("/")) sDirectory = sDirectory + "/";
513                        list.push_back( sDirectory + sFile );
514                }
515        }
516
517        return list;
518}
519
520
521
522std::vector<QString> mergeQStringVectors( std::vector<QString> firstVector , std::vector<QString> secondVector )
523{
524        /*
525                 merges two vectors ( containing drumkits). Elements of the first vector have priority
526        */
527
528        if( firstVector.size() == 0 ) return secondVector;
529        if( secondVector.size() == 0 ) return firstVector;
530       
531        std::vector<QString> newVector;
532
533        newVector = firstVector;
534        newVector.resize(firstVector.size()+ secondVector.size());
535
536
537        for ( int i = 0; i < (int)secondVector.size(); ++i )
538        {
539                QString toFind = secondVector[i];
540               
541                for ( int ii = 0; ii < (int)firstVector.size(); ++ii )
542                {
543                        if( toFind == firstVector[ii])
544                        {
545                                //the String already exists in firstVector, don't copy it to the resulting vector
546                                break;
547                        }
548                }
549                newVector[firstVector.size() + i] = toFind;
550        }
551
552        return newVector;
553}
554
555
556std::vector<QString> LocalFileMng::getPatternDirList()
557{
558        return getDrumkitsFromDirectory( Preferences::getInstance()->getDataDirectory() + "patterns" );;
559}
560
561
562int  LocalFileMng::mergeAllPatternList( std::vector<QString> current )
563{
564        m_allPatternList = mergeQStringVectors (m_allPatternList, current );
565        return 0;
566}
567
568
569
570std::vector<QString> LocalFileMng::getUserDrumkitList()
571{
572        std::vector<QString> oldLocation = getDrumkitsFromDirectory( Preferences::getInstance()->getDataDirectory() );
573        std::vector<QString> newLocation = getDrumkitsFromDirectory( Preferences::getInstance()->getDataDirectory() + "drumkits" );
574        return mergeQStringVectors( newLocation ,  oldLocation );
575}
576
577std::vector<QString> LocalFileMng::getSystemDrumkitList()
578{
579        return getDrumkitsFromDirectory( DataPath::get_data_path() + "/drumkits" );
580}
581
582
583QString LocalFileMng::getDrumkitDirectory( const QString& drumkitName )
584{
585        // search in system drumkit
586        std::vector<QString> systemDrumkits = Drumkit::getSystemDrumkitList();
587        for ( unsigned i = 0; i < systemDrumkits.size(); i++ ) {
588                if ( systemDrumkits[ i ].endsWith(drumkitName) ) {
589                        QString path = QString( DataPath::get_data_path() ) + "/drumkits/";
590                        return path;
591                }
592        }
593
594        // search in user drumkit
595        std::vector<QString> userDrumkits = Drumkit::getUserDrumkitList();
596        for ( unsigned i = 0; i < userDrumkits.size(); i++ ) {
597                if ( userDrumkits[ i ].endsWith(drumkitName) ) {
598                        QString path = Preferences::getInstance()->getDataDirectory();
599                        return userDrumkits[ i ].remove(userDrumkits[ i ].length() - drumkitName.length(),drumkitName.length());
600                }
601        }
602
603        ERRORLOG( "drumkit \"" + drumkitName + "\" not found" );
604        return "";      // FIXME
605}
606
607
608
609/// Restituisce un oggetto DrumkitInfo.
610/// Gli strumenti non hanno dei veri propri sample,
611/// viene utilizzato solo il campo filename.
612Drumkit* LocalFileMng::loadDrumkit( const QString& directory )
613{
614        //INFOLOG( directory );
615
616        // che if the drumkit.xml file exists
617       
618        QString drumkitInfoFile = directory + "/drumkit.xml";
619        QFileInfo fInfo( directory );
620
621        if( fInfo.isFile() )
622                return NULL;
623
624        if ( QFile( drumkitInfoFile ).exists() == false ) {
625                ERRORLOG( "Load Instrument: Data file " + drumkitInfoFile + " not found." );
626                return NULL;
627        }
628
629        TiXmlDocument doc( drumkitInfoFile.toAscii() );
630        doc.LoadFile();
631
632        // root element
633        TiXmlNode* drumkitNode; // root element
634        if ( !( drumkitNode = doc.FirstChild( "drumkit_info" ) ) ) {
635                ERRORLOG( "Error reading drumkit: drumkit_info node not found" );
636                return NULL;
637        }
638
639        // Name
640        QString sDrumkitName = readXmlString( drumkitNode, "name", "" );
641        if ( sDrumkitName == "" ) {
642                ERRORLOG( "Error reading drumkit: name node not found" );
643                return NULL;
644        }
645
646        QString author = readXmlString( drumkitNode, "author", "undefined author", true );
647        QString info = readXmlString( drumkitNode, "info", "defaultInfo", true );
648        QString license = readXmlString( drumkitNode, "license", "undefined license", true );
649
650        Drumkit *drumkitInfo = new Drumkit();
651        drumkitInfo->setName( sDrumkitName );
652        drumkitInfo->setAuthor( author );
653        drumkitInfo->setInfo( info );
654        drumkitInfo->setLicense( license );
655
656        InstrumentList *instrumentList = new InstrumentList();
657
658        TiXmlNode* instrumentListNode;
659        if ( ( instrumentListNode = drumkitNode->FirstChild( "instrumentList" ) ) ) {
660                // INSTRUMENT NODE
661                int instrumentList_count = 0;
662                TiXmlNode* instrumentNode = 0;
663                for ( instrumentNode = instrumentListNode->FirstChild( "instrument" ); instrumentNode; instrumentNode = instrumentNode->NextSibling( "instrument" ) ) {
664                        instrumentList_count++;
665                        if ( instrumentList_count > MAX_INSTRUMENTS ) {
666                                ERRORLOG( "Instrument count >= MAX_INSTRUMENTS. Drumkit: " + drumkitInfo->getName() );
667                                break;
668                        }
669
670                        QString id = readXmlString( instrumentNode, "id", "" );
671                        QString name = readXmlString( instrumentNode, "name", "" );
672                        float volume = readXmlFloat( instrumentNode, "volume", 1.0f );
673                        bool isMuted = readXmlBool( instrumentNode, "isMuted", false );
674                        float pan_L = readXmlFloat( instrumentNode, "pan_L", 1.0f );
675                        float pan_R = readXmlFloat( instrumentNode, "pan_R", 1.0f );
676                        bool bFilterActive = readXmlBool( instrumentNode, "filterActive", false, false );
677                        float fFilterCutoff = readXmlFloat( instrumentNode, "filterCutoff", 1.0f, false, false );
678                        float fFilterResonance = readXmlFloat( instrumentNode, "filterResonance", 0.0f, false, false );
679                        float fRandomPitchFactor = readXmlFloat( instrumentNode, "randomPitchFactor", 0.0f, false, false );
680                        float fAttack = LocalFileMng::readXmlFloat( instrumentNode, "Attack", 0, false, false );                // Attack
681                        float fDecay = LocalFileMng::readXmlFloat( instrumentNode, "Decay", 0, false, false  );         // Decay
682                        float fSustain = LocalFileMng::readXmlFloat( instrumentNode, "Sustain", 1.0, false, false );    // Sustain
683                        float fRelease = LocalFileMng::readXmlFloat( instrumentNode, "Release", 1000, false, false );   // Release
684                        float fGain = readXmlFloat( instrumentNode, "gain", 1.0f, false, false );
685                        QString sMuteGroup = readXmlString( instrumentNode, "muteGroup", "-1", false, false );
686                        int nMuteGroup = sMuteGroup.toInt();
687
688                        // some sanity checks
689                        if ( id == "" ) {
690                                ERRORLOG( "Empty ID for instrument. The drumkit '" + sDrumkitName + "' is corrupted. Skipping instrument '" + name + "'" );
691                                continue;
692                        }
693
694                        Instrument *pInstrument = new Instrument( id, name, new ADSR() );
695                        pInstrument->set_volume( volume );
696
697
698                        // back compatibility code
699                        TiXmlNode* filenameNode = instrumentNode->FirstChild( "filename" );
700                        if ( filenameNode ) {
701                                //warningLog( "Using back compatibility code. filename node found" );
702                                QString sFilename = LocalFileMng::readXmlString( instrumentNode, "filename", "" );
703                                Sample *pSample = new Sample( 0, sFilename );
704                                InstrumentLayer *pLayer = new InstrumentLayer( pSample );
705                                pInstrument->set_layer( pLayer, 0 );
706                        }
707                        //~ back compatibility code
708                        else {
709                                unsigned nLayer = 0;
710                                for ( TiXmlNode* layerNode = instrumentNode->FirstChild( "layer" ); layerNode; layerNode = layerNode->NextSibling( "layer" ) ) {
711                                        if ( nLayer >= MAX_LAYERS ) {
712                                                ERRORLOG( "nLayer > MAX_LAYERS" );
713                                                continue;
714                                        }
715                                        QString sFilename = LocalFileMng::readXmlString( layerNode, "filename", "" );
716                                        float fMin = LocalFileMng::readXmlFloat( layerNode, "min", 0.0 );
717                                        float fMax = LocalFileMng::readXmlFloat( layerNode, "max", 1.0 );
718                                        float fGain = LocalFileMng::readXmlFloat( layerNode, "gain", 1.0, false, false );
719                                        float fPitch = LocalFileMng::readXmlFloat( layerNode, "pitch", 0.0, false, false );
720
721                                        Sample *pSample = new Sample( 0, sFilename );
722                                        InstrumentLayer *pLayer = new InstrumentLayer( pSample );
723                                        pLayer->set_start_velocity( fMin );
724                                        pLayer->set_end_velocity( fMax );
725                                        pLayer->set_gain( fGain );
726                                        pLayer->set_pitch( fPitch );
727                                        pInstrument->set_layer( pLayer, nLayer );
728
729                                        nLayer++;
730                                }
731                        }
732
733                        pInstrument->set_filter_active( bFilterActive );
734                        pInstrument->set_filter_cutoff( fFilterCutoff );
735                        pInstrument->set_filter_resonance( fFilterResonance );
736                        pInstrument->set_muted( isMuted );
737                        pInstrument->set_pan_l( pan_L );
738                        pInstrument->set_pan_r( pan_R );
739                        pInstrument->set_random_pitch_factor( fRandomPitchFactor );
740                        pInstrument->set_drumkit_name( drumkitInfo->getName() );
741                        pInstrument->set_gain( fGain );
742                        pInstrument->set_mute_group( nMuteGroup );
743
744                        pInstrument->set_adsr( new ADSR( fAttack, fDecay, fSustain, fRelease ) );
745                        instrumentList->add( pInstrument );
746                }
747        } else {
748                WARNINGLOG( "Error reading drumkit: instrumentList node not found" );
749        }
750        drumkitInfo->setInstrumentList( instrumentList );
751
752        return drumkitInfo;
753}
754
755
756
757int LocalFileMng::saveDrumkit( Drumkit *info )
758{
759        INFOLOG( "[saveDrumkit]" );
760        info->dump();   // debug
761
762        QString sDrumkitDir = Preferences::getInstance()->getDataDirectory() + "drumkits/" + info->getName();
763
764        // check if the directory exists
765        QDir dir( sDrumkitDir );
766        if ( !dir.exists() ) {
767                dir.mkdir( sDrumkitDir );// create the drumkit directory
768                //mkdir( sDrumkitDir.c_str(), S_IRWXU );
769        } else {
770               
771                //warningLog( "[saveDrumkit] Cleaning directory " + sDrumkitDir );
772                // clear all the old files in the directory
773                //string clearCmd = "rm -f " + sDrumkitDir + "/*";
774                //system( clearCmd.c_str() );
775        }
776
777
778        // create the drumkit.xml file
779        QString sDrumkitXmlFilename = sDrumkitDir + QString( "/drumkit.xml" );
780
781        TiXmlDocument doc( sDrumkitXmlFilename.toAscii() );
782
783        TiXmlElement rootNode( "drumkit_info" );
784
785        writeXmlString( &rootNode, "name", info->getName() );   // name
786        writeXmlString( &rootNode, "author", info->getAuthor() );       // author
787        writeXmlString( &rootNode, "info", info->getInfo() );   // info
788        writeXmlString( &rootNode, "license", info->getLicense() );     // license
789
790        TiXmlElement instrumentListNode( "instrumentList" );            // instrument list
791        unsigned nInstrument = info->getInstrumentList()->get_size();
792        // INSTRUMENT NODE
793        for ( unsigned i = 0; i < nInstrument; i++ ) {
794                Instrument *instr = info->getInstrumentList()->get( i );
795
796                for ( unsigned nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
797                        InstrumentLayer *pLayer = instr->get_layer( nLayer );
798                        if ( pLayer ) {
799                                Sample *pSample = pLayer->get_sample();
800                                QString sOrigFilename = pSample->get_filename();
801
802                                QString sDestFilename = sOrigFilename;
803
804                                int nPos = sDestFilename.lastIndexOf( '/' );
805                                sDestFilename = sDestFilename.mid( nPos + 1, sDestFilename.size() - nPos - 1 );
806                                sDestFilename = sDrumkitDir + "/" + sDestFilename;
807
808                                fileCopy( sOrigFilename, sDestFilename );
809                        }
810                }
811
812                TiXmlElement instrumentNode( "instrument" );
813
814                LocalFileMng::writeXmlString( &instrumentNode, "id", instr->get_id() );
815                LocalFileMng::writeXmlString( &instrumentNode, "name", instr->get_name() );
816                LocalFileMng::writeXmlString( &instrumentNode, "volume", to_string( instr->get_volume() ) );
817                LocalFileMng::writeXmlBool( &instrumentNode, "isMuted", instr->is_muted() );
818                LocalFileMng::writeXmlString( &instrumentNode, "pan_L", to_string( instr->get_pan_l() ) );
819                LocalFileMng::writeXmlString( &instrumentNode, "pan_R", to_string( instr->get_pan_r() ) );
820                LocalFileMng::writeXmlString( &instrumentNode, "randomPitchFactor", to_string( instr->get_random_pitch_factor() ) );
821                LocalFileMng::writeXmlString( &instrumentNode, "gain", to_string( instr->get_gain() ) );
822
823                LocalFileMng::writeXmlBool( &instrumentNode, "filterActive", instr->is_filter_active() );
824                LocalFileMng::writeXmlString( &instrumentNode, "filterCutoff", to_string( instr->get_filter_cutoff() ) );
825                LocalFileMng::writeXmlString( &instrumentNode, "filterResonance", to_string( instr->get_filter_resonance() ) );
826
827                LocalFileMng::writeXmlString( &instrumentNode, "Attack", to_string( instr->get_adsr()->__attack ) );
828                LocalFileMng::writeXmlString( &instrumentNode, "Decay", to_string( instr->get_adsr()->__decay ) );
829                LocalFileMng::writeXmlString( &instrumentNode, "Sustain", to_string( instr->get_adsr()->__sustain ) );
830                LocalFileMng::writeXmlString( &instrumentNode, "Release", to_string( instr->get_adsr()->__release ) );
831
832                LocalFileMng::writeXmlString( &instrumentNode, "muteGroup", to_string( instr->get_mute_group() ) );
833
834                for ( unsigned nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
835                        InstrumentLayer *pLayer = instr->get_layer( nLayer );
836                        if ( pLayer == NULL ) continue;
837                        Sample *pSample = pLayer->get_sample();
838
839                        QString sFilename = pSample->get_filename();
840
841                        //if (instr->getDrumkitName() != "") {
842                        // se e' specificato un drumkit, considero solo il nome del file senza il path
843                        int nPos = sFilename.lastIndexOf( "/" );
844                        sFilename = sFilename.mid( nPos + 1, sFilename.length() );
845                        //}
846
847                        TiXmlElement layerNode( "layer" );
848                        LocalFileMng::writeXmlString( &layerNode, "filename", sFilename );
849                        LocalFileMng::writeXmlString( &layerNode, "min", to_string( pLayer->get_start_velocity() ) );
850                        LocalFileMng::writeXmlString( &layerNode, "max", to_string( pLayer->get_end_velocity() ) );
851                        LocalFileMng::writeXmlString( &layerNode, "gain", to_string( pLayer->get_gain() ) );
852                        LocalFileMng::writeXmlString( &layerNode, "pitch", to_string( pLayer->get_pitch() ) );
853
854                        instrumentNode.InsertEndChild( layerNode );
855                }
856
857                instrumentListNode.InsertEndChild( instrumentNode );
858        }
859
860        rootNode.InsertEndChild( instrumentListNode );
861
862        doc.InsertEndChild( rootNode );
863        doc.SaveFile();
864
865        return 0; // ok
866}
867
868int LocalFileMng::savePlayList( const std::string& patternname)
869{
870        TiXmlDocument doc = patternname.c_str();
871        std::string name = patternname.c_str();
872
873        std::string realname = name.substr(name.rfind("/")+1);
874
875       
876        TiXmlElement rootNode( "playlist" );
877        //LIB_ID just in work to get better usability
878        writeXmlString( &rootNode, "Name", QString (realname.c_str()) );
879        writeXmlString( &rootNode, "LIB_ID", "in_work" );
880               
881        TiXmlElement playlistNode( "Songs" );
882                        for ( uint i = 0; i < Hydrogen::get_instance()->m_PlayList.size(); ++i ){
883                        TiXmlElement nextNode( "next" );
884                        LocalFileMng::writeXmlString ( &nextNode, "song", Hydrogen::get_instance()->m_PlayList[i].m_hFile );
885                        LocalFileMng::writeXmlString ( &nextNode, "script", Hydrogen::get_instance()->m_PlayList[i].m_hScript );
886                        LocalFileMng::writeXmlString ( &nextNode, "enabled", Hydrogen::get_instance()->m_PlayList[i].m_hScriptEnabled );
887                        playlistNode.InsertEndChild( nextNode );
888        }
889
890        rootNode.InsertEndChild( playlistNode );
891        doc.InsertEndChild( rootNode );
892        doc.SaveFile();
893        return 0; // ok
894
895}
896
897int LocalFileMng::loadPlayList( const std::string& patternname)
898{
899
900       
901        std::string playlistInfoFile = patternname;
902        std::ifstream verify( playlistInfoFile.c_str() , std::ios::in | std::ios::binary );
903        if ( verify == NULL ) {
904                //ERRORLOG( "Load Playlist: Data file " + playlistInfoFile + " not found." );
905                return NULL;
906        }
907
908        TiXmlDocument doc( playlistInfoFile.c_str() );
909        doc.LoadFile();
910
911        Hydrogen::get_instance()->m_PlayList.clear();
912
913        TiXmlNode* rootNode;    // root element
914                if ( !( rootNode = doc.FirstChild( "playlist" ) ) ) {
915                ERRORLOG( "Error reading playlist: playlist node not found" );
916                return NULL;
917        }
918       
919        TiXmlNode* playlistNode = rootNode->FirstChild( "Songs" );
920
921        if ( playlistNode ) {
922                // new code :)
923                Hydrogen::get_instance()->m_PlayList.clear();
924                for ( TiXmlNode* nextNode = playlistNode->FirstChild( "next" ); nextNode; nextNode = nextNode->NextSibling( "next" ) ) {
925                        std::string song =  LocalFileMng::readXmlString( nextNode, "song", "" ).toStdString();
926                        std::string script = LocalFileMng::readXmlString( nextNode, "script", "" ).toStdString();
927                        std::string ScriptEnabled = LocalFileMng::readXmlString( nextNode, "enabled", "" ).toStdString();
928
929                        Hydrogen::HPlayListNode playListItem;
930                        playListItem.m_hFile = song.c_str();
931                        playListItem.m_hScript = script.c_str();
932                        playListItem.m_hScriptEnabled = ScriptEnabled.c_str();
933                        Hydrogen::get_instance()->m_PlayList.push_back( playListItem );
934                }
935        }
936        return 0; // ok
937}
938
939
940
941QString LocalFileMng::readXmlString( TiXmlNode* parent, const QString& nodeName, const QString& defaultValue, bool bCanBeEmpty, bool bShouldExists )
942{
943        TiXmlNode* node;
944        if ( parent && ( node = parent->FirstChild( nodeName.toAscii() ) ) ) {
945                if ( node->FirstChild() ) {
946                        return node->FirstChild()->Value();
947                } else {
948                        if ( !bCanBeEmpty ) {
949                                _WARNINGLOG( "Using default value in " + nodeName );
950                        }
951                        return defaultValue;
952                }
953        } else {
954                if ( bShouldExists ) {
955                        _WARNINGLOG( "'" + nodeName + "' node not found" );
956                }
957                return defaultValue;
958        }
959}
960
961
962
963float LocalFileMng::readXmlFloat( TiXmlNode* parent, const QString& nodeName, float defaultValue, bool bCanBeEmpty, bool bShouldExists )
964{
965        TiXmlNode* node;
966        if ( parent && ( node = parent->FirstChild( nodeName.toAscii() ) ) ) {
967                if ( node->FirstChild() ) {
968                        float res = string_to_float( node->FirstChild()->Value() );
969                        return res;
970                } else {
971                        if ( !bCanBeEmpty ) {
972                                _WARNINGLOG( "Using default value in " + nodeName );
973                        }
974                        return defaultValue;
975                }
976        } else {
977                if ( bShouldExists ) {
978                        _WARNINGLOG( "'" + nodeName + "' node not found" );
979                }
980                return defaultValue;
981        }
982}
983
984
985
986int LocalFileMng::readXmlInt( TiXmlNode* parent, const QString& nodeName, int defaultValue, bool bCanBeEmpty, bool bShouldExists )
987{
988        TiXmlNode* node;
989        if ( parent && ( node = parent->FirstChild( nodeName.toAscii() ) ) ) {
990                if ( node->FirstChild() ) {
991                        return atoi( node->FirstChild()->Value() );
992                } else {
993                        if ( !bCanBeEmpty ) {
994                                _WARNINGLOG( "Using default value in " + nodeName );
995                        }
996                        return defaultValue;
997                }
998        } else {
999                if ( bShouldExists )  {
1000                        _WARNINGLOG( "'" + nodeName + "' node not found" );
1001                }
1002                return defaultValue;
1003        }
1004}
1005
1006
1007
1008bool LocalFileMng::readXmlBool( TiXmlNode* parent, const QString& nodeName, bool defaultValue, bool bShouldExists )
1009{
1010        TiXmlNode* node;
1011        if ( parent && ( node = parent->FirstChild( nodeName.toAscii() ) ) ) {
1012                if ( node->FirstChild() ) {
1013                        if ( QString( node->FirstChild()->Value() ) == "true" ) {
1014                                return true;
1015                        } else {
1016                                return false;
1017                        }
1018                } else {
1019                        _WARNINGLOG( "Using default value in " + nodeName );
1020                        return defaultValue;
1021                }
1022        } else {
1023                if ( bShouldExists ) {
1024                        _WARNINGLOG( "'" + nodeName + "' node not found" );
1025                }
1026                return defaultValue;
1027        }
1028}
1029
1030
1031
1032void LocalFileMng::writeXmlString( TiXmlNode *parent, const QString& name, const QString& text )
1033{
1034        TiXmlElement versionNode( name.toAscii() );
1035        TiXmlText versionText( text.toAscii() );
1036        versionNode.InsertEndChild( versionText );
1037        parent->InsertEndChild( versionNode );
1038}
1039
1040
1041
1042void LocalFileMng::writeXmlBool( TiXmlNode *parent, const QString& name, bool value )
1043{
1044        if ( value ) {
1045                writeXmlString( parent, name, QString( "true" ) );
1046        } else {
1047                writeXmlString( parent, name, QString( "false" ) );
1048        }
1049}
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062//-----------------------------------------------------------------------------
1063//      Implementation of SongWriter class
1064//-----------------------------------------------------------------------------
1065
1066
1067SongWriter::SongWriter()
1068                : Object( "SongWriter" )
1069{
1070//      infoLog("init");
1071}
1072
1073
1074
1075SongWriter::~SongWriter()
1076{
1077//      infoLog("destroy");
1078}
1079
1080
1081// Returns 0 on success, passes the TinyXml error code otherwise.
1082int SongWriter::writeSong( Song *song, const QString& filename )
1083{
1084        INFOLOG( "Saving song " + filename );
1085        int rv = 0; // return value
1086
1087        // FIXME: has the file write-permssion?
1088        // FIXME: verificare che il file non sia gia' esistente
1089        // FIXME: effettuare copia di backup per il file gia' esistente
1090
1091        TiXmlDocument doc( filename.toAscii() );
1092
1093        TiXmlElement songNode( "song" );
1094
1095        LocalFileMng::writeXmlString( &songNode, "version", QString( get_version().c_str() ) );
1096        LocalFileMng::writeXmlString( &songNode, "bpm", to_string( song->__bpm ) );
1097        LocalFileMng::writeXmlString( &songNode, "volume", to_string( song->get_volume() ) );
1098        LocalFileMng::writeXmlString( &songNode, "metronomeVolume", to_string( song->get_metronome_volume() ) );
1099        LocalFileMng::writeXmlString( &songNode, "name", song->__name );
1100        LocalFileMng::writeXmlString( &songNode, "author", song->__author );
1101        LocalFileMng::writeXmlString( &songNode, "notes", song->get_notes() );
1102        LocalFileMng::writeXmlString( &songNode, "license", song->get_license() );
1103        LocalFileMng::writeXmlBool( &songNode, "loopEnabled", song->is_loop_enabled() );
1104
1105        if ( song->get_mode() == Song::SONG_MODE ) {
1106                LocalFileMng::writeXmlString( &songNode, "mode", QString( "song" ) );
1107        } else {
1108                LocalFileMng::writeXmlString( &songNode, "mode", QString( "pattern" ) );
1109        }
1110
1111        LocalFileMng::writeXmlString( &songNode, "humanize_time", to_string( song->get_humanize_time_value() ) );
1112        LocalFileMng::writeXmlString( &songNode, "humanize_velocity", to_string( song->get_humanize_velocity_value() ) );
1113        LocalFileMng::writeXmlString( &songNode, "swing_factor", to_string( song->get_swing_factor() ) );
1114
1115        /*      LocalFileMng::writeXmlBool( &songNode, "delayFXEnabled", song->m_bDelayFXEnabled );
1116                LocalFileMng::writeXmlString( &songNode, "delayFXWetLevel", to_string( song->m_fDelayFXWetLevel ) );
1117                LocalFileMng::writeXmlString( &songNode, "delayFXFeedback", to_string( song->m_fDelayFXFeedback ) );
1118                LocalFileMng::writeXmlString( &songNode, "delayFXTime", to_string( song->m_nDelayFXTime ) );
1119        */
1120
1121        // instrument list
1122        TiXmlElement instrumentListNode( "instrumentList" );
1123        unsigned nInstrument = song->get_instrument_list()->get_size();
1124
1125        // INSTRUMENT NODE
1126        for ( unsigned i = 0; i < nInstrument; i++ ) {
1127                Instrument *instr = song->get_instrument_list()->get( i );
1128                assert( instr );
1129
1130                TiXmlElement instrumentNode( "instrument" );
1131
1132                LocalFileMng::writeXmlString( &instrumentNode, "id", instr->get_id() );
1133                LocalFileMng::writeXmlString( &instrumentNode, "drumkit", instr->get_drumkit_name() );
1134                LocalFileMng::writeXmlString( &instrumentNode, "name", instr->get_name() );
1135                LocalFileMng::writeXmlString( &instrumentNode, "volume", to_string( instr->get_volume() ) );
1136                LocalFileMng::writeXmlBool( &instrumentNode, "isMuted", instr->is_muted() );
1137                LocalFileMng::writeXmlString( &instrumentNode, "pan_L", to_string( instr->get_pan_l() ) );
1138                LocalFileMng::writeXmlString( &instrumentNode, "pan_R", to_string( instr->get_pan_r() ) );
1139                LocalFileMng::writeXmlString( &instrumentNode, "gain", to_string( instr->get_gain() ) );
1140
1141                LocalFileMng::writeXmlBool( &instrumentNode, "filterActive", instr->is_filter_active() );
1142                LocalFileMng::writeXmlString( &instrumentNode, "filterCutoff", to_string( instr->get_filter_cutoff() ) );
1143                LocalFileMng::writeXmlString( &instrumentNode, "filterResonance", to_string( instr->get_filter_resonance() ) );
1144
1145                LocalFileMng::writeXmlString( &instrumentNode, "FX1Level", to_string( instr->get_fx_level( 0 ) ) );
1146                LocalFileMng::writeXmlString( &instrumentNode, "FX2Level", to_string( instr->get_fx_level( 1 ) ) );
1147                LocalFileMng::writeXmlString( &instrumentNode, "FX3Level", to_string( instr->get_fx_level( 2 ) ) );
1148                LocalFileMng::writeXmlString( &instrumentNode, "FX4Level", to_string( instr->get_fx_level( 3 ) ) );
1149
1150                assert( instr->get_adsr() );
1151                LocalFileMng::writeXmlString( &instrumentNode, "Attack", to_string( instr->get_adsr()->__attack ) );
1152                LocalFileMng::writeXmlString( &instrumentNode, "Decay", to_string( instr->get_adsr()->__decay ) );
1153                LocalFileMng::writeXmlString( &instrumentNode, "Sustain", to_string( instr->get_adsr()->__sustain ) );
1154                LocalFileMng::writeXmlString( &instrumentNode, "Release", to_string( instr->get_adsr()->__release ) );
1155
1156                LocalFileMng::writeXmlString( &instrumentNode, "randomPitchFactor", to_string( instr->get_random_pitch_factor() ) );
1157
1158                LocalFileMng::writeXmlString( &instrumentNode, "muteGroup", to_string( instr->get_mute_group() ) );
1159
1160                for ( unsigned nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
1161                        InstrumentLayer *pLayer = instr->get_layer( nLayer );
1162                        if ( pLayer == NULL ) continue;
1163                        Sample *pSample = pLayer->get_sample();
1164                        if ( pSample == NULL ) continue;
1165
1166                        QString sFilename = pSample->get_filename();
1167
1168                        if ( instr->get_drumkit_name() != "" ) {
1169                                // se e' specificato un drumkit, considero solo il nome del file senza il path
1170                                int nPos = sFilename.lastIndexOf( "/" );
1171                                sFilename = sFilename.mid( nPos + 1, sFilename.length() );
1172                        }
1173
1174                        TiXmlElement layerNode( "layer" );
1175                        LocalFileMng::writeXmlString( &layerNode, "filename", sFilename );
1176                        LocalFileMng::writeXmlString( &layerNode, "min", to_string( pLayer->get_start_velocity() ) );
1177                        LocalFileMng::writeXmlString( &layerNode, "max", to_string( pLayer->get_end_velocity() ) );
1178                        LocalFileMng::writeXmlString( &layerNode, "gain", to_string( pLayer->get_gain() ) );
1179                        LocalFileMng::writeXmlString( &layerNode, "pitch", to_string( pLayer->get_pitch() ) );
1180
1181                        instrumentNode.InsertEndChild( layerNode );
1182                }
1183
1184                instrumentListNode.InsertEndChild( instrumentNode );
1185        }
1186        songNode.InsertEndChild( instrumentListNode );
1187
1188
1189        // pattern list
1190        TiXmlElement patternListNode( "patternList" );
1191
1192        unsigned nPatterns = song->get_pattern_list()->get_size();
1193        for ( unsigned i = 0; i < nPatterns; i++ ) {
1194                Pattern *pat = song->get_pattern_list()->get( i );
1195
1196                // pattern
1197                TiXmlElement patternNode( "pattern" );
1198                LocalFileMng::writeXmlString( &patternNode, "name", pat->get_name() );
1199                LocalFileMng::writeXmlString( &patternNode, "category", pat->get_category() );
1200                LocalFileMng::writeXmlString( &patternNode, "size", to_string( pat->get_lenght() ) );
1201
1202                TiXmlElement noteListNode( "noteList" );
1203                std::multimap <int, Note*>::iterator pos;
1204                for ( pos = pat->note_map.begin(); pos != pat->note_map.end(); ++pos ) {
1205                        Note *pNote = pos->second;
1206                        assert( pNote );
1207
1208                        TiXmlElement noteNode( "note" );
1209                        LocalFileMng::writeXmlString( &noteNode, "position", to_string( pNote->get_position() ) );
1210                        LocalFileMng::writeXmlString( &noteNode, "leadlag", to_string( pNote->get_leadlag() ) );
1211                        LocalFileMng::writeXmlString( &noteNode, "velocity", to_string( pNote->get_velocity() ) );
1212                        LocalFileMng::writeXmlString( &noteNode, "pan_L", to_string( pNote->get_pan_l() ) );
1213                        LocalFileMng::writeXmlString( &noteNode, "pan_R", to_string( pNote->get_pan_r() ) );
1214                        LocalFileMng::writeXmlString( &noteNode, "pitch", to_string( pNote->get_pitch() ) );
1215
1216                        LocalFileMng::writeXmlString( &noteNode, "key", Note::keyToString( pNote->m_noteKey ) );
1217
1218                        LocalFileMng::writeXmlString( &noteNode, "length", to_string( pNote->get_lenght() ) );
1219                        LocalFileMng::writeXmlString( &noteNode, "instrument", pNote->get_instrument()->get_id() );
1220                        noteListNode.InsertEndChild( noteNode );
1221                }
1222                patternNode.InsertEndChild( noteListNode );
1223
1224                patternListNode.InsertEndChild( patternNode );
1225        }
1226        songNode.InsertEndChild( patternListNode );
1227
1228
1229        // pattern sequence
1230        TiXmlElement patternSequenceNode( "patternSequence" );
1231
1232        unsigned nPatternGroups = song->get_pattern_group_vector()->size();
1233        for ( unsigned i = 0; i < nPatternGroups; i++ ) {
1234                TiXmlElement groupNode( "group" );
1235
1236                PatternList *pList = ( *song->get_pattern_group_vector() )[i];
1237                for ( unsigned j = 0; j < pList->get_size(); j++ ) {
1238                        Pattern *pPattern = pList->get( j );
1239                        LocalFileMng::writeXmlString( &groupNode, "patternID", pPattern->get_name() );
1240                }
1241                patternSequenceNode.InsertEndChild( groupNode );
1242        }
1243
1244        songNode.InsertEndChild( patternSequenceNode );
1245
1246
1247        // LADSPA FX
1248        TiXmlElement ladspaFxNode( "ladspa" );
1249
1250        for ( unsigned nFX = 0; nFX < MAX_FX; nFX++ ) {
1251                TiXmlElement fxNode( "fx" );
1252
1253#ifdef LADSPA_SUPPORT
1254                LadspaFX *pFX = Effects::getInstance()->getLadspaFX( nFX );
1255                if ( pFX ) {
1256                        LocalFileMng::writeXmlString( &fxNode, "name", pFX->getPluginLabel() );
1257                        LocalFileMng::writeXmlString( &fxNode, "filename", pFX->getLibraryPath() );
1258                        LocalFileMng::writeXmlBool( &fxNode, "enabled", pFX->isEnabled() );
1259                        LocalFileMng::writeXmlString( &fxNode, "volume", to_string( pFX->getVolume() ) );
1260                        for ( unsigned nControl = 0; nControl < pFX->inputControlPorts.size(); nControl++ ) {
1261                                LadspaControlPort *pControlPort = pFX->inputControlPorts[ nControl ];
1262                                TiXmlElement controlPortNode( "inputControlPort" );
1263                                LocalFileMng::writeXmlString( &controlPortNode, "name", pControlPort->sName );
1264                                LocalFileMng::writeXmlString( &controlPortNode, "value", to_string( pControlPort->fControlValue ) );
1265                                fxNode.InsertEndChild( controlPortNode );
1266                        }
1267                        for ( unsigned nControl = 0; nControl < pFX->outputControlPorts.size(); nControl++ ) {
1268                                LadspaControlPort *pControlPort = pFX->inputControlPorts[ nControl ];
1269                                TiXmlElement controlPortNode( "outputControlPort" );
1270                                LocalFileMng::writeXmlString( &controlPortNode, "name", pControlPort->sName );
1271                                LocalFileMng::writeXmlString( &controlPortNode, "value", to_string( pControlPort->fControlValue ) );
1272                                fxNode.InsertEndChild( controlPortNode );
1273                        }
1274                }
1275#else
1276                if ( false ) {
1277                }
1278#endif
1279                else {
1280                        LocalFileMng::writeXmlString( &fxNode, "name", QString( "no plugin" ) );
1281                        LocalFileMng::writeXmlString( &fxNode, "filename", QString( "-" ) );
1282                        LocalFileMng::writeXmlBool( &fxNode, "enabled", false );
1283                        LocalFileMng::writeXmlString( &fxNode, "volume", to_string( 0.0 ) );
1284                }
1285                ladspaFxNode.InsertEndChild( fxNode );
1286        }
1287
1288        songNode.InsertEndChild( ladspaFxNode );
1289
1290
1291
1292
1293        doc.InsertEndChild( songNode );
1294        rv = ( doc.SaveFile() ? 0 : doc.ErrorId() );
1295
1296        if( rv ) {
1297                WARNINGLOG("File save reported an error.");
1298        } else {
1299                song->__is_modified = false;
1300                INFOLOG("Save was successful.");
1301        }
1302        song->set_filename( filename );
1303
1304        return rv;
1305}
1306
1307
1308};
1309
Note: See TracBrowser for help on using the browser.