|
From: Jaakko N. <jni...@us...> - 2009-11-16 21:33:39
|
Module: performous
Branch: dance
Commit: c9fbf4c02ea6f080abe030335f0845d2d43575ae
Author: Jaakko Nikkola <jaa...@tk...>
Date: Mon Nov 16 23:29:53 2009 +0200
One step and a lot of fixes forward... Some songs seem to work all right. However, some songs cause segmentation fault at the end of input.
---
game/songparser-sm.cc | 166 +++++++++++++++++++++++--------------------------
game/songparser.hh | 4 +-
game/songs.cc | 3 +-
3 files changed, 83 insertions(+), 90 deletions(-)
diff --git a/game/songparser-sm.cc b/game/songparser-sm.cc
index 960e7aa..edcba3f 100644
--- a/game/songparser-sm.cc
+++ b/game/songparser-sm.cc
@@ -11,10 +11,6 @@
namespace {
- bool isNote(const char& c) {
- return c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == 'M' || c == 'L';
- }
-
void assign(int& var, std::string const& str) {
try {
var = boost::lexical_cast<int>(str);
@@ -50,89 +46,38 @@ bool SongParser::smCheck(std::vector<char> const& data) {
void SongParser::smParse() {
Song& s = m_song;
std::string line;
- int lcount = 0; //line counter for note duration
- int count = 0; //total lines counter
- bool readable = false; //makes sure that other values are read before notes
- double tm = 0; //time counter
- double dur; //note duration
- std::string notestype;
- std::string description;
- DanceDifficulty danceDifficulty = DIFFICULTYCOUNT;
- DanceDifficultyMap danceDifficultyMap;
- DanceChords chords;
-
- while (getline(line)) {
-
- if (line.empty() || line == "\r") continue;
- if (line[0] == '/' && line[1] == '/') continue; //jump over possible comments
- //reading of the values
- if (readable && isNote(line[0]) ) {
- //reading notes into a chord
- std::istringstream iss(line);
- DanceChord chord;
- for(int i =1; i <= 4; i++){
- if(iss.get() == '1') {
- Note note;
- chord[i] = note;
- }
- //if (iss.get() == ';') return false; //for the case where end mark ';' is not on its own line
- //TODO hold etc. notes
- chords.push_back(chord);
- lcount++;
- count++;
- }
- continue;
- }
- if (!readable && isNote(line[0]) ) throw std::runtime_error("Notes outside NoteData");
- if (line[0] == ',') {
- /*Counting the timestamp of each note*/
- dur = 4.0 * ( 1.0/(m_bpm/60.0) ) / lcount; //counts one note duration in seconds;
- //std::cout << "DUR: " << dur << "TM: " << tm << std::endl;
- for(int j = count - lcount; j<count ; j++) {
- for(int i = 0; i<4; i++) {
- DanceChord& _chord = chords.at(j);
- if(_chord.find(i) != _chord.end()) {
- _chord[i].begin = tm;
- _chord[i].end = tm;
- }
- }
- tm += dur;
- }
- lcount =0;
- continue;
- }
- if (line[0] == ';') continue;
-
+ while (getline(line) && smParseField(line)) {}
+ if (m_song.danceTracks.empty() ) throw std::runtime_error("No note data in the file");
+ if (s.title.empty() || s.artist.empty()) throw std::runtime_error("Required header fields missing");
+ if (m_bpm != 0.0) addBPM(0, m_bpm);
+}
+bool SongParser::smParseField(std::string line) {
+ if (line.empty() || line == "\r") return true;
+ if (line[0] == '/' && line[1] == '/') return true; //jump over possible comments
+ if (line[0] == ';') return true;
+ std::cout << line << std::endl;
std::string::size_type pos = line.find(':');
if (pos == std::string::npos) throw std::runtime_error("Invalid format, should be #key:value");
std::string key = boost::trim_copy(line.substr(1, pos - 1));
- if (key == "NOTES") {
- //if not the first time
- if(readable) {
- DanceTrack danceTrack(description, chords);
- danceDifficultyMap.insert(std::make_pair(danceDifficulty, danceTrack));
- m_song.danceTracks.insert(std::make_pair(notestype, danceDifficultyMap));
- }
- //temporary containers for note data
- /*DanceDifficultyMap danceDifficultyMap;
- DanceChords chords;*/
+ if (key == "NOTES") {
//Note values are analyzed here. Values are:
-
+ bool endOfInput = false;
// TODO: NOTES header vars needs better way to strip trailing colon ':'
-
+ while (getline(line)) {
+ std::cout << line << std::endl;
//<NotesType>:
- if(!getline(line)) { throw std::runtime_error("Required note data missing"); }
- notestype = boost::trim_copy(line.substr(0, line.size() -2));
+ //if(!getline(line)) { throw std::runtime_error("Required note data missing"); }
+ std::string notestype = boost::trim_copy(line.substr(0, line.size() -2));
//<Description>:
if(!getline(line)) { throw std::runtime_error("Required note data missing"); }
- description = boost::trim_copy(line.substr(0, line.size() -2));
+ std::string description = boost::trim_copy(line.substr(0, line.size() -2));
//<DifficultyClass>:
if(!getline(line)) { throw std::runtime_error("Required note data missing"); }
std::string difficultyclass = boost::trim_copy(line.substr(0, line.size() -2));
- //enum
- transform(difficultyclass.begin(), difficultyclass.end(),
- difficultyclass.begin(), upper_case );
+ transform(difficultyclass.begin(), difficultyclass.end(),
+ difficultyclass.begin(), upper_case );
+ DanceDifficulty danceDifficulty = DIFFICULTYCOUNT;
if(difficultyclass == "BEGINNER") danceDifficulty = BEGINNER;
if(difficultyclass == "EASY") danceDifficulty = EASY;
if(difficultyclass == "MEDIUM") danceDifficulty = MEDIUM;
@@ -148,18 +93,20 @@ void SongParser::smParse() {
//std::string radarvalues = boost::trim_copy(line.substr(0, line.size() -2));
//<NoteData>:
- /*while (getline(line) && smParseNotes(line, chords)) {}
+ DanceChords chords = smParseNotes(line, endOfInput);
+ if(endOfInput) throw std::runtime_error("end is here");
+
DanceTrack danceTrack(description, chords);
+ DanceDifficultyMap danceDifficultyMap;
danceDifficultyMap.insert(std::make_pair(danceDifficulty, danceTrack));
- m_song.danceTracks.insert(std::make_pair(notestype, danceDifficultyMap));*/
-
- readable = true;
- continue;
+ m_song.danceTracks.insert(std::make_pair(notestype, danceDifficultyMap));
+ }
+ return false;
}
std::string value = boost::trim_copy(line.substr(pos + 1));
- value.erase(value.size() -1); // compared to txtParseField, here last character(';') is eliminated
- if (value.empty()) continue;
+ value = value.substr(0, value.size() - 1); // compared to txtParseField, here last character(';') is eliminated
+ if (value.empty()) return true;
if (key == "TITLE") m_song.title = value.substr(value.find_first_not_of(" :"));
else if (key == "ARTIST") m_song.artist = value.substr(value.find_first_not_of(" "));
else if (key == "BANNER") m_song.cover = value;
@@ -188,10 +135,53 @@ void SongParser::smParse() {
#STOPS
#BGCHANGE
*/
- continue;
+ return true;
+}
+
+DanceChords SongParser::smParseNotes(std::string line, bool endOfInput) {
+ DanceChords chords;
+ int lcount = 0; //line counter for note duration
+ int count = 0; //total lines counter
+ double tm = 0; //time counter
+ double dur; //note duration
+
+ while(getline(line)) {
+// std::cout << line << std::endl;
+ if (line.empty() || line == "\r") continue;
+ if (line[0] == '/' && line[1] == '/') continue;
+ if (line[0] == '#') return chords;
+ if (line[0] == ';') continue;
+ if (line[0] == ',') {
+ /*Counting the timestamp of each note*/
+ dur = 4.0 * ( 1.0/(m_bpm/60.0) ) / lcount; //counts one note duration in seconds;
+ //std::cout << "DUR: " << dur << "TM: " << tm << std::endl;
+ for(int j = count - lcount; j<count ; j++) {
+ for(int i = 0; i<4; i++) {
+ DanceChord& _chord = chords.at(j);
+ if(_chord.find(i) != _chord.end()) {
+ _chord[i].begin = tm;
+ _chord[i].end = tm;
+ }
+ }
+ tm += dur;
+ }
+ lcount =0;
+ continue;
}
- if (m_song.danceTracks.empty() ) throw std::runtime_error("No note data in the file");
- if (s.title.empty() || s.artist.empty()) throw std::runtime_error("Required header fields missing");
- if (m_bpm != 0.0) addBPM(0, m_bpm);
-
-}
+ //reading notes into a chord
+ std::istringstream iss(line);
+ DanceChord chord;
+ for(int i =0; i<4; i++){
+ if(iss.get() == '1') {
+ Note note;
+ chord[i] = note;
+ }
+ chords.push_back(chord);
+ lcount++;
+ count++;
+ }
+ continue;
+ }
+ endOfInput = true;
+ return chords;
+}
diff --git a/game/songparser.hh b/game/songparser.hh
index 9a16644..becd2e1 100644
--- a/game/songparser.hh
+++ b/game/songparser.hh
@@ -86,7 +86,7 @@ class SongParser {
Song& m_song;
std::stringstream m_ss;
unsigned int m_linenum;
- bool getline(std::string& line) { ++m_linenum; return std::getline(m_ss, line); }
+ bool getline(std::string& line) { ++m_linenum; return std::getline(m_ss, line);}
bool m_relative;
double m_gap;
double m_bpm;
@@ -98,6 +98,8 @@ class SongParser {
void iniParse();
bool smCheck(std::vector<char> const& data);
void smParse();
+ bool smParseField(std::string line);
+ DanceChords smParseNotes(std::string line, bool endOfInput);
double m_prevtime;
unsigned int m_prevts;
unsigned int m_relativeShift;
diff --git a/game/songs.cc b/game/songs.cc
index 477faab..c0e82db 100644
--- a/game/songs.cc
+++ b/game/songs.cc
@@ -86,7 +86,8 @@ void Songs::reload_internal(fs::path const& parent) {
}
}
} catch (std::exception const& e) {
- std::cout << "Error accessing " << parent << std::endl;
+
+ std::cout << "Error accessing " << parent << e.what() << std::endl;
}
}
|