191 lines
3.4 KiB
C++
191 lines
3.4 KiB
C++
// Copyright (c) 2011 Bryan Schumaker.
|
|
#include <deck.h>
|
|
#include <audio.h>
|
|
#include <print.h>
|
|
|
|
#include <sstream>
|
|
using namespace std;
|
|
|
|
static GstElement *player = NULL;
|
|
static GstFormat fmt_time = GST_FORMAT_TIME;
|
|
static GstState cur_state = GST_STATE_READY;
|
|
|
|
static void notify_state_change(GstState state)
|
|
{
|
|
if (state == GST_STATE_PLAYING)
|
|
libsaria::notify(PLAYING, NULL);
|
|
else if (state == GST_STATE_PAUSED)
|
|
libsaria::notify(PAUSED, NULL);
|
|
}
|
|
|
|
static bool change_state(GstState new_state)
|
|
{
|
|
GstStateChangeReturn ret;
|
|
ret = gst_element_set_state(GST_ELEMENT(player), new_state);
|
|
|
|
switch(ret) {
|
|
case GST_STATE_CHANGE_SUCCESS:
|
|
case GST_STATE_CHANGE_ASYNC:
|
|
cur_state = new_state;
|
|
notify_state_change(cur_state);
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void load_file(GstElement *playbin, string file, GstState state)
|
|
{
|
|
gchar *escaped;
|
|
if (file == "" || !libsaria::exists(file))
|
|
return;
|
|
|
|
println("Loading file: " + file);
|
|
escaped = gst_filename_to_uri(file.c_str(), NULL);
|
|
|
|
/* Set pipeline to the requested state */
|
|
change_state(GST_STATE_READY);
|
|
g_object_set(G_OBJECT(playbin), "uri", escaped, NULL);
|
|
change_state(state);
|
|
|
|
g_free(escaped);
|
|
}
|
|
|
|
static string to_string(gint64 time)
|
|
{
|
|
stringstream stream;
|
|
int minutes, seconds;
|
|
|
|
if (time == 0)
|
|
return "";
|
|
|
|
time = time / GST_SECOND;
|
|
minutes = time / 60;
|
|
seconds = time - (minutes * 60);
|
|
stream << minutes << ":";
|
|
if (seconds < 10)
|
|
stream << "0";
|
|
stream << seconds;
|
|
return stream.str();
|
|
}
|
|
|
|
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 gboolean on_message(GstBus *bus, GstMessage *message, gpointer data)
|
|
{
|
|
switch (GST_MESSAGE_TYPE(message)) {
|
|
case GST_MESSAGE_ERROR:
|
|
parse_error(message);
|
|
case GST_MESSAGE_EOS:
|
|
libsaria::deck::next();
|
|
default:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
namespace libsaria
|
|
{
|
|
|
|
void audio::play()
|
|
{
|
|
change_state(GST_STATE_PLAYING);
|
|
}
|
|
|
|
void audio::pause()
|
|
{
|
|
change_state(GST_STATE_PAUSED);
|
|
}
|
|
|
|
void audio::toggle_play()
|
|
{
|
|
if (cur_state == GST_STATE_PLAYING)
|
|
pause();
|
|
else
|
|
play();
|
|
}
|
|
|
|
GstState audio::get_state()
|
|
{
|
|
return cur_state;
|
|
}
|
|
|
|
void audio::stop()
|
|
{
|
|
pause();
|
|
seek_to(0);
|
|
}
|
|
|
|
void audio::load(string file, bool play)
|
|
{
|
|
GstState state = GST_STATE_PLAYING;
|
|
if (!play)
|
|
state = GST_STATE_PAUSED;
|
|
load_file(player, file, state);
|
|
}
|
|
|
|
/* Seek to this many seconds into the song */
|
|
void audio::seek_to(double pos)
|
|
{
|
|
gst_element_seek_simple(GST_ELEMENT(player),
|
|
GST_FORMAT_TIME,
|
|
GST_SEEK_FLAG_FLUSH,
|
|
pos);
|
|
}
|
|
|
|
gint64 audio::duration()
|
|
{
|
|
gint64 duration;
|
|
if (!gst_element_query_duration(player, &fmt_time, &duration))
|
|
return 0;
|
|
if (duration < 0)
|
|
duration = 0;
|
|
return duration;
|
|
}
|
|
|
|
gint64 audio::position()
|
|
{
|
|
gint64 position;
|
|
if (!gst_element_query_position(player, &fmt_time, &position))
|
|
return 0;
|
|
return position;
|
|
}
|
|
|
|
string audio::posstr()
|
|
{
|
|
return to_string(position());
|
|
}
|
|
|
|
bool audio::played()
|
|
{
|
|
return position() > ((duration() * 3) / 4);
|
|
}
|
|
|
|
void audio::init(int argc, char **argv)
|
|
{
|
|
static GstBus *bus;
|
|
println("Initializing libsaria audio");
|
|
gst_init(&argc, &argv);
|
|
|
|
player = gst_element_factory_make("playbin2", "player");
|
|
bus = gst_pipeline_get_bus(GST_PIPELINE(player));
|
|
|
|
gst_bus_add_watch(bus, on_message, NULL);
|
|
}
|
|
|
|
void audio::quit()
|
|
{
|
|
gst_deinit();
|
|
}
|
|
|
|
};
|