MusicFlex.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2005  The Pentagram Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "MusicFlex.h"
00022 #include "XMidiFile.h"
00023 #include "IDataSource.h"
00024 
00025 DEFINE_RUNTIME_CLASSTYPE_CODE(MusicFlex,Pentagram::Archive);
00026 
00027 
00028 MusicFlex::MusicFlex(IDataSource* ds) : Archive(ds)
00029 {
00030         songs = 0;
00031         std::memset(info,0, sizeof(SongInfo*)*128);
00032         loadSongInfo();
00033 }
00034 
00035 MusicFlex::~MusicFlex()
00036 {
00037         uint32 i;
00038         for (i = 0; i < 128; i++)
00039         {
00040                 delete info[i];
00041                 info[i] = 0;
00042         }
00043 
00044         Archive::uncache();
00045         delete [] songs;
00046 }
00047 
00048 MusicFlex::SongInfo::SongInfo() : num_measures(0), loop_jump(0)
00049 {
00050         std::memset(filename,0,16);
00051         std::memset(transitions,0,128*sizeof(int*));
00052 }
00053 
00054 MusicFlex::SongInfo::~SongInfo()
00055 {
00056         for (int i = 0; i < 128; i++)
00057         {
00058                 delete [] transitions[i];
00059                 transitions[i] = 0;
00060         }
00061 }
00062 
00063 void MusicFlex::cache(uint32 index)
00064 {
00065         if (index >= count) return;
00066 
00067         if (!songs) 
00068         {
00069                 songs = new XMidiFile * [count];
00070                 std::memset(songs, 0, sizeof (XMidiFile *) * count);
00071         }
00072 
00073         if (songs[index]) return;
00074 
00075         // This will cache the data
00076         uint32 size;
00077         uint8 *buf = getRawObject(index, &size);
00078 
00079         if (!buf || !size) return;
00080         IBufferDataSource ds(buf,size);
00081 
00082         XMidiFile *x = new XMidiFile(&ds, XMIDIFILE_CONVERT_NOCONVERSION);
00083 
00084         if (x->number_of_tracks())
00085                 songs[index] = x;
00086         else
00087                 delete x;
00088 
00089         delete [] buf;
00090 }
00091 
00092 void MusicFlex::uncache(uint32 index)
00093 {
00094         if (index >= count) return;
00095         if (!songs) return;
00096 
00097         delete songs[index];
00098         songs[index] = 0;
00099 }
00100 
00101 bool MusicFlex::isCached(uint32 index)
00102 {
00103         if (index >= count) return false;
00104         if (!songs) return false;
00105 
00106         return (songs[index] != 0);
00107 }
00108 
00109 IDataSource* MusicFlex::getAdlibTimbres()
00110 {
00111         uint32 size;
00112         uint8* data = getRawObject(259, &size);
00113         return new IBufferDataSource(data, size, false, true);
00114 }
00115 
00116 void MusicFlex::loadSongInfo()
00117 {
00118         uint32 size;
00119         uint8 *buf = getRawObject(0, &size);
00120 
00121         if (!buf || !size)
00122         {
00123                 perr << "Unable to load song info from sound/music.flx. Exiting" << std::endl;
00124                 std::exit(-1);
00125         }
00126         IBufferDataSource ds(buf,size);
00127         std::string line;
00128 
00129         // Read first section till we hit a #
00130         for (;;)
00131         {
00132                 ds.readline(line);      
00133 
00134                 // We have hit the end of the section
00135                 if (line.at(0) == '#') break;
00136 
00137                 std::string::size_type  begIdx, endIdx;
00138 
00139                 // Find the first not space, which will get us the name
00140                 begIdx = line.find_first_not_of(' ');
00141                 endIdx = line.find_first_of(' ', begIdx);
00142                 std::string name = line.substr(begIdx,endIdx-begIdx);
00143 
00144                 // Now find the first not space after the name, which will get us the num
00145                 begIdx = line.find_first_not_of(' ', endIdx);
00146                 endIdx = line.find_first_of(' ', begIdx);
00147                 int num = line.at(begIdx);
00148 
00149                 // Now number of measures
00150                 begIdx = line.find_first_not_of(' ', endIdx);
00151                 endIdx = line.find_first_of(' ', begIdx);
00152                 int measures = std::atoi(line.substr(begIdx,endIdx-begIdx).c_str());
00153 
00154                 // Now finally loop_jump
00155                 begIdx = line.find_first_not_of(' ', endIdx);
00156                 endIdx = line.find_first_of(' ', begIdx);
00157                 int loop_jump = std::atoi(line.substr(begIdx,endIdx-begIdx).c_str());
00158 
00159                 // Uh oh
00160                 if (num < 0 || num > 127)
00161                 {
00162                         perr << "Invalid Section 1 song info data. num out of range. Exiting." << std::endl;
00163                         std::exit(-1);
00164                 }
00165 
00166                 if (info[num])
00167                 {
00168                         perr << "Invalid Section 1 song info data. num already defined. Exiting." << std::endl;
00169                         std::exit(-1);
00170                 }
00171 
00172                 info[num] = new SongInfo();
00173 
00174                 std::strncpy(info[num]->filename, name.c_str(), 16);
00175                 info[num]->num_measures = measures;
00176                 info[num]->loop_jump = loop_jump;
00177         };
00178 
00179         // Read 'Section2', or more like skip it, since it's only trans.xmi
00180         // Read first section till we hit a #
00181         for (;;)
00182         {
00183                 ds.readline(line);      
00184 
00185                 // We have hit the end of the section
00186                 if (line.at(0) == '#') break;
00187         }
00188 
00189         // Skip 'Section3'
00190         for (;;)
00191         {
00192                 ds.readline(line);      
00193 
00194                 // We have hit the end of the section
00195                 if (line.at(0) == '#') break;
00196         }
00197 
00198         // Read 'Section4' (trans info)
00199         for (;;)
00200         {
00201                 ds.readline(line);      
00202 
00203                 // We have hit the end of the section
00204                 if (line.at(0) == '#') break;
00205 
00206                 std::string::size_type  begIdx, endIdx;
00207 
00208                 // Get 'from' name
00209                 begIdx = line.find_first_not_of(' ');
00210                 endIdx = line.find_first_of(' ', begIdx);
00211                 std::string from = line.substr(begIdx,endIdx-begIdx);
00212 
00213                 // Get 'to' name
00214                 begIdx = line.find_first_not_of(' ', endIdx);
00215                 endIdx = line.find_first_of(' ', begIdx);
00216                 std::string to = line.substr(begIdx,endIdx-begIdx);
00217 
00218                 // Find index of from name
00219                 int fi;
00220                 for (fi = 0; fi < 128; fi++)
00221                 {
00222                         if (info[fi] && from == info[fi]->filename) break;
00223                 }
00224 
00225                 if (fi == 128)
00226                 {
00227                         perr << "Invalid Section 4 song info data. Unable to find 'from' index (" << from << "). Exiting." << std::endl;
00228                         std::exit(-1);
00229                 }
00230 
00231                 // Find index of to name
00232                 int ti;
00233                 for (ti= 0; ti < 128; ti++)
00234                 {
00235                         if (info[ti] && to == info[ti]->filename) break;
00236                 }
00237 
00238                 if (ti == 128)
00239                 {
00240                         perr << "Invalid Section 4 song info data. Unable to find 'to' index (" << to << "). Exiting." << std::endl;
00241                         std::exit(-1);
00242                 }
00243 
00244                 // Allocate Transition info
00245                 info[fi]->transitions[ti] = new int[info[fi]->num_measures];
00246 
00247                 // Now attempt to read the trans info for the
00248                 for (int m = 0; m < info[fi]->num_measures; m++)
00249                 {
00250                         // Get trans info name
00251                         begIdx = line.find_first_not_of(' ', endIdx);
00252                         endIdx = line.find_first_of(' ', begIdx);
00253 
00254                         if (begIdx == std::string::npos)
00255                         {
00256                                 perr << "Invalid Section 4 song info data. Unable to read transitions for all measures. Exiting." << std::endl;
00257                                 std::exit(-1);
00258                         }
00259 
00260                         std::string trans = line.substr(begIdx,endIdx-begIdx);
00261                         const char *str = trans.c_str();
00262 
00263                         int num = 0;
00264 
00265                         // Overlayed
00266                         if (*str == '!')
00267                                 num = -1-atoi(str+1);
00268                         else
00269                                 num = atoi(str+1);
00270 
00271                         info[fi]->transitions[ti][m] = num;
00272                 }
00273         }
00274 
00275         // Skip all remaining sections
00276 
00277         delete[] buf;
00278 }
00279 

Generated on Fri Jul 27 22:27:26 2007 for pentagram by  doxygen 1.4.7