audio: Implement pause after N tracks feature

This patch implements the pause-after-N-tracks feature.  I also included
various improvements to the audio code.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2013-12-25 14:35:33 -05:00 committed by Anna Schumaker
parent ee9a98737a
commit c65c8b06f2
5 changed files with 220 additions and 13 deletions

View File

@ -33,6 +33,9 @@ Audio: (lib/audio.cpp)
options from the argv array as they are processed, so pass
pointers to argc and argv to this function.
void audio :: quit()
Clean up memory allocated by gstreamer.
bool audio :: play()
bool audio :: pause()
Change the gstreamer state to either GST_STATE_PLAYING or
@ -71,12 +74,19 @@ Audio: (lib/audio.cpp)
unsigned int audio :: duration()
Return the duration of the current song in seconds.
void audio :: pause_after(unsigned int)
Pause after N tracks, pass a negative number to disable. The
count will only be decremented when an end-of-stream message
is received by the gstreamer pipeline.
void audio :: pause_after(bool enabled, unsigned int N)
Pause after N tracks. The first parameter is a bool
representing if this feature is enabled or not (true == enabled,
false == disabled).
The count will only be decremented when an end-of-stream message
is received by the gstreamer pipeline, and not when calling
next().
bool audio :: pause_enabled()
Return true if pausing is enabled, and false if pausing is
disabled.
unsigned int audio :: pause_count()
Return the number of tracks that will be played before
playback pauses. Throw -1 if the user does not want us to
pause.
playback pauses.

View File

@ -12,6 +12,7 @@ namespace audio
{
void init(int *, char ***);
void quit();
bool play();
bool pause();
@ -22,6 +23,10 @@ namespace audio
bool seek_to(long);
long position();
long duration();
void pause_after(bool, unsigned int);
bool pause_enabled();
unsigned int pause_count();
};
#endif /* OCARINA_AUDIO_H */

View File

@ -8,11 +8,49 @@
#include <string.h>
static GstElement *ocarina_player;
static bool track_loaded = false;
static unsigned int cur_trackid = 0;
static bool o_pause_enabled = false;
static unsigned int o_pause_count = 0;
static bool o_should_pause = false;
static void parse_error(GstMessage *error)
{
GError *err;
gchar *debug;
gst_message_parse_error(error, &err, &debug);
g_print("Error: %s\n", err->message);
g_error_free(err);
g_free(debug);
}
static void handle_pause_count()
{
if (o_pause_enabled == false)
return;
else if (o_pause_count == 0) {
o_should_pause = true;
o_pause_enabled = false;
} else
o_pause_count--;
}
static gboolean on_message(GstBus *bus, GstMessage *message, gpointer data)
{
switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_ERROR:
parse_error(message);
audio :: next();
break;
case GST_MESSAGE_EOS:
handle_pause_count();
audio :: next();
default:
break;
}
return TRUE;
}
@ -36,9 +74,15 @@ static bool load_song(library :: Song &song)
gchar *escaped;
std::string filepath = song.library->root_path + "/" + song.track->filepath;
gst_element_get_state(GST_ELEMENT(ocarina_player), &state,
NULL, GST_CLOCK_TIME_NONE);
if (o_should_pause == true) {
state = GST_STATE_PAUSED;
o_should_pause = false;
} else {
gst_element_get_state(GST_ELEMENT(ocarina_player), &state,
NULL, GST_CLOCK_TIME_NONE);
}
change_state(GST_STATE_NULL);
escaped = gst_filename_to_uri(filepath.c_str(), NULL);
g_object_set(G_OBJECT(ocarina_player), "uri", escaped, NULL);
g_free(escaped);
@ -58,6 +102,11 @@ void audio :: init(int *argc, char ***argv)
gst_bus_add_watch(bus, on_message, NULL);
}
void audio :: quit()
{
gst_deinit();
}
bool audio :: play()
{
if (track_loaded == false)
@ -142,3 +191,19 @@ long audio :: duration()
return 0;
return duration;
}
void audio :: pause_after(bool enabled, unsigned int n)
{
o_pause_enabled = enabled;
o_pause_count = n;
}
bool audio :: pause_enabled()
{
return o_pause_enabled;
}
unsigned int audio :: pause_count()
{
return o_pause_count;
}

