core/audio: Rework audio message handling

Let's just do everything inline and cut out the extra function calls to
make the code simpler.  I also created functions to help tests send EOS
or error messages.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2017-04-06 08:13:30 -04:00
parent 4986bdad13
commit e6f34d34f0
4 changed files with 57 additions and 76 deletions

View File

@ -73,15 +73,46 @@ static void __audio_pad_added(GstElement *element, GstPad *pad, gpointer data)
static gboolean __audio_message(GstBus *bus, GstMessage *message, gpointer data)
{
GstObject *source = GST_OBJECT(GST_MESSAGE_SRC(message));
gchar *debug = NULL;
GError *error = NULL;
GstState old, state, next;
unsigned int load_flags = LOAD_DEFAULT;
switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_ERROR:
audio_error(message);
gst_message_parse_error(message, &error, &debug);
g_printerr("ERROR from element %s: %s\n",
GST_OBJECT_NAME(source), error->message);
g_printerr("DEBUG details: %s\n", debug ? debug : "none");
g_error_free(error);
g_free(debug);
if (audio_cur_state() != GST_STATE_PLAYING)
load_flags = LOAD_HISTORY;
__audio_load(playlist_next(), load_flags);
break;
case GST_MESSAGE_EOS:
audio_eos();
track_played(audio_track);
if (audio_pause_count >= 0) {
audio_pause_after(audio_pause_count - 1);
if (audio_pause_count == -1)
load_flags = LOAD_HISTORY;
}
__audio_load(playlist_next(), load_flags);
break;
case GST_MESSAGE_STATE_CHANGED:
audio_state_changed(message);
if (!audio_cb || source != GST_OBJECT(audio_pipeline))
break;
gst_message_parse_state_changed(message, &old, &state, &next);
if (state == GST_STATE_PLAYING || state == GST_STATE_PAUSED) {
if (next == GST_STATE_VOID_PENDING)
audio_cb->audio_cb_state_change(state);
}
default:
break;
}
@ -258,56 +289,6 @@ struct track *audio_prev()
return __audio_load(playlist_prev(), LOAD_PLAYING);
}
void audio_state_changed(GstMessage *message)
{
GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(message));
GstState old, state, next;
if (!audio_cb || src != audio_pipeline)
return;
gst_message_parse_state_changed(message, &old, &state, &next);
if (next != GST_STATE_VOID_PENDING)
return;
if (state == GST_STATE_PLAYING || state == GST_STATE_PAUSED)
audio_cb->audio_cb_state_change(state);
}
struct track *audio_eos()
{
/* Mark current track as played */
if (audio_track)
track_played(audio_track);
/* Check pause count and pick the next track */
if (audio_pause_count >= 0)
audio_pause_after(audio_pause_count - 1);
return __audio_load(playlist_next(), audio_pause_count != -1 ?
LOAD_DEFAULT : LOAD_HISTORY);
}
void audio_error(GstMessage *error)
{
gchar *path = NULL, *debug = NULL;
GError *err = NULL;
if (audio_track)
path = track_path(audio_track);
if (error)
gst_message_parse_error(error, &err, &debug);
g_print("Error: %s (%s)\n", err->message, path);
if (debug)
g_print("Debug details: %s\n", debug);
__audio_load(playlist_next(), audio_cur_state() == GST_STATE_PLAYING ?
LOAD_DEFAULT : LOAD_HISTORY);
g_error_free(err);
g_free(debug);
g_free(path);
}
void audio_pause_after(int n)
{
if (n != audio_pause_count) {
@ -318,6 +299,21 @@ void audio_pause_after(int n)
}
#ifdef CONFIG_TESTING
void test_audio_eos()
{
GstMessage *message = gst_message_new_eos(GST_OBJECT(audio_pipeline));
__audio_message(NULL, message, NULL);
gst_message_unref(message);
}
void test_audio_error(GError *error, gchar *debug)
{
GstMessage *message = gst_message_new_error(
GST_OBJECT(audio_pipeline), error, debug);
__audio_message(NULL, message, NULL);
gst_message_unref(message);
}
GstElement *test_audio_pipeline()
{
return audio_pipeline;

View File

@ -72,19 +72,12 @@ struct track *audio_next();
/* Called to load the previous track. */
struct track *audio_prev();
/* Called when the state of the pipeline has changed. */
void audio_state_changed(GstMessage *);
/* Called when playback has reached the end-of-stream position. */
struct track *audio_eos();
/* Called when gstreamer has received an error. */
void audio_error(GstMessage *);
/* Called to configure automatic pausing. */
void audio_pause_after(int);
#ifdef CONFIG_TESTING
void test_audio_eos();
void test_audio_error(GError *, gchar *);
GstElement *test_audio_pipeline();
#endif /* CONFIG_TESTING */
#endif /* OCARINA_CORE_AUDIO_H */

View File

@ -24,17 +24,9 @@ static unsigned int test_wait_state(void)
static void test_send_error()
{
GstMessage *message;
GError *error;
error = g_error_new(1, G_FILE_ERROR_BADF, "Simulated Error");
message = gst_message_new_error(GST_OBJECT(test_audio_pipeline()),
error, "Fake error for testing");
audio_error(message);
gst_message_unref(message);
GError *error = g_error_new(1, G_FILE_ERROR_BADF, "Simulated Error");
test_audio_error(error, "Fake error for testing");
g_error_free(error);
}
static void test_audio_load(struct track *track) { load_count++; }
@ -221,14 +213,14 @@ void test_autopause()
state_count = 0;
for (i = 4; i > -1; i--) {
audio_eos();
test_audio_eos();
g_assert_cmpuint(pause_count, ==, i);
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
g_assert(playlist_at(history, 0) == audio_cur_track());
}
g_assert_cmpuint(test_wait_state(), ==, 5);
audio_eos();
test_audio_eos();
while (idle_run_task()) {}
g_assert_cmpint(pause_count, ==, -1);
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);

View File

@ -80,12 +80,12 @@ static void test_audio_buttons()
g_assert(audio_cur_track() == track_get(0));
gtk_combo_box_set_active(GTK_COMBO_BOX(gui_pause_after()), 2);
audio_eos();
test_audio_eos();
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PLAYING);
g_assert_cmpuint(gtk_combo_box_get_active(
GTK_COMBO_BOX(gui_pause_after())), ==, 1);
audio_eos();
test_audio_eos();
g_assert_cmpuint(audio_cur_state(), ==, GST_STATE_PAUSED);
g_assert_cmpuint(gtk_combo_box_get_active(
GTK_COMBO_BOX(gui_pause_after())), ==, 0);