/* * Copyright 2014 (c) Anna Schumaker. * * The gst_init() function parses command line options passed to Ocarina * through argv. Use the command `gst-inspect-1.0 --help-gst` to find * what options are supported. */ #include #include #include static GstBus *gst_bus; static GstElement *gst_player; static Gtk::Button *o_next; static Gtk::Button *o_pause; static Gtk::Button *o_play; static Gtk::Button *o_prev; static Gtk::Scale *o_seek; static Gtk::Button *o_stop; static Gtk::SpinButton *o_count; static Gtk::CheckButton *o_enabled; static Gtk::Label *o_album; static Gtk::Label *o_artist; static Gtk::Label *o_duration; static Gtk::Label *o_position; static Gtk::Label *o_title; static Glib::RefPtr o_progress; static bool gst_change_state(GstState state) { GstStateChangeReturn ret = gst_element_set_state(gst_player, state); switch (ret) { case GST_STATE_CHANGE_SUCCESS: case GST_STATE_CHANGE_ASYNC: return true; default: return false; } } static void set_markup(Gtk::Label *label, const std::string &size, const std::string &text) { label->set_markup("" + Glib::Markup::escape_text(text) + ""); } class GSTDriver : public AudioDriver { public: void load(Track *track) { gchar *uri = gst_filename_to_uri(track->path().c_str(), NULL); gst_change_state(GST_STATE_NULL); g_object_set(G_OBJECT(gst_player), "uri", uri, NULL); g_free(uri); set_markup(o_album, "x-large", "From: " + track->album()->name()); set_markup(o_artist, "x-large", "By: " + track->artist()->name()); set_markup(o_title, "xx-large", track->name()); o_duration->set_text(track->length_str()); plist :: track_loaded(track); } void play() { if (gst_change_state(GST_STATE_PLAYING)) { o_play->hide(); o_pause->show(); } } void pause() { if (gst_change_state(GST_STATE_PAUSED)) { o_play->show(); o_pause->hide(); } } bool is_playing() { GstState state; gst_element_get_state(gst_player, &state, NULL, GST_CLOCK_TIME_NONE); return state == GST_STATE_PLAYING; } void seek_to(long offset) { gst_element_seek_simple(gst_player, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, offset); } long position() { long position; if (gst_element_query_position(gst_player, GST_FORMAT_TIME, &position)) return position; return 0; } long duration() { long duration; if (gst_element_query_duration(gst_player, GST_FORMAT_TIME, &duration)) return duration; return 0; } }; static GSTDriver *gst_driver; static void parse_gst_error(GstMessage *error) { GError *err; Track *track = audio :: current_track(); gst_message_parse_error(error, &err, NULL); if (track) g_print("Error playing file: %s\n", track->path().c_str()); g_print("Error: %s\n", err->message); g_error_free(err); } static gboolean on_gst_message(GstBus *bus, GstMessage *message, gpointer data) { switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ERROR: parse_gst_error(message); audio :: next(); break; case GST_MESSAGE_EOS: gst_driver->eos(); o_count->set_value(audio :: pause_count()); o_enabled->set_active(audio :: pause_enabled()); break; default: break; } return TRUE; } static bool on_seek(Gtk::ScrollType type, double value) { audio :: seek_to(value); return true; } static void on_pause_count() { o_enabled->set_active(true); } static void on_pause_enabled() { audio :: pause_after(o_enabled->get_active(), o_count->get_value()); } static bool on_timeout() { o_position->set_text(audio :: position_str()); o_progress->set_upper(audio :: duration()); o_progress->set_value(audio :: position()); return true; } void gst :: next() { audio :: next(); audio :: play(); } void gst :: toggle() { if (gst_driver->is_playing()) audio :: pause(); else audio :: play(); } void gst :: init(int *argc, char ***argv) { gst_init(argc, argv); gst_player = gst_element_factory_make("playbin", "ocarina_player"); gst_bus = gst_pipeline_get_bus(GST_PIPELINE(gst_player)); gst_driver = new GSTDriver(); o_next = gui :: get_widget("o_next"); o_pause = gui :: get_widget("o_pause"); o_play = gui :: get_widget("o_play"); o_prev = gui :: get_widget("o_prev"); o_seek = gui :: get_widget("o_seek"); o_stop = gui :: get_widget("o_stop"); o_count = gui :: get_widget("o_pause_count"); o_enabled = gui :: get_widget("o_pause_enabled"); o_album = gui :: get_widget("o_album"); o_artist = gui :: get_widget("o_artist"); o_duration = gui :: get_widget("o_duration"); o_position = gui :: get_widget("o_position"); o_title = gui :: get_widget("o_title"); o_progress = gui :: get_object("o_progress"); o_next->signal_clicked().connect(sigc::ptr_fun(next)); o_pause->signal_clicked().connect(sigc::ptr_fun(audio :: pause)); o_play->signal_clicked().connect(sigc::ptr_fun(audio :: play)); o_prev->signal_clicked().connect(sigc::ptr_fun(audio :: prev)); o_seek->signal_change_value().connect(sigc::ptr_fun(on_seek)); o_stop->signal_clicked().connect(sigc::ptr_fun(audio :: stop)); o_count->signal_changed().connect(sigc::ptr_fun(on_pause_count)); o_enabled->signal_toggled().connect(sigc::ptr_fun(on_pause_enabled)); gst_bus_add_watch(gst_bus, on_gst_message, NULL); Glib :: signal_timeout().connect(sigc::ptr_fun(on_timeout), 500); } void gst :: quit() { delete gst_driver; gst_change_state(GST_STATE_NULL); gst_deinit(); }