View File

@ -63,11 +63,90 @@ void test_1()
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 :: 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);
check_ret("1e", audio :: stop(), true);
check_ret("1f", audio :: current_trackid() == 0, true);
check_ret("1g", audio :: position(), 0);
print("\n");
}
/* Test pause_after() */
unsigned int test_2_count = 0;
int test_2_cb(gpointer data)
{
long seek_pos, pos, max;
library :: Song song;
GMainLoop *loop = (GMainLoop *)data;
library :: lookup(audio :: current_trackid(), &song);
pos = audio :: position();
switch (test_2_count) {
case 0:
break;
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);
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);
break;
case 3:
check_ret("2k", pos, 0);
check_ret("2l", audio :: play(), true);
check_ret("2m", audio :: seek_to(audio :: duration() - 1), true);
break;
case 4:
check_ret("2n", audio :: pause_count(), (long)2);
check_ret("2o", audio :: seek_to(audio :: duration() - 1), true);
break;
case 5:
check_ret("2p", audio :: pause_count(), (long)1);
check_ret("2q", audio :: seek_to(audio :: duration() - 1), true);
break;
case 6:
check_ret("2r", audio :: pause_count(), (long)0);
check_ret("2s", audio :: seek_to(audio :: duration() - 1), true);
break;
case 7:
check_ret("2t", audio :: pause_enabled(), false);
check_ret("2u", audio :: pause_count(), (long)0);
break;
case 8:
pos = audio :: position();
check_ret("2v", (0 <= pos) && (pos <= GST_MSECOND), true);
break;
case 9:
pos = audio :: position();
check_ret("2w", (0 <= pos) && (pos <= GST_MSECOND), true);
default:
g_main_quit(loop);
}
test_2_count++;
return true;
}
void test_2()
{
GMainLoop *loop;
check_ret("2a", audio :: pause_enabled(), false);
check_ret("2b", audio :: pause_count(), (long)0);
audio :: pause_after(true, 3);
check_ret("2c", audio :: pause_enabled(), true);
check_ret("2d", audio :: pause_count(), (long)3);
audio :: next();
check_ret("2e", audio :: pause_enabled(), true);
check_ret("2f", audio :: pause_count(), (long)3);
audio :: play();
loop = g_main_loop_new(NULL, FALSE);
g_timeout_add(500, test_2_cb, loop);
g_main_loop_run(loop);
}
int main(int argc, char **argv)
@ -87,6 +166,8 @@ int main(int argc, char **argv)
plist->add(i);
test_1();
test_2();
//audio :: quit();
return 0;
}

46
tests/audio/audio.good Normal file
View File

@ -0,0 +1,46 @@
Generating library: 0
Generating library: 1
Generating library: 2
Generating library: 3
Generating library: 4
Test 0a: Success!
Test 0b: Success!
Test 0c: Success!
Test 0d: Success!
Test 0e: Success!
Test 0f: Success!
Test 0g: Success!
Test 0h: Success!
Test 1a: Success!
Test 1b: Success!
Test 1c: Success!
Test 1d: Success!
Test 1e: Success!
Test 1f: Success!
Test 1g: Success!
Test 2a: Success!
Test 2b: Success!
Test 2c: Success!
Test 2d: Success!
Test 2e: Success!
Test 2f: Success!
Test 2g: Success!
Test 2h: Success!
Test 2i: Success!
Test 2j: Success!
Test 2k: Success!
Test 2l: Success!
Test 2m: Success!
Test 2n: Success!
Test 2o: Success!
Test 2p: Success!
Test 2q: Success!
Test 2r: Success!
Test 2s: Success!
Test 2t: Success!
Test 2u: Success!
Test 2v: Success!
Test 2w: Success!