2008-10-22 02:23:35 UTC
previous
next
/* Echo Media Player
* Copyright (C) 2008 Shane O'Connell
*
* [ The original file includes a copyright header in this location describing
* the file as being released under the terms of the GNU General Public
* License. It has been removed in order to display the file as part of the
* archive. ]
*/
#include "PlaybackManager.h"
#include <giomm.h>
#include <gst/gst.h>
#include <list>
#include <iostream>
#include <cassert>
#include <cstdlib>
using namespace std;
sigc::signal<void, PlaySourceRef, int, bool> PlaybackManager::_signal_track_started;
sigc::signal<void, PlaySourceRef, int, bool> PlaybackManager::_signal_track_stopped;
static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer data);
GstElement* gst_player;
PlaySourceRef current_playlist;
int current_index; // TODO we need to update current_index when tracks are inserted/removed in the playlist
ShuffleType current_shuffle;
void PlaybackManager::init_sound(int *argc, char **argv[])
{
gst_init(argc, argv);
// TODO use gconfsink so that we use users settings
gst_player = gst_element_factory_make("playbin", "player");
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE (gst_player));
gst_bus_add_watch(bus, bus_callback, NULL);
gst_object_unref(bus);
}
gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer data)
{
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:
GError *err;
gchar *debug;
gst_message_parse_error (message, &err, &debug);
cout << "Gstreamer error: " << err->message << endl;
g_error_free (err);
g_free (debug);
break;
case GST_MESSAGE_EOS:
PlaybackManager::next();
break;
default:
break;
}
return TRUE;
}
void PlaybackManager::play(PlaySourceRef playlist, int index)
{
assert(index >= 0);
assert(index < playlist->get_num_tracks());
gst_element_set_state(gst_player, GST_STATE_READY);
if (current_playlist)
PlaybackManager::signal_track_stopped().emit(current_playlist, current_index, false);
current_playlist = playlist;
current_index = index;
g_object_set(G_OBJECT(gst_player), "uri", playlist->get_track(index)->get_uri().c_str(), NULL);
gst_element_set_state(gst_player, GST_STATE_PLAYING);
PlaybackManager::signal_track_started().emit(current_playlist, current_index, false);
}
void PlaybackManager::next()
{
assert(current_playlist);
if (GST_STATE(gst_player) != GST_STATE_READY)
gst_element_set_state(gst_player, GST_STATE_READY);
if (current_playlist)
PlaybackManager::signal_track_stopped().emit(current_playlist, current_index, false);
switch (current_shuffle) {
case SHUFFLE_NONE:
current_index++;
break;
default:
current_index = rand() % current_playlist->get_num_tracks();
break;
}
if (current_index < current_playlist->get_num_tracks()) {
g_object_set(G_OBJECT(gst_player), "uri", current_playlist->get_track(current_index)->get_uri().c_str(), NULL);
gst_element_set_state(gst_player, GST_STATE_PLAYING);
PlaybackManager::signal_track_started().emit(current_playlist, current_index, false);
}
else
current_playlist.reset();
}
void PlaybackManager::prev()
{
assert(current_playlist);
if (GST_STATE(gst_player) != GST_STATE_READY)
gst_element_set_state(gst_player, GST_STATE_READY);
if (current_playlist)
PlaybackManager::signal_track_stopped().emit(current_playlist, current_index, false);
current_index--;
if (current_index >= 0) {
g_object_set(G_OBJECT(gst_player), "uri", current_playlist->get_track(current_index)->get_uri().c_str(), NULL);
gst_element_set_state(gst_player, GST_STATE_PLAYING);
PlaybackManager::signal_track_started().emit(current_playlist, current_index, false);
}
}
void PlaybackManager::stop()
{
gst_element_set_state(gst_player, GST_STATE_READY);
PlaybackManager::signal_track_started().emit(current_playlist, current_index, false);
current_playlist.reset();
}
void PlaybackManager::pause()
{
assert(current_playlist);
assert(!is_paused());
gst_element_set_state(gst_player, GST_STATE_PAUSED);
PlaybackManager::signal_track_stopped().emit(current_playlist, current_index, true);
}
void PlaybackManager::unpause()
{
assert(current_playlist);
assert(is_paused());
gst_element_set_state(gst_player, GST_STATE_PLAYING);
PlaybackManager::signal_track_started().emit(current_playlist, current_index, true);
}
bool PlaybackManager::is_paused()
{
//GstState state;
//gst_element_get_state(gst_player, &state, NULL, GST_CLOCK_TIME_NONE);
//return (state == GST_STATE_PAUSED);
return (GST_STATE(gst_player) == GST_STATE_PAUSED);
}
int PlaybackManager::get_track_length()
{
GstFormat format = GST_FORMAT_TIME;
long long length;
if (gst_element_query_duration(gst_player, &format, &length) == TRUE) {
if (format == GST_FORMAT_TIME) {
return (length / 1000000); // return in ms
}
}
return 0;
}
int PlaybackManager::get_track_position()
{
GstFormat format = GST_FORMAT_TIME;
long long position;
if (gst_element_query_position(gst_player, &format, &position) == TRUE) {
if (format == GST_FORMAT_TIME) {
return (position / 1000000); // return in ms
}
}
return 0;
}
PlaySourceRef PlaybackManager::get_playing_source()
{
return current_playlist;
}
int PlaybackManager::get_playing_index()
{
return current_index;
}
void PlaybackManager::set_shuffle(ShuffleType type)
{
current_shuffle = type;
}