diff --git a/core/driver.cpp b/core/driver.cpp index caa4e912..e0810293 100644 --- a/core/driver.cpp +++ b/core/driver.cpp @@ -40,123 +40,6 @@ void TestDriver :: error() { on_error(); } #else /* CONFIG_TEST */ -static gboolean on_gst_message(GstBus *bus, GstMessage *message, gpointer data) -{ - GSTDriver *driver = (GSTDriver *)data; - driver->on_message(message); - return TRUE; -} - -static void parse_gst_error(GstMessage *error, const std::string filepath) -{ - GError *err; - gchar *debug; - - gst_message_parse_error(error, &err, &debug); - g_print("Error playing file: %s\n", filepath.c_str()); - g_print("Error: %s\n", err->message); - g_error_free(err); - g_free(debug); -} - -GSTDriver :: GSTDriver() {} - -GSTDriver :: ~GSTDriver() -{ - change_state(GST_STATE_NULL); - gst_deinit(); -} - -bool GSTDriver :: change_state(GstState state) -{ - GstStateChangeReturn ret = gst_element_set_state(player, state); - switch (ret) { - case GST_STATE_CHANGE_SUCCESS: - case GST_STATE_CHANGE_ASYNC: - return true; - default: - return false; - } -} - -void GSTDriver :: init(int *argc, char ***argv, void (*eos_cb)(), void (*error_cb)()) -{ - GstBus *bus; - - on_eos = eos_cb; - on_error = error_cb; - - gst_init(argc, argv); - player = gst_element_factory_make("playbin", "ocarina_player"); - bus = gst_pipeline_get_bus(GST_PIPELINE(player)); - gst_bus_add_watch(bus, on_gst_message, this); -} - -void GSTDriver :: load(const std::string &filepath) -{ - gchar *uri; - - cur_file = filepath; - change_state(GST_STATE_NULL); - uri = gst_filename_to_uri(filepath.c_str(), NULL); - g_object_set(G_OBJECT(player), "uri", uri, NULL); - g_free(uri); -} - -bool GSTDriver :: play() -{ - return change_state(GST_STATE_PLAYING); -} - -bool GSTDriver :: pause() -{ - return change_state(GST_STATE_PAUSED); -} - -bool GSTDriver :: is_playing() -{ - GstState state; - gst_element_get_state(player, &state, NULL, GST_CLOCK_TIME_NONE); - return state == GST_STATE_PLAYING; -} - -void GSTDriver :: seek_to(long offset) -{ - gst_element_seek_simple(player, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, offset); -} - -long GSTDriver :: position() -{ - long position; - if (gst_element_query_position(player, GST_FORMAT_TIME, &position)) - return position; - return 0; -} - -long GSTDriver :: duration() -{ - long duration; - - if (gst_element_query_duration(player, GST_FORMAT_TIME, &duration)) - return duration; - return 0; -} - -void GSTDriver :: on_message(GstMessage *message) -{ - switch (GST_MESSAGE_TYPE(message)) { - case GST_MESSAGE_ERROR: - parse_gst_error(message, cur_file); - on_error(); - break; - case GST_MESSAGE_EOS: - on_eos(); - break; - default: - break; - } -} - #endif /* CONFIG_TEST */ diff --git a/gui/gst.cpp b/gui/gst.cpp index 53dd406e..3be6cb09 100644 --- a/gui/gst.cpp +++ b/gui/gst.cpp @@ -2,10 +2,216 @@ * Copyright 2014 (c) Anna Schumaker. */ #include +#include + +class GSTDriver; static GSTDriver *gst_driver; +/** + * Driver for the GStreamer audio library. + * + * The shell command `gst-inspect-1.0 --help-gst` details the command line + * options that can be passed to Ocarina. + */ +class GSTDriver : public Driver +{ +private: + GstElement *player; + std::string cur_file; + bool change_state(GstState state); + +public: + /** + * GStreamer audio driver constructor. + */ + GSTDriver(); + + /** + * GStreamer audio driver destructor. + */ + ~GSTDriver(); + + /** + * Called to initialize the GStreamer audio driver. + * @param argc Argc passed to the application's main() function. + * @param argv Argv passed to the applicaiton's main() function. + * @param eos_cb End-of-stream callback function. + * @param error_cb Callback function used when the audio library encounters an error. + */ + void init(int *, char ***, void (*)(), void (*)()); + + /** + * Load a track into the gstreamer pipeline. + * @param filepath The file to be loaded. + */ + void load(const std::string &); + + /** + * Begin playback on the GStreamer pipeline. + * @return True if the state change was successful. + */ + bool play(); + + /** + * Pause the GStreamer pipeline. + * @return True if the state change was successful. + */ + bool pause(); + + /** + * Check if the GStreamer pipeline is playing. + * @return True if the pipeline is playing. + */ + bool is_playing(); + + + /** + * Seek to a specific position in the pipeline. + * @param offset Offset from the beginning of the pipeline, in nanoseconds. + */ + void seek_to(long); + + /** + * Find the current playback position of the pipeline. + * @return The current position of the pipeline, in nanoseconds. + */ + long position(); + + /** + * Find the duration of the pipeline. + * @return The duration of the pipeline, in nanoseconds. + */ + long duration(); + + + /** + * Called to handle messages from the GStreamer bus. + * @param message The message to be handled. + */ + void on_message(GstMessage *); +}; + + +static gboolean on_gst_message(GstBus *bus, GstMessage *message, gpointer data) +{ + GSTDriver *driver = (GSTDriver *)data; + driver->on_message(message); + return TRUE; +} + +static void parse_gst_error(GstMessage *error, const std::string filepath) +{ + GError *err; + gchar *debug; + + gst_message_parse_error(error, &err, &debug); + g_print("Error playing file: %s\n", filepath.c_str()); + g_print("Error: %s\n", err->message); + g_error_free(err); + g_free(debug); +} + +GSTDriver :: GSTDriver() {} + +GSTDriver :: ~GSTDriver() +{ + change_state(GST_STATE_NULL); + gst_deinit(); +} + +bool GSTDriver :: change_state(GstState state) +{ + GstStateChangeReturn ret = gst_element_set_state(player, state); + switch (ret) { + case GST_STATE_CHANGE_SUCCESS: + case GST_STATE_CHANGE_ASYNC: + return true; + default: + return false; + } +} + +void GSTDriver :: init(int *argc, char ***argv, void (*eos_cb)(), void (*error_cb)()) +{ + GstBus *bus; + + on_eos = eos_cb; + on_error = error_cb; + + gst_init(argc, argv); + player = gst_element_factory_make("playbin", "ocarina_player"); + bus = gst_pipeline_get_bus(GST_PIPELINE(player)); + gst_bus_add_watch(bus, on_gst_message, this); +} + +void GSTDriver :: load(const std::string &filepath) +{ + gchar *uri; + + cur_file = filepath; + change_state(GST_STATE_NULL); + uri = gst_filename_to_uri(filepath.c_str(), NULL); + g_object_set(G_OBJECT(player), "uri", uri, NULL); + g_free(uri); +} + +bool GSTDriver :: play() +{ + return change_state(GST_STATE_PLAYING); +} + +bool GSTDriver :: pause() +{ + return change_state(GST_STATE_PAUSED); +} + +bool GSTDriver :: is_playing() +{ + GstState state; + gst_element_get_state(player, &state, NULL, GST_CLOCK_TIME_NONE); + return state == GST_STATE_PLAYING; +} + +void GSTDriver :: seek_to(long offset) +{ + gst_element_seek_simple(player, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, offset); +} + +long GSTDriver :: position() +{ + long position; + if (gst_element_query_position(player, GST_FORMAT_TIME, &position)) + return position; + return 0; +} + +long GSTDriver :: duration() +{ + long duration; + + if (gst_element_query_duration(player, GST_FORMAT_TIME, &duration)) + return duration; + return 0; +} + +void GSTDriver :: on_message(GstMessage *message) +{ + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: + parse_gst_error(message, cur_file); + on_error(); + break; + case GST_MESSAGE_EOS: + on_eos(); + break; + default: + break; + } +} + + void init_gst() { gst_driver = new GSTDriver(); diff --git a/include/core/driver.h b/include/core/driver.h index 9ca2f62d..bef80fe7 100644 --- a/include/core/driver.h +++ b/include/core/driver.h @@ -112,93 +112,6 @@ public: void eos(); void error(); }; -#else /* !CONFIG_TEST */ - -#include - -/** - * Driver for the GStreamer audio library. - * - * The shell command `gst-inspect-1.0 --help-gst` details the command line - * options that can be passed to Ocarina. - */ -class GSTDriver : public Driver -{ -private: - GstElement *player; - std::string cur_file; - bool change_state(GstState state); - -public: - /** - * GStreamer audio driver constructor. - */ - GSTDriver(); - - /** - * GStreamer audio driver destructor. - */ - ~GSTDriver(); - - /** - * Called to initialize the GStreamer audio driver. - * @param argc Argc passed to the application's main() function. - * @param argv Argv passed to the applicaiton's main() function. - * @param eos_cb End-of-stream callback function. - * @param error_cb Callback function used when the audio library encounters an error. - */ - void init(int *, char ***, void (*)(), void (*)()); - - /** - * Load a track into the gstreamer pipeline. - * @param filepath The file to be loaded. - */ - void load(const std::string &); - - /** - * Begin playback on the GStreamer pipeline. - * @return True if the state change was successful. - */ - bool play(); - - /** - * Pause the GStreamer pipeline. - * @return True if the state change was successful. - */ - bool pause(); - - /** - * Check if the GStreamer pipeline is playing. - * @return True if the pipeline is playing. - */ - bool is_playing(); - - - /** - * Seek to a specific position in the pipeline. - * @param offset Offset from the beginning of the pipeline, in nanoseconds. - */ - void seek_to(long); - - /** - * Find the current playback position of the pipeline. - * @return The current position of the pipeline, in nanoseconds. - */ - long position(); - - /** - * Find the duration of the pipeline. - * @return The duration of the pipeline, in nanoseconds. - */ - long duration(); - - - /** - * Called to handle messages from the GStreamer bus. - * @param message The message to be handled. - */ - void on_message(GstMessage *); -}; #endif /* CONFIG_TEST */