From 823a82611d37e618a4734ea480fab4c60b73f5b7 Mon Sep 17 00:00:00 2001 From: piernov Date: Thu, 18 Aug 2016 14:13:40 +0200 Subject: Initial Import --- loadSongs.cpp | 367 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100755 loadSongs.cpp (limited to 'loadSongs.cpp') diff --git a/loadSongs.cpp b/loadSongs.cpp new file mode 100755 index 0000000..0948212 --- /dev/null +++ b/loadSongs.cpp @@ -0,0 +1,367 @@ +#include +#include +#include +#include +#include +#include + +#include "logging.h" +#include "files.h" + +const char *songsPath = "/sdcard/Songs/"; + +void split(std::vector &tokens, const std::string &text, const char *sep) { + int start = 0, end = 0; + while ((end = text.find(sep, start)) != std::string::npos) { + tokens.push_back(text.substr(start, end - start)); + start = end + 1; + } + tokens.push_back(text.substr(start)); +} + +// trim from start +static inline std::string <rim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(isspace)))); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(isspace))).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) { + return ltrim(rtrim(s)); +} + +/* Returns a list of directories (except the ones that begin with a dot) */ + +void GetDirectories(std::vector &out, const char *directory) +{ +#ifdef WINDOWS + HANDLE dir; + WIN32_FIND_DATA file_data; + + if ((dir = FindFirstFile((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE) + return; /* No files found */ + + do { + const string file_name = file_data.cFileName; + const string full_file_name = directory + "/" + file_name; + const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + + if (file_name[0] == '.') + continue; + + if (!is_directory) + continue; + + out.push_back(full_file_name); + } while (FindNextFile(dir, &file_data)); + + FindClose(dir); +#else + DIR *dir; + class dirent *ent; + class stat st; + + dir = opendir(directory); + if(dir == NULL) + { + std::string errmsg = "Cannot open directory "; + logstdError("GetDirectories", errmsg + directory); + } + else + { + while ((ent = readdir(dir)) != NULL) { + const std::string file_name = ent->d_name; + std::string full_file_name = directory; + full_file_name.append("/" + file_name + "/"); + + if (file_name[0] == '.') + continue; + + if (stat(full_file_name.c_str(), &st) == -1) + continue; + + if (!S_ISDIR(st.st_mode)) + continue; + + out.push_back(full_file_name); + } + closedir(dir); + if(out.empty()) + { + std::string errmsg = "Directory empty: "; + logstdError("GetDirectories", errmsg + directory); + } + } +#endif +} // GetFilesInDirectory + +/* Returns a list of sm files */ + +void GetSmFiles(std::vector &out, const std::string directory) +{ +#ifdef WINDOWS + HANDLE dir; + WIN32_FIND_DATA file_data; + + if ((dir = FindFirstFile((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE) + return; /* No files found */ + + do { + const string file_name = file_data.cFileName; + const string full_file_name = directory + "/" + file_name; + const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + + std::vector tokens; + split(tokens, file_name, "."); + + if (strcmp(tokens.back(), "sm")) + continue; + + if (is_directory) + continue; + + out.push_back(full_file_name); + } while (FindNextFile(dir, &file_data)); + + FindClose(dir); +#else + DIR *dir; + class dirent *ent; + class stat st; + + dir = opendir(directory.c_str()); + if(dir == NULL) + { + std::string errmsg = "Cannot open directory "; + logstdError("GetDirectories", errmsg + directory); + } + else + { + while ((ent = readdir(dir)) != NULL) { + const std::string file_name = ent->d_name; + std::string full_file_name = directory; + full_file_name.append("/" + file_name); + + std::vector tokens; + split(tokens, file_name, "."); + + if (tokens.back() != "sm") + continue; + + if (stat(full_file_name.c_str(), &st) == -1) + continue; + + const bool is_readable = (st.st_mode & S_IRUSR) != 0; + + if (!is_readable) + continue; + + out.push_back(file_name); + } + closedir(dir); + if(out.empty()) + { + std::string errmsg = "Directory empty: "; + logstdError("GetDirectories", errmsg + directory); + } + } +#endif +} // GetSmFiles + + +int readSongFile(std::string &path, musicfile &songFile) +{ + bool reading_note = false; + int current_note_line = 0; + std::vector currentNoteData; + std::vector> currentLineNoteData; + notes currentNotes; + + std::string line; + std::ifstream file; + file.open(path.c_str(), std::ifstream::in); + if (!file) + { + std::string msg = "Could not open "; + msg.append(path); + logstdError("loadFile", msg); + return 1; + } + while(file.good()) + { + std::getline(file, line); + line = trim(line); + if(line.length() == 0) + continue; + else if(line[0] == '/') + continue; + else if(line[0] == '#') + { + std::vector tokens; + split(tokens, line, ":"); + + if(tokens[0].compare("#NOTES") == 0) + { + reading_note = true; + continue; + } + else + reading_note = false; + + if(*tokens[1].rbegin() == ';') + tokens[1].pop_back(); + + if(tokens[0].compare("#TITLE") == 0) + { + songFile.title = tokens[1]; + } + else if(tokens[0].compare("#ARTIST") == 0) + { + songFile.artist = tokens[1]; + } + else if(tokens[0].compare("#BANNER") == 0) + { + songFile.banner = tokens[1]; + } + else if(tokens[0].compare("#BACKGROUND") == 0) + { + songFile.background = tokens[1]; + } + else if(tokens[0].compare("#MUSIC") == 0) + { + songFile.file = tokens[1]; + } + else if(tokens[0].compare("#OFFSET") == 0) + { + std::istringstream(tokens[1]) >> songFile.offset; + } + else if(tokens[0].compare("#BPMS") == 0) + { + std::vector listBpms; + split(listBpms, tokens[1], ","); + for(std::vector::iterator bpmData = listBpms.begin(); bpmData != listBpms.end(); ++bpmData) + { + std::vector bpm; + split(bpm, *bpmData, "="); + songBpm bpms; + std::istringstream(bpm[0]) >> bpms.beat; + std::istringstream(bpm[1]) >> bpms.bpm; + songFile.bpms.push_back(bpms); + } + } + } + else if(reading_note) + { + std::vector tokens; + split(tokens, line, ":"); + + if((*line.rbegin() == ':') || (tokens.size() > 1)) + { + switch(current_note_line) + { + case 0: + currentNotes.type = tokens[0]; + break; + case 1: + currentNotes.description = tokens[0]; + break; + case 2: + currentNotes.difficultyClass = tokens[0]; + break; + case 3: + std::istringstream ( tokens[1] ) >> currentNotes.difficultyMeter; + break; + case 4: + currentNotes.radarValues = tokens[0]; + break; + default: + std::string msg = "Too much ':' for #NOTES in "; + msg.append(path); + logstdError("readSongFile", msg); + break; + } + current_note_line += 1; + } + else if(line[0] == ',') + { + currentNotes.noteData.push_back(currentLineNoteData); + currentLineNoteData.clear(); + } + else if(line[0] == ';') + { + current_note_line = 0; + songFile.songNotes.push_back(currentNotes); + static const notes tempStruct; + currentNotes = tempStruct; + } + else + { + for(std::string::iterator c = line.begin(); c != line.end(); ++c) { + switch(*c) + { + case '0': + currentNoteData.push_back(None); + break; + case '1': + currentNoteData.push_back(Tap); + break; + case '2': + currentNoteData.push_back(Hold_begin); + break; + case '3': + currentNoteData.push_back(Hold_end); + break; + case '4': + currentNoteData.push_back(Roll); + break; + case 'M': + currentNoteData.push_back(Mine); + break; + case 'L': + currentNoteData.push_back(Lift); + break; + case 'F': + currentNoteData.push_back(Fake); + break; + } + } + currentLineNoteData.push_back(currentNoteData); + currentNoteData.clear(); + } + } + } + if(!file.eof()) + { + logstdError("readSongFile", "Line cannot be read"); + } + file.close(); + return 0; +} + +std::vector loadSongs() +{ + std::vector directories; + std::vector smfiles; + std::vector songs; + + GetDirectories(directories, songsPath); + + for(std::vector::iterator it = directories.begin(); it != directories.end(); ++it) { + GetSmFiles(smfiles, *it); + for(std::vector::iterator ite = smfiles.begin(); ite != smfiles.end(); ++ite) { + musicfile songData; + std::string file = *it + *ite; + if(!readSongFile(file, songData)) + songData.path = *it; + songs.push_back(songData); + } + } + return songs; +} + -- cgit v1.2.3-54-g00ecf