/*
* UltraStar Deluxe - Karaoke Game
*
* UltraStar Deluxe is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "song.hpp"
#include "lyric_word.hpp"
#include "utils/locale_independent_float.hpp"
namespace usdx
{
log4cpp::Category& Song::log =
log4cpp::Category::getInstance("usdx.base.Song");
const boost::filesystem::wpath& Song::get_filename(void) const
{
return filename;
}
Song::Song(const boost::filesystem::wpath& filename,
const std::map<std::string, std::string>& header) :
filename(filename), custom_header_tags(header)
{
std::map<std::string, std::string>::iterator it;
title = get_header_tag("TITLE", true);
artist = get_header_tag("ARTIST", true);
mp3 = get_header_tag("MP3", true);
bpm.push_back(new BPM(get_header_tag_float("BPM", true)));
gap = get_header_tag_float("GAP");
cover_file = get_header_tag("COVER");
background = get_header_tag("BACKGROUND");
video = get_header_tag("VIDEO");
video_gap = get_header_tag_float("VIDEOGAP");
genre = get_header_tag("GENRE");
edition = get_header_tag("EDITION");
creator = get_header_tag("CREATOR");
language = get_header_tag("LANGUAGE");
year = get_header_tag_int("YEAR");
start = get_header_tag_float("START");
stop = get_header_tag_int("END");
resolution = get_header_tag_int("RESOLUTION");
notes_gap = get_header_tag_int("NOTESGAP");
relative = get_header_tag_bool("RELATIVE");
// TODO
// EncFile := DecodeFilename(Value);
// if (self.Path.Append(EncFile).IsFile) then
// self.Video := EncFile
// else
// Log.LogError('Can''t find video file in song: ' +
// Fulfilling);
// TODO
// encoding = get_header_tag("ENCODING");
}
Song::~Song(void)
{
for (std::list<BPM*>::iterator it = bpm.begin(); it != bpm.end(); it++) {
delete *it;
}
bpm.clear();
for (std::list<LyricLine*>::iterator it = lyrics.begin(); it != lyrics.end(); it++) {
delete *it;
}
lyrics.clear();
}
std::string Song::get_header_tag(const std::string& tag, const bool required)
{
std::map<std::string, std::string>::iterator it;
std::string result = "";
if ((it = custom_header_tags.find(tag)) != custom_header_tags.end()) {
result = it->second;
custom_header_tags.erase(it);
}
else if (required) {
log << log4cpp::Priority::ERROR << "Incomplete Song! Missing '" <<
tag << "' Tag in: '" << get_filename() << "'";
throw MissingTagException(tag, "Incomplete Song! Missing Tag.");
}
return result;
}
float Song::get_header_tag_float(const std::string& tag, const bool required)
{
std::map<std::string, std::string>::iterator it;
float result;
if ((it = custom_header_tags.find(tag)) != custom_header_tags.end()) {
result = LocaleIndependentFloat(it->second).get_value();
custom_header_tags.erase(it);
}
else if (required) {
log << log4cpp::Priority::ERROR << "Incomplete Song! Missing '" <<
tag << "' Tag in: '" << get_filename() << "'";
throw MissingTagException(tag, "Incomplete Song! Missing Tag.");
}
return result;
}
int Song::get_header_tag_int(const std::string& tag, const bool required)
{
std::map<std::string, std::string>::iterator it;
int result;
if ((it = custom_header_tags.find(tag)) != custom_header_tags.end()) {
std::istringstream stream(it->second);
custom_header_tags.erase(it);
stream >> result;
}
else if (required) {
log << log4cpp::Priority::ERROR << "Incomplete Song! Missing '" <<
tag << "' Tag in: '" << get_filename() << "'";
throw MissingTagException(tag, "Incomplete Song! Missing Tag.");
}
return result;
}
bool Song::get_header_tag_bool(const std::string& tag, const bool required)
{
std::map<std::string, std::string>::iterator it;
bool result;
if ((it = custom_header_tags.find(tag)) != custom_header_tags.end()) {
// accept all like (YES, JA, TRUE, 1)
result = (it->second[0] == 'j' || it->second[0] == 'J' ||
it->second[0] == 'y' || it->second[0] == 'Y' ||
it->second[0] == 't' || it->second[0] == 'T' ||
it->second[0] == '1');
custom_header_tags.erase(it);
}
else if (required) {
log << log4cpp::Priority::ERROR << "Incomplete Song! Missing '" <<
tag << "' Tag in: '" << get_filename() << "'";
throw MissingTagException(tag, "Incomplete Song! Missing Tag.");
}
return result;
}
LyricLine* Song::get_last_lyric_line(void)
{
if (lyrics.size() > 0) {
return lyrics.back();
}
return create_new_lyric_line(0);
}
LyricLine* Song::create_new_lyric_line(int start)
{
LyricLine* line = new LyricLine(start);
lyrics.push_back(line);
return line;
}
const std::string& Song::get_title(void) const
{
return title;
}
const std::string& Song::get_artist(void) const
{
return artist;
}
const std::string& Song::get_mp3(void) const
{
return mp3;
}
const float Song::get_bpm(int beat) const
{
float last_bpm;
for (std::list<BPM*>::const_iterator it = bpm.begin(); it != bpm.end(); it++) {
if ((*it)->get_beat() > beat) {
break;
}
last_bpm = (*it)->get_bpm();
}
return last_bpm;
}
const float Song::get_gap(void) const
{
return gap;
}
const std::string& Song::get_cover_file(void) const
{
return cover_file;
}
const std::string& Song::get_background(void) const
{
return background;
}
const std::string& Song::get_video(void) const
{
return video;
}
const float Song::get_video_gap(void) const
{
return video_gap;
}
const std::string& Song::get_genre(void) const
{
return genre;
}
const std::string& Song::get_edition(void) const
{
return edition;
}
const std::string& Song::get_creator(void) const
{
return creator;
}
const std::string& Song::get_language(void) const
{
return language;
}
const int Song::get_year(void) const
{
return year;
}
const float Song::get_start(void) const
{
return start;
}
const int Song::get_stop(void) const
{
return stop;
}
const int Song::get_resolution(void) const
{
return resolution;
}
const int Song::get_notes_gap(void) const
{
return notes_gap;
}
const bool Song::get_relative(void) const
{
return relative;
}
// TODO:
// const std::string& Song::get_encoding(void) const
// {
// return encoding;
// }
int Song::get_relative_beat(void)
{
if (relative)
return get_last_lyric_line()->get_start();
return 0;
}
void Song::new_bpm(const int beat, const float new_bpm)
{
bpm.push_back(new BPM(beat + get_relative_beat(), new_bpm));
}
void Song::new_line(const int line_out, const int line_in)
{
get_last_lyric_line()->set_end(line_out + get_relative_beat());
create_new_lyric_line(line_in + get_relative_beat());
}
void Song::new_note(const char type, const int beat, const int length, const int height, const std::string& lyric)
{
get_last_lyric_line()->add_word(new LyricWord(type, beat + get_relative_beat(), length, height, lyric));
}
};