diff --git a/design/audio.txt b/design/audio.txt index c6384654..f4f64610 100644 --- a/design/audio.txt +++ b/design/audio.txt @@ -38,11 +38,14 @@ Audio: (lib/audio.cpp) Change the gstreamer state to either GST_STATE_PLAYING or GST_STATE_PAUSED. Return true on success and false otherwise. - bool audio :: seek_to(int) - Seek to a position X seconds into the track. Return true if - a track is loaded and the seek isn't out of bounds. False + bool audio :: seek_to(long) + Seek to a position X nanoseconds into the track. Return true + if track is loaded and the seek isn't out of bounds. False otherwise. + Seconds can be converted to nanoseconds by multiplying with + GST_SECOND. + void audio :: stop() pause() seek_to(0) @@ -75,4 +78,5 @@ Audio: (lib/audio.cpp) unsigned int audio :: pause_count() Return the number of tracks that will be played before - playback pauses. + playback pauses. Throw -1 if the user does not want us to + pause. diff --git a/include/audio.h b/include/audio.h index 6f8f04f9..3cc357cb 100644 --- a/include/audio.h +++ b/include/audio.h @@ -15,9 +15,13 @@ namespace audio bool play(); bool pause(); - bool seek_to(double); + bool stop(); bool next(); + unsigned int current_trackid(); + bool seek_to(long); + long position(); + long duration(); }; #endif /* OCARINA_AUDIO_H */ diff --git a/lib/audio.cpp b/lib/audio.cpp index a69eeca9..2bcf43c7 100644 --- a/lib/audio.cpp +++ b/lib/audio.cpp @@ -9,6 +9,7 @@ static GstElement *ocarina_player; static bool track_loaded = false; +static unsigned int cur_trackid = 0; static gboolean on_message(GstBus *bus, GstMessage *message, gpointer data) { @@ -71,30 +72,73 @@ bool audio :: pause() return change_state(GST_STATE_PAUSED); } -bool audio :: seek_to(double pos) +bool audio :: stop() { + if (pause() == false) + return false; + return seek_to(0); +} + +bool audio :: seek_to(long pos) +{ + bool ret; if (track_loaded == false) return false; - return gst_element_seek_simple(GST_ELEMENT(ocarina_player), + ret = gst_element_seek_simple(GST_ELEMENT(ocarina_player), GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, pos); + return ret; +} + +static bool _next() +{ + library :: Song song; + unsigned int id = deck :: next(); + + if (library :: lookup(id, &song) == false) + return false; + if (load_song(song) == false) + return false; + cur_trackid = id; return true; } bool audio :: next() { - unsigned int id; - library :: Song song; - try { - id = deck :: next(); - if (library :: lookup(id, &song) == false) - track_loaded = false; - else - track_loaded = load_song(song); + track_loaded = _next(); } catch (int) { track_loaded = false; } return track_loaded; } + +unsigned int audio :: current_trackid() +{ + if (track_loaded == false) + throw -1; + return cur_trackid; +} + +long audio :: position() +{ + long position; + + if (track_loaded == false) + return 0; + if (!gst_element_query_position(GST_ELEMENT(ocarina_player), GST_FORMAT_TIME, &position)) + return 0; + return position; +} + +long audio :: duration() +{ + long duration; + + if (track_loaded == false) + return 0; + if (!gst_element_query_duration(ocarina_player, GST_FORMAT_TIME, &duration)) + return 0; + return duration; +} diff --git a/tests/audio/audio.cpp b/tests/audio/audio.cpp index d0c7000b..467239c2 100644 --- a/tests/audio/audio.cpp +++ b/tests/audio/audio.cpp @@ -25,6 +25,15 @@ void check_ret(const std :: string &test, bool ret, bool expected) print("Failed.\n"); } +void check_ret(const std :: string &test, long ret, long expected) +{ + print("Test %s: ", test.c_str()); + if (ret == expected) + print("Success!\n"); + else + print("Failed (Expected %ld but got %ld)\n", expected, ret); +} + /* Call various functions without a track loaded */ void test_0() { @@ -32,15 +41,33 @@ void test_0() check_ret("0b", audio :: pause(), false); check_ret("0c", audio :: seek_to(10), false); check_ret("0d", audio :: next(), false); + check_ret("0e", audio :: stop(), false); + check_ret("0f", audio :: position(), 0); + check_ret("0g", audio :: duration(), 0); + try { + print("Test 0h: "); + audio :: current_trackid(); + print("Failed.\n"); + } catch (int error) { + print("Success!\n"); + } print("\n"); } void test_1() { + library :: Song song; + library :: lookup(0, &song); + check_ret("1a", audio :: next(), true); check_ret("1b", audio :: play(), true); check_ret("1c", audio :: pause(), true); - check_ret("1c", audio :: seek_to(10), true); + check_ret("1d", audio :: seek_to(1 * GST_SECOND), true); + check_ret("1e", audio :: position(), 1 * GST_SECOND); + check_ret("1f", audio :: stop(), true); + check_ret("1g", audio :: current_trackid() == 0, true); + check_ret("1h", audio :: position(), 0); + check_ret("1i", audio :: duration(), song.track->length); } int main(int argc, char **argv)