ocarina/gui/gst.cpp

223 lines
4.2 KiB
C++

/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <core/audio.h>
#include <core/driver.h>
#include <gst/gst.h>
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(int *, char ***);
/**
* GStreamer audio driver destructor.
*/
~GSTDriver();
/**
* Called to initialize the GStreamer audio driver.
* @param eos_cb End-of-stream callback function.
*/
void init(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(int *argc, char ***argv)
: Driver()
{
GstBus *bus;
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);
}
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(void (*eos_cb)())
{
on_eos = eos_cb;
}
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);
audio :: next();
break;
case GST_MESSAGE_EOS:
on_eos();
break;
default:
break;
}
}
void init_gst(int *argc, char ***argv)
{
gst_driver = new GSTDriver(argc, argv);
}
void quit_gst()
{
delete gst_driver;
}