/* * Copyright 2013 (c) Anna Schumaker. */ #include #include #include #include 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; } static bool change_state(GstState state) { GstStateChangeReturn ret; ret = gst_element_set_state(GST_ELEMENT(ocarina_player), state); switch (ret) { case GST_STATE_CHANGE_SUCCESS: case GST_STATE_CHANGE_ASYNC: return true; default: return false; } } static bool load_song(library :: Song &song) { GstState state; gchar *escaped; std::string filepath = song.library->root_path + "/" + song.track->filepath; 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); return change_state(state); } void audio :: init(int *argc, char ***argv) { GstBus *bus; gst_init(argc, argv); ocarina_player = gst_element_factory_make("playbin", "ocarina_player"); bus = gst_pipeline_get_bus(GST_PIPELINE(ocarina_player)); gst_bus_add_watch(bus, on_message, NULL); } void audio :: quit() { gst_deinit(); } bool audio :: play() { if (track_loaded == false) return false; return change_state(GST_STATE_PLAYING); } bool audio :: pause() { if (track_loaded == false) return false; return change_state(GST_STATE_PAUSED); } bool audio :: stop() { if (pause() == false) return false; return seek_to(0); } bool audio :: seek_to(long pos) { bool ret; if (track_loaded == false) return false; ret = gst_element_seek_simple(GST_ELEMENT(ocarina_player), GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, pos); return ret; } static bool _next() { library :: Song song; unsigned int id = deck :: next(); if (library :: lookup(id, &song) == false) return false; if (load_song(song) == false) return false; cur_trackid = id; return true; } bool audio :: next() { try { track_loaded = _next(); } catch (int) { track_loaded = false; } return track_loaded; } unsigned int audio :: current_trackid() { if (track_loaded == false) throw -1; return cur_trackid; } long audio :: position() { long position; if (track_loaded == false) return 0; if (!gst_element_query_position(GST_ELEMENT(ocarina_player), GST_FORMAT_TIME, &position)) return 0; return position; } long audio :: duration() { long duration; if (track_loaded == false) return 0; if (!gst_element_query_duration(ocarina_player, GST_FORMAT_TIME, &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; }