You can subscribe to this list here.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(25) |
Jul
(288) |
Aug
(119) |
Sep
(31) |
Oct
(59) |
Nov
(458) |
Dec
(359) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(268) |
Feb
(26) |
Mar
(36) |
Apr
(48) |
May
(119) |
Jun
(37) |
Jul
(173) |
Aug
(429) |
Sep
(137) |
Oct
(156) |
Nov
(59) |
Dec
(45) |
| 2011 |
Jan
(398) |
Feb
(257) |
Mar
(49) |
Apr
(5) |
May
(34) |
Jun
(11) |
Jul
(38) |
Aug
(12) |
Sep
(1) |
Oct
(49) |
Nov
(5) |
Dec
(10) |
| 2012 |
Jan
(21) |
Feb
(32) |
Mar
(20) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(173) |
Aug
|
Sep
(25) |
Oct
(6) |
Nov
(44) |
Dec
|
|
From: Yoda-JM <yo...@us...> - 2010-01-15 22:44:57
|
Module: performous
Branch: master
Commit: 47ae3fe068c751197d41b8d9c89184162859e0bf
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Jan 15 23:44:39 2010 +0100
Fixed TigerGame dancepad (strange fix)
---
data/schema.xml | 2 +-
game/joystick.cc | 20 ++++++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/data/schema.xml b/data/schema.xml
index 6548b2a..58cd9c4 100644
--- a/data/schema.xml
+++ b/data/schema.xml
@@ -85,7 +85,7 @@ to save the current settings to XML.
</locale>
</entry>
<entry name="game/instruments" type="string_list">
- <!-- Should be SDL_ID:{GUITAR_GUITARHERO|GUITAR_GUITARHERO_XPLORER|GUITAR_ROCKBAND_PS3|GUITAR_ROCKBAND_XB360|DRUMS_GUITARHERO|DRUMS_ROCKBAND_PS3|DRUMS_ROCKBAND_XB360|DRUMS_MIDI|DANCEPAD_GENERIC}
+ <!-- Should be SDL_ID:{GUITAR_GUITARHERO|GUITAR_GUITARHERO_XPLORER|GUITAR_ROCKBAND_PS3|GUITAR_ROCKBAND_XB360|DRUMS_GUITARHERO|DRUMS_ROCKBAND_PS3|DRUMS_ROCKBAND_XB360|DRUMS_MIDI|DANCEPAD_GENERIC|DANCEPAD_TIGERGAME}
example:
<stringvalue>0:GUITAR_GUITARHERO</stringvalue>
-->
diff --git a/game/joystick.cc b/game/joystick.cc
index 0cd0bfc..61ec453 100644
--- a/game/joystick.cc
+++ b/game/joystick.cc
@@ -35,22 +35,22 @@ void input::MidiDrums::process() {
}
#endif
-static const unsigned SDL_BUTTONS = 10;
+static const unsigned SDL_BUTTONS = 12;
int input::buttonFromSDL(input::Private::Type _type, unsigned int _sdl_button) {
static const int inputmap[9][SDL_BUTTONS] = {
//G R Y B O S // for guitars (S=starpower)
- { 2, 0, 1, 3, 4, 5, -1, -1, 8, 9 }, // Guitar Hero guitar
- { 0, 1, 3, 2, 4,-1, 8, 9,-1,-1 }, // Guitar Hero X-plorer guitar
- { 3, 0, 1, 2, 4, 5, -1, -1, 8, 9 }, // Rock Band guitar PS3
- { 0, 1, 3, 2, 4, 5, -1, -1, 8, 9 }, // Rock Band guitar XBOX360
+ { 2, 0, 1, 3, 4, 5, -1, -1, 8, 9, -1, -1 }, // Guitar Hero guitar
+ { 0, 1, 3, 2, 4,-1, 8, 9,-1,-1, -1, -1 }, // Guitar Hero X-plorer guitar
+ { 3, 0, 1, 2, 4, 5, -1, -1, 8, 9, -1, -1 }, // Rock Band guitar PS3
+ { 0, 1, 3, 2, 4, 5, -1, -1, 8, 9, -1, -1 }, // Rock Band guitar XBOX360
//K R Y B G O // for drums
- { 3, 4, 1, 2, 0, 4, -1, -1, 8, 9 }, // Guitar Hero drums
- { 3, 4, 1, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums PS3
- { 4, 1, 3, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums XBOX360
+ { 3, 4, 1, 2, 0, 4, -1, -1, 8, 9, -1, -1 }, // Guitar Hero drums
+ { 3, 4, 1, 2, 0,-1, -1, -1, 8, 9, -1, -1 }, // Rock Band drums PS3
+ { 4, 1, 3, 2, 0,-1, -1, -1, 8, 9, -1, -1 }, // Rock Band drums XBOX360
// Left Down Up Right DownL DownR UpL UpR Start Select
- { 0, 1, 2, 3, 6, 7, 4, 5, 9, 8 }, // generic dance pad
- { 9, 8, 2, 1, 6, 7, 4, 5, 0, 3 } // TigerGame dance pas
+ { 0, 1, 2, 3, 6, 7, 4, 5, 9, 8, -1, -1 }, // generic dance pad
+ { 9, 8, -1, -1, -1, -1, -1, -1, 0, 3, 1, 2 } // TigerGame dance pad
};
if( _sdl_button >= SDL_BUTTONS ) return -1;
switch(_type) {
|
|
From: Yoda-JM <yo...@us...> - 2010-01-15 22:17:49
|
Module: performous
Branch: master
Commit: 952a80c282ae460a1ca5d77ae9590f3b6da67d03
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Jan 15 23:17:30 2010 +0100
Added TigerGame USB dancepad
---
game/joystick.cc | 17 ++++++++++++++---
game/joystick.hh | 12 ++++++------
2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/game/joystick.cc b/game/joystick.cc
index 4a1196a..0cd0bfc 100644
--- a/game/joystick.cc
+++ b/game/joystick.cc
@@ -38,7 +38,7 @@ void input::MidiDrums::process() {
static const unsigned SDL_BUTTONS = 10;
int input::buttonFromSDL(input::Private::Type _type, unsigned int _sdl_button) {
- static const int inputmap[8][SDL_BUTTONS] = {
+ static const int inputmap[9][SDL_BUTTONS] = {
//G R Y B O S // for guitars (S=starpower)
{ 2, 0, 1, 3, 4, 5, -1, -1, 8, 9 }, // Guitar Hero guitar
{ 0, 1, 3, 2, 4,-1, 8, 9,-1,-1 }, // Guitar Hero X-plorer guitar
@@ -49,7 +49,8 @@ int input::buttonFromSDL(input::Private::Type _type, unsigned int _sdl_button) {
{ 3, 4, 1, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums PS3
{ 4, 1, 3, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums XBOX360
// Left Down Up Right DownL DownR UpL UpR Start Select
- { 0, 1, 2, 3, 6, 7, 4, 5, 9, 8 } // generic dance pad
+ { 0, 1, 2, 3, 6, 7, 4, 5, 9, 8 }, // generic dance pad
+ { 9, 8, 2, 1, 6, 7, 4, 5, 0, 3 } // TigerGame dance pas
};
if( _sdl_button >= SDL_BUTTONS ) return -1;
switch(_type) {
@@ -69,6 +70,8 @@ int input::buttonFromSDL(input::Private::Type _type, unsigned int _sdl_button) {
return inputmap[6][_sdl_button];
case input::Private::DANCEPAD_GENERIC:
return inputmap[7][_sdl_button];
+ case input::Private::DANCEPAD_TIGERGAME:
+ return inputmap[8][_sdl_button];
default:
return -1;
}
@@ -188,7 +191,7 @@ void input::SDL::init() {
using namespace boost::spirit::classic;
rule<> type = str_p("GUITAR_GUITARHERO") | "GUITAR_ROCKBAND_PS3" | "GUITAR_ROCKBAND_XB360"
| "GUITAR_GUITARHERO_XPLORER" | "DRUMS_GUITARHERO" | "DRUMS_ROCKBAND_PS3" | "DRUMS_ROCKBAND_XB360"
- | "DRUMS_MIDI" | "DANCEPAD_GENERIC";
+ | "DRUMS_MIDI" | "DANCEPAD_GENERIC" | "DANCEPAD_TIGERGAME";
rule<> entry = uint_p[assign_a(sdl_id)] >> ":" >> (type)[assign_a(instrument_type)];
ConfigItem::StringList const& instruments = config["game/instruments"].sl();
@@ -215,6 +218,8 @@ void input::SDL::init() {
forced_type[sdl_id] = input::Private::DRUMS_MIDI;
} else if (instrument_type == "DANCEPAD_GENERIC") {
forced_type[sdl_id] = input::Private::DANCEPAD_GENERIC;
+ } else if (instrument_type == "DANCEPAD_TIGERGAME") {
+ forced_type[sdl_id] = input::Private::DANCEPAD_TIGERGAME;
}
}
}
@@ -261,6 +266,9 @@ void input::SDL::init() {
case input::Private::DRUMS_MIDI:
std::cout << " Detected as: MIDI Drums (forced)" << std::endl;
break;
+ case input::Private::DANCEPAD_TIGERGAME:
+ std::cout << " Detected as: TigerGame dance pad (forced)" << std::endl;
+ break;
case input::Private::DANCEPAD_GENERIC:
std::cout << " Detected as: Generic dance pad (forced)" << std::endl;
break;
@@ -295,6 +303,9 @@ void input::SDL::init() {
} else if( name.find("Mad Catz Portable Drum") != std::string::npos) {
std::cout << " Detected as: RockBand Drums Xbox360" << std::endl;
input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB_XB360);
+ } else if( name.find("TigerGame") != std::string::npos ) {
+ std::cout << " Detected as: TigerGame Dance Pad" << std::endl;
+ input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DANCEPAD_TIGERGAME);
} else if( name.find("RedOctane USB Pad") != std::string::npos ) {
std::cout << " Detected as: Generic Dance Pad" << std::endl;
input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DANCEPAD_GENERIC);
diff --git a/game/joystick.hh b/game/joystick.hh
index 8c4bcdf..e55a9d5 100644
--- a/game/joystick.hh
+++ b/game/joystick.hh
@@ -33,11 +33,11 @@ namespace input {
namespace Private {
enum Type { GUITAR_RB_PS3, DRUMS_RB_PS3, GUITAR_RB_XB360, DRUMS_RB_XB360,
- GUITAR_GH, GUITAR_GH_XPLORER, DRUMS_GH, DRUMS_MIDI, DANCEPAD_GENERIC };
+ GUITAR_GH, GUITAR_GH_XPLORER, DRUMS_GH, DRUMS_MIDI, DANCEPAD_TIGERGAME, DANCEPAD_GENERIC };
static unsigned int KEYBOARD_ID = UINT_MAX;
static unsigned int KEYBOARD_ID2 = KEYBOARD_ID-1;
static unsigned int KEYBOARD_ID3 = KEYBOARD_ID-2; // Three ids needed for keyboard guitar/drumkit/dancepad
-
+
class InputDevPrivate {
public:
InputDevPrivate() : m_assigned(false), m_type(input::Private::DRUMS_GH) {
@@ -90,7 +90,7 @@ namespace input {
return true;
}
else if( _type == input::DANCEPAD &&
- (m_type == input::Private::DANCEPAD_GENERIC) ) {
+ (m_type == input::Private::DANCEPAD_GENERIC || m_type == input::Private::DANCEPAD_TIGERGAME) ) {
return true;
}
else {
@@ -103,7 +103,7 @@ namespace input {
bool m_pressed[BUTTONS];
input::Private::Type m_type;
};
-
+
typedef std::map<unsigned int,InputDevPrivate> InputDevs;
extern InputDevs devices;
}
@@ -164,7 +164,7 @@ namespace input {
// Returns true if event is taken, feed an InputDev by transforming SDL_Event into Event
bool pushEvent(SDL_Event);
}
-
+
#ifdef USE_PORTMIDI
class MidiDrums {
public:
@@ -178,6 +178,6 @@ namespace input {
Map map;
};
#endif
-
+
};
|
|
From: Yoda-JM <yo...@us...> - 2010-01-15 19:04:32
|
Module: performous
Branch: master
Commit: fc7b036020f54ee534db9bed1b60e2be97cd3bb4
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Jan 15 20:04:13 2010 +0100
Fixed whitespaces
---
game/songparser-sm.cc | 16 +++++++---------
1 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/game/songparser-sm.cc b/game/songparser-sm.cc
index 85229ca..f42f6ed 100644
--- a/game/songparser-sm.cc
+++ b/game/songparser-sm.cc
@@ -11,7 +11,7 @@
/// Functions used for parsing the StepMania SM format
namespace {
-
+
// Here are some functions needed in reading the data.
void assign(int& var, std::string const& str) {
try {
@@ -70,7 +70,7 @@ void SongParser::smParse() {
for (std::size_t i = 0; i < m_stops.size(); ++i) s.stops[i] = stopConvert(m_stops[i]);
m_tsPerBeat = 4;
}
-
+
bool SongParser::smParseField(std::string line) {
boost::trim(line);
if (line.empty()) return true;
@@ -83,7 +83,6 @@ bool SongParser::smParseField(std::string line) {
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") {
-
/*All remaining data is parsed here.
All five lines of note metadata is read first and then smParseNotes is called to read
the actual note data.
@@ -112,11 +111,11 @@ bool SongParser::smParseField(std::string line) {
//<DifficultyMeter>:
if(!getline(line)) { throw std::runtime_error("Required note data missing"); }
if(!getline(line)) { throw std::runtime_error("Required note data missing"); }
-
+
//<NoteData>:
Notes notes = smParseNotes(line);
- //Here all note data from the current track is inserted into containers
+ //Here all note data from the current track is inserted into containers
// TODO: support other track types. For now all others are simply ignored.
if (notestype == "dance-single" || notestype == "dance-double" || notestype == "dance-solo"
|| notestype == "pump-single" || notestype == "ez2-single" || notestype == "ez2-real"
@@ -149,7 +148,7 @@ bool SongParser::smParseField(std::string line) {
else if (key == "SAMPLESTART") assign(m_song.preview_start, value);
else if (key == "BPMS"){
std::istringstream iss(value);
- double ts, bpm;
+ double ts, bpm;
char chr;
while (iss >> ts >> chr >> bpm) {
if (ts == 0.0) m_bpm = bpm;
@@ -164,7 +163,6 @@ bool SongParser::smParseField(std::string line) {
while (iss >> beat >> chr >> sec) {
m_stops.push_back(std::make_pair(beat * 4.0, sec));
if (!(iss >> chr)) break;
-
}
}
/*.sm fileformat has also the following constants but they are ignored in this version of the parser:
@@ -188,11 +186,11 @@ bool SongParser::smParseField(std::string line) {
Notes SongParser::smParseNotes(std::string line) {
//container for dance songs
- typedef std::map<int, Note> DanceChord; //int indicates "arrow" position (cmp. fret in guitar)
+ typedef std::map<int, Note> DanceChord; //int indicates "arrow" position (cmp. fret in guitar)
typedef std::vector<DanceChord> DanceChords;
DanceChords chords; //temporary container for notes
- Notes notes;
+ Notes notes;
unsigned measure = 1;
double begin = 0.0;
|
|
From: Tapio V. <aa...@us...> - 2010-01-15 09:45:55
|
Module: web Branch: master Commit: 0b4025efc7b7470c0b067a2f12c5b04ecd0cddee Author: Tapio Vierros <tap...@gm...> Date: Fri Jan 15 11:42:53 2010 +0200 Fixed preface in About page. --- htdocs-source/about.txt | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/htdocs-source/about.txt b/htdocs-source/about.txt index 7ae41d6..b780533 100644 --- a/htdocs-source/about.txt +++ b/htdocs-source/about.txt @@ -1,6 +1,8 @@ What is it? -:~preface:Performous is a free cross-platform band game game. +:~preface:Performous is a free cross-platform music and rhythm game. + + :h2:Karaoke? |
|
From: Tapio V. <aa...@us...> - 2010-01-15 08:58:20
|
Module: performous Branch: master Commit: a2a90691af131cb15ffe08252a4406cba941392f Author: Tapio Vierros <tap...@gm...> Date: Fri Jan 15 10:55:11 2010 +0200 Update manpage. --- docs/performous.h2m | 76 ++++++++++++++++++--------------------------------- 1 files changed, 27 insertions(+), 49 deletions(-) diff --git a/docs/performous.h2m b/docs/performous.h2m index 27fb766..98e578d 100644 --- a/docs/performous.h2m +++ b/docs/performous.h2m @@ -1,19 +1,16 @@ Include file for Performous man page [name] -performous \- The free karaoke game +performous \- The free music and rhythm game [description] -Performous is a free cross-platform clone of the Playstation 2 game Singstar. +Performous is a free cross-platform karaoke, band and dancing game, where +one or more players perform a song and the game scores their performances +based on timing and accuracy. -While Performous might be classified as a karaoke program, it is actually much -more than that. Instead of just displaying the lyrics, notes are also displayed -and the performance is scored based on how well you hit the notes and you can -see your own singing pitch on screen. - -Performous was previously known as UltraStar Next Generation (USNG) because it -supports the UltraStar song format. It is not a fork of the Delphi-based -UltraStar games, as Performous is rewritten from scratch in C++. +Performous supports songs in UltraStar, Frets on Fire and StepMania formats. +Also, microphones and instruments from SingStar, Guitar Hero and Rock Band +as well as some dance pads are autodetected. If you have trouble with the program (no songs found, audio not working, etc), try running it on a terminal. Some useful debug information is printed there. @@ -22,40 +19,32 @@ try running it on a terminal. Some useful debug information is printed there. In-game navigation uses the following keys: .SS "Global shortcuts:" .TP +\fBLeft\fR/\fBRight\fR/\fBUp\fR/\fBDown\fR/ +Change selected option/song +.TP +\fBEnter\fR +Enter selection +.TP \fBEsc\fR -Exit the current screen +Exit the current screen/mode .TP \fBAlt+Enter\fR Switch between full screen and windowed modes - -.SS "Main menu:" .TP -\fBS\fR -Sing: single player game +\fBPause\fR or \fBCtrl+P\fR +Pause audio/game .TP -\fBP\fR -Practice: displays the tones detected and a VU meter for checking microphone recording levels -.TP -\fBC\fR -Configuration: adjust settings +\fBCtrl+Up/Down\fR +Change audio volume .SS "Song selection:" .TP -\fBEnter\fR -Pick the currently selected song -.TP -\fBLeft\fR/\fBRight\fR/\fBPgUp\fR/\fBPgDn\fR -Browse the list of songs -.TP \fBUp\fR/\fBDown\fR Switch the sort order (song name, artist, edition, genre or song folder path) .TP \fBAny text\fR Search for songs (write the text to find, uses regexp format) .TP -\fBPause\fR or \fBSpace\fR -Pause song preview and automatic song switching -.TP \fBTab\fR Randomize songs (sort them again) .TP @@ -64,47 +53,36 @@ Refresh song list (reload from disk) .TP \fBF4\fR Enter jukebox mode (play songs entirely, hide song browser, allow seeking with Up/Down) -.TP -\fBEsc\fR -Exit to main menu, exit jukebox mode or quit search mode .SS "Singing screen:" .TP -\fBLeft\fR/\fBRight\fR/\fBUp\fR/\fBDown\fR/\fBHome\fR +\fBCtrl+Left/Right\fR/\fBHome\fR Fast forward or rewind the song .TP \fBEnter\fR Skip long instrumental breaks, or get the grading instantly at the end of song. .TP -\fBPause\fR or \fBSpace\fR -Pause the game -.TP -\fBF4\fR +\fBCtrl+S\fR Toggle synth mode (synthesized tone for notes) .TP -\fBF5\fR/\fBF6\fR +\fBCtrl+F1/F2\fR Adjust audio/video sync. Use if the notes pass the black line at incorrect time. .TP -\fBF7\fR/\fBF8\fR +\fBCtrl+F3/F4\fR Adjust audio roundtrip latency. Use if the pitch wave does not match the notes, when you match your timing to what you hear. .TP -\fBF9\fR +\fBCtrl+F5/F6\fR +The total of USB controller latency combined with audio output latency. Adjust so that you can hit the notes best when playing by ear (not looking on screen). +.TP +\fBCtrl+K\fR Toggle karaoke mode (hide notes and scores) .TP -\fBF10\fR +\fBCtrl+W\fR Toggle pitch wave rendering (only when karaoke mode is disabled) .TP \fBCtrl+R\fR Hot reload song from disk (useful for making or repairing songs) -.SS "Configuration:" -.TP -\fBLeft\fR/\fBRight\fR/\fBUp\fR/\fBDown\fR/\fBEnter\fR -Modify options -.TP -\fBCtrl+S\fR -Save current configuration to configuration file - [audio device configuration] Performous normally autodetects microphones and playback devices correctly, but if this fails on your machine, you will need to configure them from command line because in-game configuration is not yet implemented. Once you have them working, enter the configuration menu and press \fBCtrl+S\fR to save them to your config file so that they don't need to specified when starting the program. |
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-15 01:34:47
|
Module: performous
Branch: master
Commit: 34646e81d281c3458702c3d4e82dc07b039618ad
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jan 15 03:34:34 2010 +0200
Skip scoring if the note hasn't begun yet (fixes flashing on the next note)
---
game/player.cc | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/game/player.cc b/game/player.cc
index 8b8c7f5..7de86d5 100644
--- a/game/player.cc
+++ b/game/player.cc
@@ -25,6 +25,7 @@ void Player::update() {
double endTime = Engine::TIMESTEP * m_pos;
// Iterate over all the notes that are considered for this timestep
while (m_scoreIt != m_song.notes.end()) {
+ if (endTime < m_scoreIt->begin) break; // The note begins later than on this timestep
// If tone was detected, calculate score
if (t) {
double note = m_song.scale.getNote(t->freq);
@@ -33,7 +34,7 @@ void Player::update() {
m_score += score_addition;
m_noteScore += score_addition;
m_lineScore += score_addition;
- // Add power
+ // Add power if already on the note
m_scoreIt->power = std::max(m_scoreIt->power, m_scoreIt->powerFactor(note));
}
// If a row of lyrics ends, calculate how well it went
@@ -42,7 +43,7 @@ void Player::update() {
} else {
m_maxLineScore = 0; // Not in SLEEP note anymore, so reset maximum
}
- if (endTime < m_scoreIt->end) break;
+ if (endTime < m_scoreIt->end) break; // The note continues past this timestep
// Set accuracy
m_scoreIt->accuracy = std::max(m_scoreIt->accuracy, m_noteScore / m_song.m_scoreFactor / m_scoreIt->maxScore());
m_noteScore = 0; // Reset noteScore as we are moving on to the next one
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-15 00:45:59
|
Module: performous
Branch: master
Commit: 0d4d24e28073498b2fd59b77b2899d279a53fdb9
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jan 15 02:45:48 2010 +0200
Rewritten singing note power handling (fixes flashing notes issue) and score calculation (cleanup)
---
docs/TODO.txt | 2 ++
game/notes.cc | 21 ++++++++-------------
game/notes.hh | 10 ++++++----
game/player.cc | 11 ++++++++---
4 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/docs/TODO.txt b/docs/TODO.txt
index dd2933b..acb923e 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -70,3 +70,5 @@ Bugs:
* Different images may also stop at the exact same pixel
=> out of memory condition or something?
+- Instrument data files + catch
+
diff --git a/game/notes.cc b/game/notes.cc
index 0b78c10..3ee1845 100644
--- a/game/notes.cc
+++ b/game/notes.cc
@@ -55,25 +55,20 @@ double MusicalScale::getNoteOffset(double freq) const {
Note::Note(): begin(getNaN()), end(getNaN()), phase(getNaN()), power(getNaN()), type(NORMAL), note(), notePrev() {}
double Note::diff(double note, double n) { return remainder(n - note, 12.0); }
-double Note::maxScore() const { return scoreMultiplier(0.0) * (end - begin); }
+double Note::maxScore() const { return scoreMultiplier() * (end - begin); }
double Note::score(double n, double b, double e) const {
double len = std::min(e, end) - std::max(b, begin);
if (len <= 0.0 || !(n > 0.0)) return 0.0;
- return scoreMultiplier(std::abs(diff(n))) * len;
+ return scoreMultiplier() * powerFactor(n) * len;
}
-double Note::scoreMultiplier(double error) const {
- double max = 0.0;
- switch (type) {
- case FREESTYLE: power += 1.0; return 1.0;
- case NORMAL: case SLIDE: max = 1.0; break;
- case GOLDEN: max = 2.0; break;
- case SLEEP: case TAP: case HOLDBEGIN: case HOLDEND: case ROLL: case MINE: case LIFT: break;
- }
- double accuracy = clamp(1.5 - error, 0.0, 1.0);
- power += accuracy;
- return accuracy * max;
+double Note::scoreMultiplier() const { return type == GOLDEN ? 2.0 : 1.0; }
+
+double Note::powerFactor(double note) const {
+ if (type == FREESTYLE) return 1.0;
+ double error = std::abs(diff(note));
+ return clamp(1.5 - error, 0.0, 1.0);
}
Duration::Duration(): begin(getNaN()), end(getNaN()) {}
diff --git a/game/notes.hh b/game/notes.hh
index ae1694e..fdb0b09 100644
--- a/game/notes.hh
+++ b/game/notes.hh
@@ -71,10 +71,10 @@ struct Note {
double begin, ///< begin time
end; ///< end time
double phase; /// Position within a measure, [0, 1)
- /// power of note
+ /// power of note (how well it is being hit right now)
mutable double power;
/// how well the note was sung [0,1] (used for drawing a star)
- mutable float accuracy;
+ mutable double accuracy;
/// note type
enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLIDE = '+', SLEEP = '-',
TAP = '1', HOLDBEGIN = '2', HOLDEND = '3', ROLL = '4', MINE = 'M', LIFT = 'L'} type;
@@ -88,14 +88,16 @@ struct Note {
static double diff(double note, double n);
/// maximum score
double maxScore() const;
- /// score when singing
+ /// score when singing over time period (a, b), which needs not to be entirely within the note
double score(double freq, double b, double e) const;
+ /// How precisely the note is hit (always 1.0 for freestyle, 0..1 for others)
+ double powerFactor(double note) const;
/// compares begin of two notes
static bool ltBegin(Note const& a, Note const& b) { return a.begin < b.begin; }
/// compares end of two notes
static bool ltEnd(Note const& a, Note const& b) { return a.end < b.end; }
private:
- double scoreMultiplier(double error) const;
+ double scoreMultiplier() const;
};
typedef std::vector<Note> Notes;
diff --git a/game/player.cc b/game/player.cc
index 3e43d95..8b8c7f5 100644
--- a/game/player.cc
+++ b/game/player.cc
@@ -13,6 +13,7 @@ Player::Player(Song& song, Analyzer& analyzer, size_t frames):
void Player::update() {
if (m_pos == m_pitch.size()) return; // End of song already
double beginTime = Engine::TIMESTEP * m_pos;
+ // Get the currently sung tone and store it in player's pitch data (also control inactivity timer)
Tone const* t = m_analyzer.findTone();
if (t) {
m_activitytimer = 1000;
@@ -22,13 +23,18 @@ void Player::update() {
m_pitch[m_pos++] = std::make_pair(getNaN(), -getInf());
}
double endTime = Engine::TIMESTEP * m_pos;
+ // Iterate over all the notes that are considered for this timestep
while (m_scoreIt != m_song.notes.end()) {
+ // If tone was detected, calculate score
if (t) {
+ double note = m_song.scale.getNote(t->freq);
// Add score
- double score_addition = m_song.m_scoreFactor * m_scoreIt->score(m_song.scale.getNote(t->freq), beginTime, endTime);
+ double score_addition = m_song.m_scoreFactor * m_scoreIt->score(note, beginTime, endTime);
m_score += score_addition;
m_noteScore += score_addition;
m_lineScore += score_addition;
+ // Add power
+ m_scoreIt->power = std::max(m_scoreIt->power, m_scoreIt->powerFactor(note));
}
// If a row of lyrics ends, calculate how well it went
if (m_scoreIt->type == Note::SLEEP) {
@@ -38,8 +44,7 @@ void Player::update() {
}
if (endTime < m_scoreIt->end) break;
// Set accuracy
- m_scoreIt->accuracy = std::max(m_scoreIt->accuracy,
- float(m_noteScore / m_song.m_scoreFactor / m_scoreIt->maxScore()));
+ m_scoreIt->accuracy = std::max(m_scoreIt->accuracy, m_noteScore / m_song.m_scoreFactor / m_scoreIt->maxScore());
m_noteScore = 0; // Reset noteScore as we are moving on to the next one
++m_scoreIt;
}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 22:33:45
|
Module: performous
Branch: master
Commit: 1f8ebee3ed40aaf7669d019b372e84621006f4b0
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jan 15 00:01:14 2010 +0200
Update TODO.txt with new plans, also removed old crashes that don't seem to be relevant anymore.
---
docs/TODO.txt | 70 +++++++++++---------------------------------------------
1 files changed, 14 insertions(+), 56 deletions(-)
diff --git a/docs/TODO.txt b/docs/TODO.txt
index 2d8377e..dd2933b 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -24,10 +24,18 @@ Big features:
Features:
-- Auto-calibration of acoustic roundtrip latency (playback + capture)
-- Better audio card configuration ingame (needs libda support for listing cards) [WIP]
+- Latency calibration
+ * Audio roundtrip by analyzing the sound captured by the microphone
+ * Controller/audio latency by playing blindly (listening to the beat only)
+ * Audio/video by playing visually without audio? (needs controller/audio calibrated)
+- Better audio card configuration ingame (needs PortAudio backend) [WIP]
- Allow playing a single song given as commandline argument (no menus)
-- Kiosk/arcade mode
+- Kiosk/arcade mode (disable exiting game and limit other functions)
+
+
+Dance features:
+- Colored arrows for timing
+- BGCHANGE support (background videos)
Text rendering bugs:
@@ -44,7 +52,7 @@ New config menu:
- Predefined options from config schema and libda device enumeration
-Ripper:
+SS Ripper:
- Compress into Vorbis Ogg and H.264 MKV
@@ -52,58 +60,8 @@ Ripper:
Bugs:
- On Compiz switching from fullscreen to window makes the window maximized even though the viewport stays small
-- Random segfault deep within librsvg when entering the singing screen (very hard to reproduce)
-
-*** glibc detected *** performous: free(): invalid pointer: 0x00007f1bc016ec30 ***
-======= Backtrace: =========
-/lib/libc.so.6[0x7f1bdc530cb8]
-/lib/libc.so.6(cfree+0x76)[0x7f1bdc533276]
-/usr/lib/libglib-2.0.so.0(g_ptr_array_free+0x4a)[0x7f1bdfca68fa]
-/usr/lib/librsvg-2.so.2[0x7f1bdf5b0c2c]
-/usr/lib/librsvg-2.so.2[0x7f1bdf5b0c59]
-/usr/lib/librsvg-2.so.2[0x7f1bdf59c532]
-/usr/lib/librsvg-2.so.2[0x7f1bdf5be78d]
-/usr/lib/libgobject-2.0.so.0(g_object_unref+0xc2)[0x7f1bdfa5a1f2]
-/usr/lib/librsvg-2.so.2[0x7f1bdf5bed68]
-/usr/lib/librsvg-2.so.2(rsvg_pixbuf_from_file_at_size+0x26)[0x7f1bdf5bee56]
-performous(_Z6loaderI7TextureEvRT_Ssb+0x82c)[0x451e1c]
-performous(_ZN7TextureC1ERKSs+0x44)[0x44f8b4]
-performous(_ZN11ProgressBarC1ERKSsS1_NS_4ModeEffb+0x40)[0x4aebd0]
-performous(_ZN10ScreenSing5enterEv+0x209)[0x4c9379]
-performous(_ZN11ScreenSongs15manageSharedKeyEi6SDLMod+0x178)[0x475d68]
-performous(_ZN11ScreenSongs11manageEventE9SDL_Event+0xcb)[0x47600b]
-performous[0x4d0659]
-performous(_Z8mainLoopv+0x579)[0x4d1bf9]
-performous(main+0x1d30)[0x4d42c0]
-
-- Random segfault on program exit (very hard to reproduce)
- * Don't even need to enter songs screen, start and exit is enough.
-
-- Hang on program exit (deadlock in mixer):
-(gdb) thread 1
-[Switching to thread 1 (Thread 0x7f6f4f1aa8a0 (LWP 13792))]#0 0x00007f6f4949e5a9 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
-(gdb) bt
-#0 0x00007f6f4949e5a9 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
-#1 0x00007f6f4ecc7669 in boost::thread::join() () from /usr/lib/libboost_thread.so.1.40.0 // Waiting for audio thread (thread 3) to terminate
-#2 0x00007f6f3d980f09 in ~alsa_playback (this=0x218e770, __in_chrg=<value optimized out>) at /home/tronic/performous/libs/libda/plugins/audio_dev_alsa.cpp:194
-#3 0x000000000048e68d in da::mixer::~mixer() ()
-#4 0x00000000004ffad8 in Audio::~Audio() ()
-#5 0x00000000004f7e73 in mainLoop (songlist=<value optimized out>) at /home/tronic/performous/game/main.cc:179
-#6 0x00000000004f9a9d in main (argc=<value optimized out>, argv=<value optimized out>) at /home/tronic/performous/game/main.cc:290
-(gdb) thread 3
-[Switching to thread 3 (Thread 0x7f6f3c65d910 (LWP 13794))]#0 0x00007f6f494a0c34 in __lll_lock_wait () from /lib/libpthread.so.0
-(gdb) bt
-#0 0x00007f6f494a0c34 in __lll_lock_wait () from /lib/libpthread.so.0
-#1 0x00007f6f4949c2b0 in _L_lock_1022 () from /lib/libpthread.so.0
-#2 0x00007f6f4949c111 in pthread_mutex_lock () from /lib/libpthread.so.0
-#3 0x000000000048c253 in boost::unique_lock<boost::recursive_mutex>::unique_lock(boost::recursive_mutex&) () // Mixer lock?
-#4 0x000000000048cad5 in boost::detail::function::function_ref_invoker1<da::mutex_stream, bool, da::pcm_data&>::invoke(boost::detail::function::function_buffer&, da::pcm_data&) ()
-#5 0x000000000048bd3e in boost::function1<bool, da::pcm_data&>::operator()(da::pcm_data&) const ()
-#6 0x00007f6f3d97fddb in operator() (this=0x218e770) at /home/tronic/performous/libs/libda/plugins/audio_dev_alsa.cpp:205
-#7 0x00007f6f4ecc6db0 in thread_proxy () from /usr/lib/libboost_thread.so.1.40.0
-#8 0x00007f6f49499a04 in start_thread () from /lib/libpthread.so.0
-#9 0x00007f6f492037bd in clone () from /lib/libc.so.6
-#10 0x0000000000000000 in ?? ()
+
+- Segfault when browsing songs in song browser while loading (segfaults before loading finishes), quite rare
- Bitmap surfaces are often loaded only partially, loading stops at a middle of a scanline.
* Affects at least PNG format, maybe not others
|
|
From: Tapio V. <aa...@us...> - 2010-01-14 20:14:47
|
Module: performous
Branch: master
Commit: a20690da7f20887e147fc899b0dbf78e219a3c00
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 14 22:11:08 2010 +0200
Fix issue with sometimes not being able to hit dance notes near holds.
---
game/dancegraph.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/game/dancegraph.cc b/game/dancegraph.cc
index 3d158f1..ad78a3b 100644
--- a/game/dancegraph.cc
+++ b/game/dancegraph.cc
@@ -284,8 +284,8 @@ void DanceGraph::dance(double time, input::Event const& ev) {
}
std::cout << "Hit button " << ev.button << " at " << time << std::endl;
- for (DanceNotes::iterator it = m_notesIt; it != m_notes.end() && time <= it->note.begin + maxTolerance; it++) {
- if(!it->isHit && time >= it->note.begin - maxTolerance && ev.button == it->note.note) {
+ for (DanceNotes::iterator it = m_notesIt; it != m_notes.end() && time <= it->note.end + maxTolerance; it++) {
+ if(!it->isHit && std::abs(time - it->note.begin) <= maxTolerance && ev.button == it->note.note) {
it->isHit = true;
if (it->note.type != Note::MINE) {
it->score = points(it->note.begin - time);
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 19:51:39
|
Module: performous
Branch: master
Commit: 67cb0bac11862b07e0678af141d5ee400d73b29f
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 21:51:10 2010 +0200
Indication of early/late danced notes + tiny adjustment to scale
---
game/dancegraph.cc | 51 ++++++++++++++++++++++++++++++---------------------
game/dancegraph.hh | 4 ++--
2 files changed, 32 insertions(+), 23 deletions(-)
diff --git a/game/dancegraph.cc b/game/dancegraph.cc
index d80c147..3d158f1 100644
--- a/game/dancegraph.cc
+++ b/game/dancegraph.cc
@@ -25,31 +25,41 @@ namespace {
float y2a(float y) { return time2a(past - y / timescale * (future - past)); }
const double maxTolerance = 0.15;
int getNextBigStreak(int prev) { return prev + 10; }
-
+
+ /// Get an accuracy value [0, 1] for the error offset (in seconds)
+ double accuracy(double error) { return 1.0 - (std::abs(error) / maxTolerance); };
+
/// Gives points based on error from a perfect hit
double points(double error) {
- error = (error < 0.0) ? -error : error;
- double ac = 1.0 - error / maxTolerance;
+ double ac = accuracy(error);
if (ac > .90) return 50.0; // Perfect
if (ac > .80) return 40.0; // Excellent
if (ac > .70) return 30.0; // Great
- if (ac > .60) return 25.0; // Good
- if (ac > .50) return 20.0; // OK
- if (ac > .40) return 15.0; // Poor
- if (ac > .30) return 10.0; // Bad
- if (ac > 0.0) return 5.0; // Horrible
- return 0.0;
+ if (ac > .60) return 20.0; // Good
+ if (ac > .40) return 15.0; // OK
+ if (ac > .20) return 10.0; // Late/Early
+ return 5.0; // Way off
}
- std::string getRank(double ac) {
- if (ac > .90) return "Perfect!";
- if (ac > .80) return "Excellent!";
- if (ac > .70) return "Great!";
- if (ac > .60) return "Good!";
- if (ac > .50) return " OK! ";
- if (ac > .40) return "Poor!";
- if (ac > .30) return " Bad! ";
- return "Horrible!";
+ std::string getRank(double error) {
+ double ac = accuracy(error);
+ if (error < 0.0) {
+ if (ac > .90) return "Perfect!";
+ if (ac > .80) return "Excellent!-";
+ if (ac > .70) return "Great!-";
+ if (ac > .60) return " Good!- ";
+ if (ac > .40) return " OK!- ";
+ if (ac > .20) return "Late!-";
+ return "Way off!";
+ } else {
+ if (ac > .90) return "Perfect!";
+ if (ac > .80) return "-Excellent!";
+ if (ac > .70) return "-Great!";
+ if (ac > .60) return " -Good! ";
+ if (ac > .40) return " -OK! ";
+ if (ac > .20) return "-Early!";
+ return "Way off!";
+ }
}
struct lessEnd {
@@ -279,7 +289,7 @@ void DanceGraph::dance(double time, input::Event const& ev) {
it->isHit = true;
if (it->note.type != Note::MINE) {
it->score = points(it->note.begin - time);
- it->accuracy = 1.0 - (std::abs(it->note.begin - time) / maxTolerance);
+ it->error = it->note.begin - time;
m_streak++;
if (m_streak > m_longestStreak) m_longestStreak = m_streak;
} else { // Mine!
@@ -411,7 +421,6 @@ void DanceGraph::drawNote(DanceNote& note, double time) {
bool mine = note.note.type == Note::MINE;
float x = panel2x(arrow_i);
float s = 1.0;
- float ac = note.accuracy;
float yBeg = time2y(tBeg);
float yEnd = time2y(tEnd);
glutil::Color c(1.0f, 1.0f, 1.0f);
@@ -469,7 +478,7 @@ void DanceGraph::drawNote(DanceNote& note, double time) {
text = "HOLD";
glow = 1.0;
} else if (glow > 0.0) { // Released already, display rank
- text = getRank(ac);
+ text = getRank(note.error);
}
if (!text.empty()) {
glColor3f(1.0f, 1.0f, 1.0f);
diff --git a/game/dancegraph.hh b/game/dancegraph.hh
index 17e2954..fbd39cf 100644
--- a/game/dancegraph.hh
+++ b/game/dancegraph.hh
@@ -14,11 +14,11 @@ class Song;
struct DanceNote {
DanceNote(Note note) :
- note(note), hitAnim(0.0, 5.0), releaseTime(0), accuracy(0), score(0), isHit(false) {}
+ note(note), hitAnim(0.0, 5.0), releaseTime(0), error(getNaN()), score(0), isHit(false) {}
Note note;
AnimValue hitAnim; /// for animating hits
double releaseTime; /// tells when a hold was ended
- float accuracy; /// how accurate the hit was [0,1]
+ double error; /// time difference between hit and correct time (negative = late)
int score;
bool isHit;
};
|
|
From: Tapio V. <aa...@us...> - 2010-01-14 17:47:43
|
Module: performous
Branch: master
Commit: 016d2ef2672d7fc4253ab002565e7dd1d46d4932
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 14 19:47:00 2010 +0200
Added support for Mad Catz Portable Drum Kit.
---
game/joystick.cc | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/game/joystick.cc b/game/joystick.cc
index 638cc1d..4a1196a 100644
--- a/game/joystick.cc
+++ b/game/joystick.cc
@@ -292,6 +292,9 @@ void input::SDL::init() {
std::cout << " Detected as: RockBand Drums PS3" << std::endl;
input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB_PS3);
}
+ } else if( name.find("Mad Catz Portable Drum") != std::string::npos) {
+ std::cout << " Detected as: RockBand Drums Xbox360" << std::endl;
+ input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB_XB360);
} else if( name.find("RedOctane USB Pad") != std::string::npos ) {
std::cout << " Detected as: Generic Dance Pad" << std::endl;
input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DANCEPAD_GENERIC);
|
|
From: Tapio V. <aa...@us...> - 2010-01-14 16:52:13
|
Module: performous
Branch: master
Commit: 8e76958d4ce005daa71faf72e52bfc9d845da584
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 14 18:48:00 2010 +0200
Different mappings for PS3/Xbox360 Rock Band instruments.
At least Select/Start/Whammy/Tilt are still b0rked.
---
data/schema.xml | 2 +-
game/joystick.cc | 74 +++++++++++++++++++++++++++++++++++------------------
game/joystick.hh | 9 ++++--
3 files changed, 56 insertions(+), 29 deletions(-)
diff --git a/data/schema.xml b/data/schema.xml
index a7312ea..6548b2a 100644
--- a/data/schema.xml
+++ b/data/schema.xml
@@ -85,7 +85,7 @@ to save the current settings to XML.
</locale>
</entry>
<entry name="game/instruments" type="string_list">
- <!-- Should be SDL_ID:{GUITAR_GUITARHERO|GUITAR_GUITARHERO_XPLORER|GUITAR_ROCKBAND|DRUMS_GUITARHERO|DRUMS_ROCKBAND|DRUMS_MIDI|DANCEPAD_GENERIC}
+ <!-- Should be SDL_ID:{GUITAR_GUITARHERO|GUITAR_GUITARHERO_XPLORER|GUITAR_ROCKBAND_PS3|GUITAR_ROCKBAND_XB360|DRUMS_GUITARHERO|DRUMS_ROCKBAND_PS3|DRUMS_ROCKBAND_XB360|DRUMS_MIDI|DANCEPAD_GENERIC}
example:
<stringvalue>0:GUITAR_GUITARHERO</stringvalue>
-->
diff --git a/game/joystick.cc b/game/joystick.cc
index 77f3401..638cc1d 100644
--- a/game/joystick.cc
+++ b/game/joystick.cc
@@ -38,14 +38,16 @@ void input::MidiDrums::process() {
static const unsigned SDL_BUTTONS = 10;
int input::buttonFromSDL(input::Private::Type _type, unsigned int _sdl_button) {
- static const int inputmap[6][SDL_BUTTONS] = {
+ static const int inputmap[8][SDL_BUTTONS] = {
//G R Y B O S // for guitars (S=starpower)
{ 2, 0, 1, 3, 4, 5, -1, -1, 8, 9 }, // Guitar Hero guitar
{ 0, 1, 3, 2, 4,-1, 8, 9,-1,-1 }, // Guitar Hero X-plorer guitar
- { 3, 0, 1, 2, 4, 5, -1, -1, 8, 9 }, // Rock Band guitar
+ { 3, 0, 1, 2, 4, 5, -1, -1, 8, 9 }, // Rock Band guitar PS3
+ { 0, 1, 3, 2, 4, 5, -1, -1, 8, 9 }, // Rock Band guitar XBOX360
//K R Y B G O // for drums
{ 3, 4, 1, 2, 0, 4, -1, -1, 8, 9 }, // Guitar Hero drums
- { 3, 4, 1, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums
+ { 3, 4, 1, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums PS3
+ { 4, 1, 3, 2, 0,-1, -1, -1, 8, 9 }, // Rock Band drums XBOX360
// Left Down Up Right DownL DownR UpL UpR Start Select
{ 0, 1, 2, 3, 6, 7, 4, 5, 9, 8 } // generic dance pad
};
@@ -55,14 +57,18 @@ int input::buttonFromSDL(input::Private::Type _type, unsigned int _sdl_button) {
return inputmap[0][_sdl_button];
case input::Private::GUITAR_GH_XPLORER:
return inputmap[1][_sdl_button];
- case input::Private::GUITAR_RB:
+ case input::Private::GUITAR_RB_PS3:
return inputmap[2][_sdl_button];
- case input::Private::DRUMS_GH:
+ case input::Private::GUITAR_RB_XB360:
return inputmap[3][_sdl_button];
- case input::Private::DRUMS_RB:
+ case input::Private::DRUMS_GH:
return inputmap[4][_sdl_button];
- case input::Private::DANCEPAD_GENERIC:
+ case input::Private::DRUMS_RB_PS3:
return inputmap[5][_sdl_button];
+ case input::Private::DRUMS_RB_XB360:
+ return inputmap[6][_sdl_button];
+ case input::Private::DANCEPAD_GENERIC:
+ return inputmap[7][_sdl_button];
default:
return -1;
}
@@ -180,8 +186,9 @@ void input::SDL::init() {
std::map<unsigned int, input::Private::Type> forced_type;
using namespace boost::spirit::classic;
- rule<> type = str_p("GUITAR_GUITARHERO") | "GUITAR_ROCKBAND" | "GUITAR_GUITARHERO_XPLORER"
- | "DRUMS_GUITARHERO" | "DRUMS_ROCKBAND" | "DRUMS_MIDI" | "DANCEPAD_GENERIC";
+ rule<> type = str_p("GUITAR_GUITARHERO") | "GUITAR_ROCKBAND_PS3" | "GUITAR_ROCKBAND_XB360"
+ | "GUITAR_GUITARHERO_XPLORER" | "DRUMS_GUITARHERO" | "DRUMS_ROCKBAND_PS3" | "DRUMS_ROCKBAND_XB360"
+ | "DRUMS_MIDI" | "DANCEPAD_GENERIC";
rule<> entry = uint_p[assign_a(sdl_id)] >> ":" >> (type)[assign_a(instrument_type)];
ConfigItem::StringList const& instruments = config["game/instruments"].sl();
@@ -196,10 +203,14 @@ void input::SDL::init() {
forced_type[sdl_id] = input::Private::GUITAR_GH_XPLORER;
} else if (instrument_type == "DRUMS_GUITARHERO") {
forced_type[sdl_id] = input::Private::DRUMS_GH;
- } else if (instrument_type == "GUITAR_ROCKBAND") {
- forced_type[sdl_id] = input::Private::GUITAR_RB;
- } else if (instrument_type == "DRUMS_ROCKBAND") {
- forced_type[sdl_id] = input::Private::DRUMS_RB;
+ } else if (instrument_type == "GUITAR_ROCKBAND_PS3") {
+ forced_type[sdl_id] = input::Private::GUITAR_RB_PS3;
+ } else if (instrument_type == "GUITAR_ROCKBAND_XB360") {
+ forced_type[sdl_id] = input::Private::GUITAR_RB_XB360;
+ } else if (instrument_type == "DRUMS_ROCKBAND_PS3") {
+ forced_type[sdl_id] = input::Private::DRUMS_RB_PS3;
+ } else if (instrument_type == "DRUMS_ROCKBAND_XB360") {
+ forced_type[sdl_id] = input::Private::DRUMS_RB_XB360;
} else if (instrument_type == "DRUMS_MIDI") {
forced_type[sdl_id] = input::Private::DRUMS_MIDI;
} else if (instrument_type == "DANCEPAD_GENERIC") {
@@ -235,11 +246,17 @@ void input::SDL::init() {
case input::Private::DRUMS_GH:
std::cout << " Detected as: Guitar Hero Drums (forced)" << std::endl;
break;
- case input::Private::GUITAR_RB:
- std::cout << " Detected as: RockBand Guitar (forced)" << std::endl;
+ case input::Private::GUITAR_RB_PS3:
+ std::cout << " Detected as: RockBand Guitar PS3 (forced)" << std::endl;
+ break;
+ case input::Private::GUITAR_RB_XB360:
+ std::cout << " Detected as: RockBand Guitar Xbox360 (forced)" << std::endl;
break;
- case input::Private::DRUMS_RB:
- std::cout << " Detected as: RockBand Drums (forced)" << std::endl;
+ case input::Private::DRUMS_RB_PS3:
+ std::cout << " Detected as: RockBand Drums PS3 (forced)" << std::endl;
+ break;
+ case input::Private::DRUMS_RB_XB360:
+ std::cout << " Detected as: RockBand Drums Xbox360 (forced)" << std::endl;
break;
case input::Private::DRUMS_MIDI:
std::cout << " Detected as: MIDI Drums (forced)" << std::endl;
@@ -260,14 +277,21 @@ void input::SDL::init() {
std::cout << " Detected as: Guitar Hero Drums (guessed)" << std::endl;
input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_GH);
} else if( name.find("Harmonix Guitar") != std::string::npos ) {
- std::cout << " Detected as: RockBand Guitar" << std::endl;
- input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::GUITAR_RB);
- } else if( name.find("Harmonix Drum Kit") != std::string::npos ) {
- std::cout << " Detected as: RockBand Drums" << std::endl;
- input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB);
- } else if( name.find("Harmonix Drum kit") != std::string::npos ) {
- std::cout << " Detected as: RockBand Drums" << std::endl;
- input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB);
+ if (name.find("Xbox") != std::string::npos) {
+ std::cout << " Detected as: RockBand Guitar Xbox360" << std::endl;
+ input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::GUITAR_RB_XB360);
+ } else {
+ std::cout << " Detected as: RockBand Guitar PS3" << std::endl;
+ input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::GUITAR_RB_PS3);
+ }
+ } else if( name.find("Harmonix Drum Kit") != std::string::npos || name.find("Harmonix Drum kit") != std::string::npos) {
+ if (name.find("Xbox") != std::string::npos) {
+ std::cout << " Detected as: RockBand Drums Xbox360" << std::endl;
+ input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB_XB360);
+ } else {
+ std::cout << " Detected as: RockBand Drums PS3" << std::endl;
+ input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DRUMS_RB_PS3);
+ }
} else if( name.find("RedOctane USB Pad") != std::string::npos ) {
std::cout << " Detected as: Generic Dance Pad" << std::endl;
input::Private::devices[i] = input::Private::InputDevPrivate(input::Private::DANCEPAD_GENERIC);
diff --git a/game/joystick.hh b/game/joystick.hh
index 20a2188..8c4bcdf 100644
--- a/game/joystick.hh
+++ b/game/joystick.hh
@@ -32,7 +32,8 @@ namespace input {
};
namespace Private {
- enum Type { GUITAR_RB, DRUMS_RB, GUITAR_GH, GUITAR_GH_XPLORER, DRUMS_GH, DRUMS_MIDI, DANCEPAD_GENERIC };
+ enum Type { GUITAR_RB_PS3, DRUMS_RB_PS3, GUITAR_RB_XB360, DRUMS_RB_XB360,
+ GUITAR_GH, GUITAR_GH_XPLORER, DRUMS_GH, DRUMS_MIDI, DANCEPAD_GENERIC };
static unsigned int KEYBOARD_ID = UINT_MAX;
static unsigned int KEYBOARD_ID2 = KEYBOARD_ID-1;
static unsigned int KEYBOARD_ID3 = KEYBOARD_ID-2; // Three ids needed for keyboard guitar/drumkit/dancepad
@@ -79,11 +80,13 @@ namespace input {
input::Private::Type type() {return m_type;};
bool type_match( input::DevType _type) {
if( _type == input::GUITAR &&
- (m_type == input::Private::GUITAR_GH || m_type == input::Private::GUITAR_GH_XPLORER || m_type == input::Private::GUITAR_RB) ) {
+ (m_type == input::Private::GUITAR_GH || m_type == input::Private::GUITAR_GH_XPLORER
+ || m_type == input::Private::GUITAR_RB_PS3 || m_type == input::Private::GUITAR_RB_XB360) ) {
return true;
}
else if( _type == input::DRUMS &&
- (m_type == input::Private::DRUMS_GH || m_type == input::Private::DRUMS_RB || m_type == input::Private::DRUMS_MIDI) ) {
+ (m_type == input::Private::DRUMS_GH || m_type == input::Private::DRUMS_MIDI
+ || m_type == input::Private::DRUMS_RB_PS3 || m_type == input::Private::DRUMS_RB_XB360) ) {
return true;
}
else if( _type == input::DANCEPAD &&
|
|
From: Tapio V. <aa...@us...> - 2010-01-14 16:52:09
|
Module: performous
Branch: master
Commit: 297185a889a66b98d2593dfde437dd09a6ff1ffd
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 14 17:48:24 2010 +0200
Added a simple joystick button utility: --jstest
---
game/main.cc | 40 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/game/main.cc b/game/main.cc
index 7c0b9e8..57f42ea 100644
--- a/game/main.cc
+++ b/game/main.cc
@@ -193,6 +193,37 @@ void mainLoop(std::string const& songlist) {
}
}
+/// Simple test utility to make mapping of joystick buttons/axes easier
+void jstestLoop() {
+ try {
+ Window window(config["graphic/window_width"].i(), config["graphic/window_height"].i(), false);
+ // Main loop
+ boost::xtime time = now();
+ while (true) {
+ SDL_Event e;
+ while(SDL_PollEvent(&e) == 1) {
+ if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) {
+ return;
+ } else if (e.type == SDL_JOYBUTTONDOWN) {
+ std::cout << "JoyID: " << int(e.jbutton.which) << ", button: " << int(e.jbutton.button) << ", state: " << int(e.jbutton.state) << std::endl;
+ } else if (e.type == SDL_JOYAXISMOTION) {
+ std::cout << "JoyID: " << int(e.jaxis.which) << ", axis: " << int(e.jaxis.axis) << ", value: " << int(e.jaxis.value) << std::endl;
+ } else if (e.type == SDL_JOYHATMOTION) {
+ std::cout << "JoyID: " << int(e.jhat.which) << ", hat: " << int(e.jhat.hat) << ", value: " << int(e.jhat.value) << std::endl;
+ }
+ }
+ window.blank(); window.swap();
+ boost::thread::sleep(time + 0.01); // Max 100 FPS
+ time = now();
+ }
+ } catch (std::exception& e) {
+ std::cout << "ERROR: " << e.what() << std::endl;
+ } catch (QuitNow&) {
+ std::cout << "Terminated." << std::endl;
+ }
+ return;
+}
+
template <typename Container> void confOverride(Container const& c, std::string const& name) {
if (c.empty()) return; // Don't override if no options specified
ConfigItem::StringList& sl = config[name].sl();
@@ -234,7 +265,8 @@ int main(int argc, char** argv) {
("mics", po::value<std::vector<std::string> >(&mics)->composing(), "specify the microphones to use")
("pdev", po::value<std::vector<std::string> >(&pdevs)->composing(), "specify the playback device")
("michelp", "detailed help and device list for --mics")
- ("pdevhelp", "detailed help and device list for --pdev");
+ ("pdevhelp", "detailed help and device list for --pdev")
+ ("jstest", "utility to get joystick button mappings");
po::options_description opt3("Hidden options");
opt3.add_options()
("songdir", po::value<std::vector<std::string> >(&songdirs)->composing(), "");
@@ -309,6 +341,12 @@ int main(int argc, char** argv) {
confOverride(mics, "audio/capture");
confOverride(pdevs, "audio/playback");
getPaths(); // Initialize paths before other threads start
+ if (vm.count("jstest")) { // Joystick test program
+ std::cout << std::endl << "Joystick utility - Touch your joystick to see buttons here" << std::endl
+ << "Hit ESC (window focused) to quit" << std::endl << std::endl;
+ jstestLoop();
+ return 0;
+ }
// Run the game init and main loop
mainLoop(songlist);
return 0; // Do not remove. SDL_Main (which this function is called on some platforms) needs return statement.
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 16:17:54
|
Module: performous
Branch: master
Commit: 8bbd0ef0bd97e99b129069e0abe248a0ba552fe2
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 18:17:23 2010 +0200
Advanced audio sync correction
---
game/audio.hh | 35 +++++++++++++++++++++++++++++++----
1 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/game/audio.hh b/game/audio.hh
index 1c2b342..ee837b4 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -22,10 +22,10 @@ struct Stream {
double fade; ///< Fade level
/// constructor
Stream(std::string const& filename, unsigned int sr):
- mpeg(false, true, filename, sr), srate(sr), fade(1.0), m_time(getTime()), m_pos() {}
+ mpeg(false, true, filename, sr), srate(sr), fade(1.0), m_time(getTime()), m_syncTime(m_time), m_correction(), m_pos() {}
/// crossfades songs
bool operator()(da::pcm_data& data) {
- m_time = getTime();
+ timeSync(); // Keep audio synced
if (fade == 1.0) {
mpeg.audioQueue(data, m_pos);
} else {
@@ -39,12 +39,39 @@ struct Stream {
return !eof();
}
void seek(double time) { m_pos = time * srate * 2.0; }
- double pos() const { return double(m_pos) / srate / 2.0 + (getTime() - m_time).total_microseconds() * 1e-6; }
+ /// Get current position in seconds (with corrections applied)
+ double pos() const {
+ boost::posix_time::ptime now = getTime();
+ double delay = seconds(now - m_syncTime); // Since last sync
+ // If more than 100 ms since last sync, freeze time to m_syncTime instead of realtime
+ // In either case, return the clock + correction
+ return seconds((delay > 0.1 ? m_syncTime : now) - m_time) + m_correction;
+ }
double duration() const { return mpeg.audioQueue.duration(); }
bool eof() const { return mpeg.audioQueue.eof(m_pos); }
private:
static boost::posix_time::ptime getTime() { return boost::posix_time::microsec_clock::universal_time(); }
- boost::posix_time::ptime m_time; ///< Audio time at last frame
+ double pos_internal() const { return double(m_pos) / srate / 2.0; }
+ double seconds(boost::posix_time::time_duration const& d) const { return 1e-6 * d.total_microseconds(); }
+ /// Adjust sync, duration of the audio
+ void timeSync() {
+ boost::posix_time::ptime now = getTime();
+ double t = seconds(now - m_time) + m_correction;
+ double duration = seconds(now - m_syncTime);
+ double diff = t - pos_internal();
+ m_syncTime = now;
+ if (duration < 0.0 || duration > 1.0) return; // No syncing for weird situations
+ if (std::abs(diff) < 0.1 * duration) {
+ // Apply 1 % adjustment either up or down
+ m_correction += (diff > 0.0 ? -1.0 : 1.0) * 0.01 * duration;
+ } else {
+ // Stepped adjustment to the right time (e.g. after seeking)
+ m_correction -= diff;
+ }
+ }
+ boost::posix_time::ptime m_time; ///< The base time (time at the beginning)
+ boost::posix_time::ptime m_syncTime; ///< Time of the previous audio timeSync
+ double m_correction; ///< Offset added to system time to get audio time
int64_t m_pos; ///< Current sample position
};
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 16:17:51
|
Module: performous
Branch: master
Commit: d0d8cbca861c8fa60a0ba61ca0b529f59f15080c
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 15:37:51 2010 +0200
Simple correction of audio clock by system clock (has glitches)
---
game/audio.hh | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/game/audio.hh b/game/audio.hh
index 95537fc..1c2b342 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -6,6 +6,7 @@
#include "ffmpeg.hh"
#include "notes.hh"
+#include <boost/date_time.hpp>
#include <boost/shared_ptr.hpp>
#include <libda/mixer.hpp>
@@ -16,15 +17,15 @@ using boost::int64_t;
/** allows buffering, fading and mixing of audiostreams
*/
struct Stream {
- /// container for the media file
- FFmpeg mpeg;
- /// sample rate
- double srate;
+ FFmpeg mpeg; ///< Audio stream
+ double srate; ///< Sample rate
+ double fade; ///< Fade level
/// constructor
Stream(std::string const& filename, unsigned int sr):
- mpeg(false, true, filename, sr), srate(sr), m_pos(), fade(1.0) {}
+ mpeg(false, true, filename, sr), srate(sr), fade(1.0), m_time(getTime()), m_pos() {}
/// crossfades songs
bool operator()(da::pcm_data& data) {
+ m_time = getTime();
if (fade == 1.0) {
mpeg.audioQueue(data, m_pos);
} else {
@@ -38,11 +39,13 @@ struct Stream {
return !eof();
}
void seek(double time) { m_pos = time * srate * 2.0; }
- double pos() const { return double(m_pos) / srate / 2.0; }
+ double pos() const { return double(m_pos) / srate / 2.0 + (getTime() - m_time).total_microseconds() * 1e-6; }
double duration() const { return mpeg.audioQueue.duration(); }
bool eof() const { return mpeg.audioQueue.eof(m_pos); }
- int64_t m_pos;
- double fade;
+private:
+ static boost::posix_time::ptime getTime() { return boost::posix_time::microsec_clock::universal_time(); }
+ boost::posix_time::ptime m_time; ///< Audio time at last frame
+ int64_t m_pos; ///< Current sample position
};
struct Sample {
|
|
From: Tapio V. <aa...@us...> - 2010-01-14 14:41:45
|
Module: performous
Branch: master
Commit: d9350d5cb7ff18bc288880b4feeb12ca7a259fef
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 14 14:31:38 2010 +0200
Change notelines.svg font to Arial for Windows compatibility.
---
themes/default/notelines.svg | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/themes/default/notelines.svg b/themes/default/notelines.svg
index 92de2a4..ab3c600 100644
--- a/themes/default/notelines.svg
+++ b/themes/default/notelines.svg
@@ -86,7 +86,7 @@
id="layer1">
<text
xml:space="preserve"
- style="font-size:17.21700287px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:justify;line-height:125%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold"
+ style="font-size:17.21700287px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:justify;line-height:125%;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial"
x="357.41422"
y="13.133085"
id="text2160"
@@ -96,62 +96,62 @@
id="tspan2162"
x="357.41422"
y="13.133085"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">B</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">B</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="30.350092"
id="tspan2164"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">A#</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">A#</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="47.567101"
id="tspan2166"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">A</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">A</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="64.784103"
id="tspan2168"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">G#</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">G#</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="82.001106"
id="tspan2170"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">G</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">G</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="99.218117"
id="tspan2172"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">F#</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">F#</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="116.43513"
id="tspan2174"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">F</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">F</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="133.65213"
id="tspan2176"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">E</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">E</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="150.86914"
id="tspan2178"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">D#</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">D#</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="168.08615"
id="tspan2180"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">D</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">D</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="185.30315"
id="tspan2182"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">C#</tspan><tspan
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#808080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">C#</tspan><tspan
sodipodi:role="line"
x="357.41422"
y="202.52016"
id="tspan2184"
- style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;text-anchor:start;fill:#800080;fill-opacity:1;font-family:Liberation Mono;-inkscape-font-specification:Liberation Mono Bold">C</tspan></text>
+ style="font-size:13.77360535px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;text-anchor:start;fill:#800080;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">C</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#808080;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196078000000000"
d="M 0.0074350522,10.699792 L 286.76721,10.699792"
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 02:53:16
|
Module: performous
Branch: master
Commit: 5bd9676a9fb1f1b197e594bd4127caf112506f8a
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 04:52:44 2010 +0200
Simplified song shuffling. Set position at first song when the song browser entered the first time.
---
game/screen_songs.cc | 1 -
game/songs.cc | 32 +++++---------------------------
game/songs.hh | 5 -----
3 files changed, 5 insertions(+), 33 deletions(-)
diff --git a/game/screen_songs.cc b/game/screen_songs.cc
index d495486..ecc3719 100644
--- a/game/screen_songs.cc
+++ b/game/screen_songs.cc
@@ -96,7 +96,6 @@ void ScreenSongs::manageEvent(SDL_Event event) {
// The rest are only available when there are songs available
else if (m_songs.empty()) return;
else if (!m_jukebox && key == SDLK_F4) m_jukebox = true;
- else if (key == SDLK_TAB && !(mod & KMOD_ALT)) m_songs.randomize();
else if (key == SDLK_END) {
ScreenManager* sm = ScreenManager::getSingletonPtr();
Screen* s = sm->getScreen("Hiscore");
diff --git a/game/songs.cc b/game/songs.cc
index 033d2f6..eb1ced2 100644
--- a/game/songs.cc
+++ b/game/songs.cc
@@ -16,7 +16,7 @@
#include <stdexcept>
#include <cstdlib>
-Songs::Songs(Database & database, std::string const& songlist): m_songlist(songlist), math_cover(), m_database(database), m_order(), m_dirty(false), m_loading(false), m_needShuffle(false) {
+Songs::Songs(Database & database, std::string const& songlist): m_songlist(songlist), math_cover(), m_database(database), m_order(), m_dirty(false), m_loading(false) {
reload();
}
@@ -28,7 +28,6 @@ Songs::~Songs() {
void Songs::reload() {
if (m_loading) return;
// Run loading thread
- m_needShuffle = false;
m_loading = true;
m_thread.reset(new boost::thread(boost::bind(&Songs::reload_internal, boost::ref(*this))));
}
@@ -50,11 +49,9 @@ void Songs::reload_internal() {
}
if (m_loading) dumpSongs_internal(); // Dump the songlist to file (if requested)
m_loading = false;
- m_needShuffle = true; // Force shuffle
}
void Songs::reload_internal(fs::path const& parent) {
- static int randomIdx = 0;
namespace fs = fs;
if (std::distance(parent.begin(), parent.end()) > 20) { m_debug << ">>> Not scanning: " << parent.string() << " (maximum depth reached, possibly due to cyclic symlinks)" << std::endl; return; }
try {
@@ -69,7 +66,7 @@ void Songs::reload_internal(fs::path const& parent) {
if (!regex_match(name.c_str(), match, expression)) continue;
try {
boost::shared_ptr<Song>s(new Song(path, name));
- s->randomIdx = ++randomIdx; // Not so random during loading, they are shuffled after load is finished
+ s->randomIdx = rand();
boost::mutex::scoped_lock l(m_mutex);
m_songs.push_back(s);
m_dirty = true;
@@ -112,28 +109,9 @@ class Songs::RestoreSel {
void Songs::update() {
if (m_dirty) filter_internal(); // Update with newly loaded songs
- if (m_needShuffle) randomize(); // Shuffle the songlist if needed
-}
-
-void Songs::randomize() {
- RestoreSel restore(*this);
- randomize_internal();
-}
-
-void Songs::randomize_internal() {
- boost::mutex::scoped_lock l(m_mutex);
- m_needShuffle = false;
- /* TR1-based random number generation
- TODO: it is enough that random_device is initialized once and not for every randomize_internal
- namespace rnd = std::tr1;
- rnd::random_device gendev; // Random number generator (using /dev/urandom usually)
- rnd::mt19937 gen(gendev); // Make Mersenne Twister random number generator, seeded with random_device.
- for (SongVector::const_iterator it = m_filtered.begin(); it != m_filtered.end(); ++it) (*it)->randomIdx = gen();
- */
- // Assign the songs randomIdx that is used for sorting in the "random" mode
- for (SongVector::const_iterator it = m_songs.begin(); it != m_songs.end(); ++it) (*it)->randomIdx = std::rand();
- m_order = 0; // Use randomIdx sort mode
- sort_internal();
+ // A hack to move to the first song when the song screen is entered the first time
+ static bool first = true;
+ if (first) { first = false; math_cover.setTarget(0, 0); math_cover.setTarget(0, size()); }
}
void Songs::setFilter(std::string const& val) {
diff --git a/game/songs.hh b/game/songs.hh
index faf974d..c49deac 100644
--- a/game/songs.hh
+++ b/game/songs.hh
@@ -55,10 +55,6 @@ class Songs: boost::noncopyable {
void setFilter(std::string const& regex);
/// sort descending
std::string sortDesc() const;
- /// randomizes songlist
- void randomize();
- /// randomizes if ordered
- void random() { if (m_order) randomize(); advance(1); }
/// changes sorting
void sortChange(int diff);
/// parses file into Song &tmp
@@ -81,7 +77,6 @@ class Songs: boost::noncopyable {
void sort_internal();
volatile bool m_dirty;
volatile bool m_loading;
- volatile bool m_needShuffle;
std::stringstream m_debug;
boost::scoped_ptr<boost::thread> m_thread;
mutable boost::mutex m_mutex;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 02:53:14
|
Module: performous
Branch: master
Commit: 70180ea11247a3a1fe78fe9aa05c2a802e6c92b4
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 04:36:51 2010 +0200
Thread-safe song loader messages
---
game/midifile.cc | 6 ++----
game/songs.cc | 26 ++++++++++++++------------
game/songs.hh | 2 ++
3 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/game/midifile.cc b/game/midifile.cc
index 8ce7226..7141d91 100644
--- a/game/midifile.cc
+++ b/game/midifile.cc
@@ -3,15 +3,13 @@
#include <algorithm>
#include <fstream>
#include <iomanip>
+#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
-#define MIDI_DEBUG_LEVEL 1
+#define MIDI_DEBUG_LEVEL 0
-#if MIDI_DEBUG_LEVEL > 0
-#include <iostream>
-#endif
/**
* @short The MidiStream class reads midifile for MidiFileParser.
diff --git a/game/songs.cc b/game/songs.cc
index 9d5e499..033d2f6 100644
--- a/game/songs.cc
+++ b/game/songs.cc
@@ -13,7 +13,6 @@
#include <libxml++/libxml++.h>
#include <algorithm>
#include <iostream>
-#include <sstream>
#include <stdexcept>
#include <cstdlib>
@@ -42,12 +41,12 @@ void Songs::reload_internal() {
}
Paths paths = getPathsConfig("system/path_songs");
for (Paths::iterator it = paths.begin(); m_loading && it != paths.end(); ++it) {
- if (!fs::is_directory(*it)) { std::cout << ">>> Not scanning: " << *it << " (no such directory)" << std::endl; continue; }
- std::cout << ">>> Scanning " << *it << std::endl;
+ if (!fs::is_directory(*it)) { m_debug << ">>> Not scanning: " << *it << " (no such directory)" << std::endl; continue; }
+ m_debug << ">>> Scanning " << *it << std::endl;
size_t count = m_songs.size();
reload_internal(*it);
size_t diff = m_songs.size() - count;
- if (diff > 0 && m_loading) std::cout << diff << " songs loaded" << std::endl;
+ if (diff > 0 && m_loading) m_debug << diff << " songs loaded" << std::endl;
}
if (m_loading) dumpSongs_internal(); // Dump the songlist to file (if requested)
m_loading = false;
@@ -57,7 +56,7 @@ void Songs::reload_internal() {
void Songs::reload_internal(fs::path const& parent) {
static int randomIdx = 0;
namespace fs = fs;
- if (std::distance(parent.begin(), parent.end()) > 20) { std::cout << ">>> Not scanning: " << parent.string() << " (maximum depth reached, possibly due to cyclic symlinks)" << std::endl; return; }
+ if (std::distance(parent.begin(), parent.end()) > 20) { m_debug << ">>> Not scanning: " << parent.string() << " (maximum depth reached, possibly due to cyclic symlinks)" << std::endl; return; }
try {
boost::regex expression("(.*\\.txt|^song\\.ini|.*\\.sm)$", boost::regex_constants::icase);
boost::cmatch match;
@@ -76,16 +75,14 @@ void Songs::reload_internal(fs::path const& parent) {
m_dirty = true;
} catch (SongParserException& e) {
if (e.silent()) continue;
- std::ostringstream oss;
- oss << "-!- Error in " << path << "\n " << name;
- if (e.line()) oss << " line " << e.line();
- oss << ": " << e.what() << std::endl;
- std::cerr << oss.str(); // More likely to be atomic when written as one string
+ // Construct error message
+ m_debug << "-!- Error in " << path << "\n " << name;
+ if (e.line()) m_debug << " line " << e.line();
+ m_debug << ": " << e.what() << std::endl;
}
}
} catch (std::exception const& e) {
-
- std::cout << "Error accessing " << parent << e.what() << std::endl;
+ m_debug << "Error accessing " << parent << e.what() << std::endl;
}
}
@@ -147,6 +144,11 @@ void Songs::setFilter(std::string const& val) {
void Songs::filter_internal() {
boost::mutex::scoped_lock l(m_mutex);
+ // Print messages when loading has finished
+ if (!m_loading) {
+ std::cerr << m_debug.str();
+ m_debug.str(""); m_debug.clear();
+ }
m_dirty = false;
RestoreSel restore(*this);
try {
diff --git a/game/songs.hh b/game/songs.hh
index 849709d..faf974d 100644
--- a/game/songs.hh
+++ b/game/songs.hh
@@ -7,6 +7,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <set>
+#include <sstream>
#include <vector>
class Song;
@@ -81,6 +82,7 @@ class Songs: boost::noncopyable {
volatile bool m_dirty;
volatile bool m_loading;
volatile bool m_needShuffle;
+ std::stringstream m_debug;
boost::scoped_ptr<boost::thread> m_thread;
mutable boost::mutex m_mutex;
};
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 02:05:44
|
Module: performous
Branch: master
Commit: f94a5de3503a14071c93c717768ce5479b93a981
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 04:03:13 2010 +0200
Remove --theme (was broken and didn't do anything).
Fix race condition in getPaths initialization by song loader and some other system.
---
game/main.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/game/main.cc b/game/main.cc
index ba91912..7c0b9e8 100644
--- a/game/main.cc
+++ b/game/main.cc
@@ -234,8 +234,7 @@ int main(int argc, char** argv) {
("mics", po::value<std::vector<std::string> >(&mics)->composing(), "specify the microphones to use")
("pdev", po::value<std::vector<std::string> >(&pdevs)->composing(), "specify the playback device")
("michelp", "detailed help and device list for --mics")
- ("pdevhelp", "detailed help and device list for --pdev")
- ("theme", po::value<std::string>(), "set theme (name or absolute path)");
+ ("pdevhelp", "detailed help and device list for --pdev");
po::options_description opt3("Hidden options");
opt3.add_options()
("songdir", po::value<std::vector<std::string> >(&songdirs)->composing(), "");
@@ -309,6 +308,7 @@ int main(int argc, char** argv) {
confOverride(songdirs, "system/path_songs");
confOverride(mics, "audio/capture");
confOverride(pdevs, "audio/playback");
+ getPaths(); // Initialize paths before other threads start
// Run the game init and main loop
mainLoop(songlist);
return 0; // Do not remove. SDL_Main (which this function is called on some platforms) needs return statement.
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 02:05:44
|
Module: performous
Branch: master
Commit: 2d78ab0723dd818f1f029c3849181f1c4c6754a3
Author: Lasse Karkkainen <tro...@tr...>
Date: Thu Jan 14 04:00:55 2010 +0200
Cleanup
---
game/fs.cc | 7 +------
1 files changed, 1 insertions(+), 6 deletions(-)
diff --git a/game/fs.cc b/game/fs.cc
index 9e4f665..f5d0751 100644
--- a/game/fs.cc
+++ b/game/fs.cc
@@ -113,12 +113,7 @@ Paths const& getPaths(bool refresh) {
fs::path shareDir = SHARED_DATA_DIR;
Paths dirs;
#ifdef _WIN32
- // Add APPLIC~1 (user-specific application data) FIXME: Not tested
- {
- //char const* appdata = getenv("APPDATA");
- //if (appdata) dirs.push_back(appdata / shortDir);
- dirs.push_back(getConfigDir());
- }
+ dirs.push_back(getConfigDir()); // APPDATA/performous
#else
// Adding XDG_DATA_HOME
{
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 02:05:40
|
Module: performous Branch: master Commit: eda87cd72903591cf4b1b9aabef1d4ef1c729073 Author: Lasse Karkkainen <tro...@tr...> Date: Thu Jan 14 03:47:29 2010 +0200 Bump version number --- CMakeLists.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c532d6..66aa7e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(Performous CXX) cmake_minimum_required(VERSION 2.6) cmake_policy(VERSION 2.6) -set(PROJECT_VERSION "0.5.0") +set(PROJECT_VERSION "0.5.0+") # Avoid source tree pollution if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-14 01:33:46
|
Module: web Branch: master Commit: f4b58dce1a0da32c20945fb0cecdeb442c28a846 Author: Lasse Karkkainen <tro...@tr...> Date: Thu Jan 14 02:34:52 2010 +0200 Notice about Windows issues --- htdocs-source/index.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/htdocs-source/index.txt b/htdocs-source/index.txt index 234874f..a6686e1 100644 --- a/htdocs-source/index.txt +++ b/htdocs-source/index.txt @@ -39,7 +39,7 @@ This is the first release to include <strong>Windows</strong> and <strong>Mac</s Navigation abstraction Windows fixes -Head over to the download page to get the new version. Because of the very large number of new features and due to porting to two new platforms we expect the release to be buggy. Please let us know if you find any problems. We'll try to release 0.5.1 soon with possible fixes and more new features. +Head over to the download page to get the new version. Because of the very large number of new features and due to porting to two new platforms we expect the release to be buggy. Please let us know if you find any problems. We'll try to release 0.5.1 soon with possible fixes and more new features. The Windows version is known to have various issues but we need all of them reported so that 0.5.1 can be made better (surprisingly we severely lack Windows testers). :h2:2009-12-12 - 0.4.1 cancelled, Windows alpha available We have rather large new features in the development version and because of this the next release will be 0.5.0 rather than 0.4.1. The hilights include a new menu and of course the dance game feature, which we just tested in two player mode with actual dance pads. No release date other than "soon" has been set. |
|
From: Arto Seppä <za...@us...> - 2010-01-13 23:01:18
|
Module: performous Branch: master Commit: 1f8537a8a1493e28c256768bc008b41dee12435b Author: Arto Seppä <za...@us...> Date: Thu Jan 14 00:58:01 2010 +0200 Added a "works-for-me" application bundling script for OS X. --- osx-utils/performous-app-build.sh | 51 ++++------ osx-utils/performous-mac_script | 4 - osx-utils/resources/Info.plist | 32 ++++++ osx-utils/resources/etc/fonts/fonts.conf | 151 ++++++++++++++++++++++++++++++ osx-utils/resources/performous-launcher | 6 + osx-utils/resources/performous.icns | Bin 0 -> 193626 bytes 6 files changed, 208 insertions(+), 36 deletions(-) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-13 22:42:06
|
Module: web Branch: master Commit: 7b72f9d53df9c0d3bac7bb1d94bc4d274fc47ad7 Author: Lasse Karkkainen <tro...@tr...> Date: Thu Jan 14 00:41:52 2010 +0200 Cleanup --- htdocs-source/install.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/htdocs-source/install.txt b/htdocs-source/install.txt index acda73d..8e3721c 100644 --- a/htdocs-source/install.txt +++ b/htdocs-source/install.txt @@ -12,7 +12,7 @@ Song downloads can be found on the separate <strong>songs page</strong>. OS X 10.5: <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0.dmg/download">bundle</a> -:h2:Linux binaries +:h2:Linux Ubuntu 9.10 Karmic Koala: <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0-Ubuntu9.10-i386.deb/download">i386</a> <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0-Ubuntu9.10-amd64.deb/download">amd64</a> Ubuntu 8.04 LTS Hardy Heron: <a href="http://sourceforge.net/projects/performous/files/performous/Performous-0.3.2-Ubuntu8.04-i386.deb">i386</a> <a href="http://sourceforge.net/projects/performous/files/performous/Performous-0.3.2-Ubuntu8.04-amd64.deb">amd64</a> |
|
From: Lasse Kärkkäi. <tr...@us...> - 2010-01-13 22:42:03
|
Module: web Branch: master Commit: 091df51d38c7b26136fd45d10a279c312690cc32 Author: Lasse Karkkainen <tro...@tr...> Date: Thu Jan 14 00:24:07 2010 +0200 Downloads --- htdocs-source/install.txt | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/htdocs-source/install.txt b/htdocs-source/install.txt index c99e067..acda73d 100644 --- a/htdocs-source/install.txt +++ b/htdocs-source/install.txt @@ -4,6 +4,14 @@ How to get performing Song downloads can be found on the separate <strong>songs page</strong>. +:h2:Windows + + WinXP or better: <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0.exe/download">installer</a> + +:h2:Mac OS X + + OS X 10.5: <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0.dmg/download">bundle</a> + :h2:Linux binaries Ubuntu 9.10 Karmic Koala: <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0-Ubuntu9.10-i386.deb/download">i386</a> <a href="https://sourceforge.net/projects/performous/files/performous/0.5.0/Performous-0.5.0-Ubuntu9.10-amd64.deb/download">amd64</a> @@ -14,13 +22,6 @@ Song downloads can be found on the separate <strong>songs page</strong>. If you get an error about unsatisfied dependencies on Ubuntu, you may have to enable the community-supported software source <strong>universe</strong> via <strong>System | Administration | Software Sources</strong>. Most users already have this enabled. -:h2:Windows - -Building software on Windows has turned out to be extremely difficult but we are still actively working on this! - -:h2:Mac OS X - -No software bundle currently available, but we expect one of the Mac users to package one shortly. :h2:Other systems and development version |