From bd2aaf73d1ae6739eef6f491b52608546f26862b Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Sat, 4 Jan 2014 13:09:44 -0500 Subject: [PATCH] audio: Updates for spec changes This is mostly to add in checks for try / catch style error handling. Signed-off-by: Anna Schumaker --- design.txt | 16 ++++---- design/audio.txt | 14 +++---- design/deck.txt | 2 +- include/audio.h | 10 ++--- lib/audio.cpp | 52 +++++++++++--------------- lib/deck.cpp | 3 +- lib/playqueue.cpp | 4 +- tests/audio/audio.cpp | 87 ++++++++++++++++++++++++++++++++----------- 8 files changed, 112 insertions(+), 76 deletions(-) diff --git a/design.txt b/design.txt index 6696a594..9c4adecf 100644 --- a/design.txt +++ b/design.txt @@ -902,7 +902,7 @@ Deck: (lib/deck.cpp) If the playqueue is empty after calling next(), remove it from the deck. - If there are no playable IDs, throw -1. + If there are no playable IDs, throw -EEXIST. void deck :: reset(); This function only exists if CONFIG_TEST is enabled. Erase @@ -959,12 +959,14 @@ Audio: (lib/audio.cpp) void audio :: play(); void audio :: pause(); Change the gstreamer state to either GST_STATE_PLAYING or - GST_STATE_PAUSED. Throw -EAUDIO if there is an error changing + GST_STATE_PAUSED. Do nothing if there is not a track loaded + in the pipeline. Throw -EAUDIO if there is an error changing state. void audio :: seek_to(long); Seek to a position X nanoseconds into the track. Throw -EAUDIO - if there is an error seeking to the requested position. + if there is an error seeking to the requested position. Do + nothing if there is not a track loaded in the pipeline. Seconds can be converted to nanoseconds by multiplying with GST_SECOND. @@ -977,7 +979,7 @@ Audio: (lib/audio.cpp) Call the deck :: next() function to get the next trackid, and load that file into the gstreamer pipeline. Do not change the state of the pipeline (if nothing is playing yet, don't - call play()). Throw -ENOTRACK if there is no track to load + call play()). Throw -EEXIST if there is no track to load into the pipeline. When a track is loaded: @@ -988,16 +990,14 @@ Audio: (lib/audio.cpp) Write out the state file. - void audio :: previous(); - Load recent.next() into the playlist. - void audio :: previous(); Call the playlist :: previous() function to iterate backwards through the recently played playqueue. Load the returned trackid without changing the pipeline state. trackid audio :: current_trackid(); - Return the trackid of the currently playing song. + Return the trackid of the currently playing song. If no track + is loaded throw -EEXIST; unsigned int audio :: position(); Return the number of seconds that the song has played. diff --git a/design/audio.txt b/design/audio.txt index 035a6db0..81d004c8 100644 --- a/design/audio.txt +++ b/design/audio.txt @@ -52,12 +52,14 @@ Audio: (lib/audio.cpp) void audio :: play(); void audio :: pause(); Change the gstreamer state to either GST_STATE_PLAYING or - GST_STATE_PAUSED. Throw -EAUDIO if there is an error changing + GST_STATE_PAUSED. Do nothing if there is not a track loaded + in the pipeline. Throw -EAUDIO if there is an error changing state. void audio :: seek_to(long); Seek to a position X nanoseconds into the track. Throw -EAUDIO - if there is an error seeking to the requested position. + if there is an error seeking to the requested position. Do + nothing if there is not a track loaded in the pipeline. Seconds can be converted to nanoseconds by multiplying with GST_SECOND. @@ -70,7 +72,7 @@ Audio: (lib/audio.cpp) Call the deck :: next() function to get the next trackid, and load that file into the gstreamer pipeline. Do not change the state of the pipeline (if nothing is playing yet, don't - call play()). Throw -ENOTRACK if there is no track to load + call play()). Throw -EEXIST if there is no track to load into the pipeline. When a track is loaded: @@ -81,16 +83,14 @@ Audio: (lib/audio.cpp) Write out the state file. - void audio :: previous(); - Load recent.next() into the playlist. - void audio :: previous(); Call the playlist :: previous() function to iterate backwards through the recently played playqueue. Load the returned trackid without changing the pipeline state. trackid audio :: current_trackid(); - Return the trackid of the currently playing song. + Return the trackid of the currently playing song. If no track + is loaded throw -EEXIST; unsigned int audio :: position(); Return the number of seconds that the song has played. diff --git a/design/deck.txt b/design/deck.txt index f25832da..c954e5cc 100644 --- a/design/deck.txt +++ b/design/deck.txt @@ -47,7 +47,7 @@ Deck: (lib/deck.cpp) If the playqueue is empty after calling next(), remove it from the deck. - If there are no playable IDs, throw -1. + If there are no playable IDs, throw -EEXIST. void deck :: reset(); This function only exists if CONFIG_TEST is enabled. Erase diff --git a/include/audio.h b/include/audio.h index 604445a7..3443c931 100644 --- a/include/audio.h +++ b/include/audio.h @@ -14,13 +14,13 @@ namespace audio void init(int *, char ***); void quit(); - bool play(); - bool pause(); - bool stop(); - bool next(); + void play(); + void pause(); + void stop(); + void next(); unsigned int current_trackid(); - bool seek_to(long); + void seek_to(long); long position(); long duration(); diff --git a/lib/audio.cpp b/lib/audio.cpp index a7092ad5..2c35a750 100644 --- a/lib/audio.cpp +++ b/lib/audio.cpp @@ -107,66 +107,56 @@ void audio :: quit() gst_deinit(); } -bool audio :: play() +void audio :: play() { if (track_loaded == false) - return false; - return change_state(GST_STATE_PLAYING); + return; + change_state(GST_STATE_PLAYING); } -bool audio :: pause() +void audio :: pause() { if (track_loaded == false) - return false; - return change_state(GST_STATE_PAUSED); + return; + change_state(GST_STATE_PAUSED); } -bool audio :: stop() +void audio :: stop() { - if (pause() == false) - return false; - return seek_to(0); + pause(); + seek_to(0); } -bool audio :: seek_to(long pos) +void audio :: seek_to(long pos) { bool ret; if (track_loaded == false) - return false; + return; ret = gst_element_seek_simple(GST_ELEMENT(ocarina_player), GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, pos); - return ret; + if (!ret) + throw -E_AUDIO; } -static bool _next() +void audio :: next() { library :: Song song; - unsigned int id = deck :: next(); + unsigned int id; - if (library :: lookup(id, &song) == false) - return false; - if (load_song(song) == false) - return false; + track_loaded = false; + id = deck :: next(); + library :: lookup(id, &song); + load_song(song); cur_trackid = id; - return true; -} - -bool audio :: next() -{ - try { - track_loaded = _next(); - } catch (int) { - track_loaded = false; - } - return track_loaded; + track_loaded = true; } unsigned int audio :: current_trackid() { if (track_loaded == false) - throw -1; + throw -E_EXIST; return cur_trackid; } diff --git a/lib/deck.cpp b/lib/deck.cpp index 17091bde..cf74d2b5 100644 --- a/lib/deck.cpp +++ b/lib/deck.cpp @@ -2,6 +2,7 @@ * Copyright 2013 (c) Anna Schumaker. */ #include +#include #include #include @@ -85,7 +86,7 @@ unsigned int deck :: next() } } - throw -1; + throw -E_EXIST; } #ifdef CONFIG_TEST diff --git a/lib/playqueue.cpp b/lib/playqueue.cpp index e9480551..5ec7edee 100644 --- a/lib/playqueue.cpp +++ b/lib/playqueue.cpp @@ -94,7 +94,9 @@ unsigned int Playqueue :: next() { unsigned int res; - if (tracks.size() == 1) + if (tracks.size() == 0) + throw -E_EXIST; + else if (tracks.size() == 1) cur = 0; else if (flags & PQ_RANDOM) cur += rand() % (tracks.size() / 2) + 1; diff --git a/tests/audio/audio.cpp b/tests/audio/audio.cpp index f4dca2d9..da9a1595 100644 --- a/tests/audio/audio.cpp +++ b/tests/audio/audio.cpp @@ -3,6 +3,7 @@ */ #include #include +#include #include #include @@ -25,6 +26,7 @@ void check_ret(const std :: string &test, bool ret, bool expected) print("Failed.\n"); } +template void check_ret(const std :: string &test, long ret, long expected) { print("Test %s: ", test.c_str()); @@ -34,22 +36,59 @@ void check_ret(const std :: string &test, long ret, long expected) print("Failed (Expected %ld but got %ld)\n", expected, ret); } +void check_error(int error, int expected) +{ + if (expected == 0) { + if (error == 0) + print("Success!\n"); + else + print("Failed with error: %d\n", error); + } else { + if (error == 0) + print("Failed (expected error: %d)\n", error); + else + print("Success!\n"); + } +} + +void call_func(const std :: string &test, void (*func)(), int expected) +{ + print("Test %s: ", test.c_str()); + try { + func(); + check_error(0, expected); + } catch (int error) { + check_error(error, expected); + } +} + +void call_func(const std :: string &test, void (*func)(long), long arg, int expected) +{ + print("Test %s: ", test.c_str()); + try { + func(arg); + check_error(0, expected); + } catch (int error) { + check_error(error, expected); + } +} + /* Call various functions without a track loaded */ void test_0() { - check_ret("0a", audio :: play(), false); - 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); + call_func("0a", audio :: play, 0); + call_func("0b", audio :: pause, 0); + call_func("0c", audio :: seek_to, 10, 0); + call_func("0d", audio :: next, -E_EXIST); + call_func("0e", audio :: stop, 0); check_ret("0f", audio :: position(), 0); check_ret("0g", audio :: duration(), 0); try { print("Test 0h: "); audio :: current_trackid(); - print("Failed.\n"); + check_error(0, -E_EXIST); } catch (int error) { - print("Success!\n"); + check_error(error, -E_EXIST); } print("\n"); } @@ -59,11 +98,11 @@ 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("1d", audio :: seek_to(1 * GST_SECOND), true); - check_ret("1e", audio :: stop(), true); + call_func("1a", audio :: next, 0); + call_func("1b", audio :: play, 0); + call_func("1c", audio :: pause, 0); + call_func("1d", audio :: seek_to, 1 * GST_SECOND, 0); + call_func("1e", audio :: stop, 0); check_ret("1f", audio :: current_trackid() == 0, true); check_ret("1g", audio :: position(), 0); print("\n"); @@ -86,30 +125,30 @@ int test_2_cb(gpointer data) case 1: check_ret("2g", audio :: duration(), song.track->length * GST_SECOND); seek_pos = (song.track->length * GST_SECOND) - GST_SECOND; - check_ret("2h", audio :: seek_to(seek_pos), true); + call_func("2h", audio :: seek_to, seek_pos, 0); break; case 2: max = (song.track->length * GST_SECOND) - GST_SECOND + (501 * GST_MSECOND); check_ret("2i", pos <= max, true); - check_ret("2j", audio :: stop(), true); + call_func("2j", audio :: stop, 0); break; case 3: check_ret("2k", pos, 0); - check_ret("2l", audio :: play(), true); - check_ret("2m", audio :: seek_to(audio :: duration() - 1), true); + call_func("2l", audio :: play, 0); + call_func("2m", audio :: seek_to, audio :: duration() - 1, 0); break; case 4: check_ret("2n", audio :: pause_count(), (long)2); - check_ret("2o", audio :: seek_to(audio :: duration() - 1), true); + call_func("2o", audio :: seek_to, audio :: duration() - 1, 0); break; case 5: check_ret("2p", audio :: pause_count(), (long)1); - check_ret("2q", audio :: seek_to(audio :: duration() - 1), true); + call_func("2q", audio :: seek_to, audio :: duration() - 1, 0); break; case 6: check_ret("2r", audio :: pause_count(), (long)0); - check_ret("2s", audio :: seek_to(audio :: duration() - 1), true); + call_func("2s", audio :: seek_to, audio :: duration() - 1, 0); break; case 7: check_ret("2t", audio :: pause_enabled(), false); @@ -151,7 +190,7 @@ void test_2() int main(int argc, char **argv) { - Playlist *plist; + Playqueue *pqueue; gen_library(); @@ -160,10 +199,14 @@ int main(int argc, char **argv) test_0(); /* Read in library, set up a playlist */ + library :: init(); + library :: reset(); library :: add_path("/tmp/library/0"); - plist = deck :: create(); + while (idle :: run_task()); + + pqueue = deck :: create(); for (unsigned int i = 0; i < 150; i++) - plist->add(i); + pqueue->add(i); test_1(); test_2();