--- /dev/null
+/*
+ * player.c
+ *
+ * Created on: 2009-10-22
+ * Author: marcin
+ */
+
+#include "player.h"
+#include <gst/gst.h>
+#include <hildon/hildon.h>
+#include "resource_utils.h"
+
+/****************************************************************************
+ * Simple playing functions
+ */
+/** TODO: Get rid of global variable pipeline */
+static GstElement *pipeline = NULL;
+static GList* tracklist = 0;
+static GList* tracklist_item = 0;
+
+GtkWidget* toolbar;
+GtkWidget* playing_label;
+guint playing_label_timer = 0;
+GtkToolButton* play_pause_button;
+gboolean error=FALSE;
+
+enum {
+ STOPPED,
+ PAUSED,
+ PLAYING
+} state;
+
+enum {
+ CMD_PREV,
+ CMD_PLAY,
+ CMD_PAUSE,
+ CMD_STOP,
+ CMD_NEXT
+};
+
+static struct {
+ const gchar* image;
+ const gchar* label;
+ const int cmd;
+ GtkWidget* icon;
+} toolbar_data[] = {
+ { "player_prev_light.png", "prev", CMD_PREV, NULL },
+ { "player_play_light.png", "play", CMD_PLAY, NULL },
+ { "player_pause_light.png", "pause", CMD_PAUSE, NULL },
+ { "player_stop_light.png", "stop", CMD_STOP, NULL },
+ { "player_next_light.png", "next", CMD_NEXT, NULL }
+};
+
+void pause_track();
+void stop_track();
+void prev_track();
+void next_track();
+void update_toolbar();
+
+static void handle_eos(GstBus * bus, GstMessage * message, gpointer * appdata) {
+ if(!error) {
+ next_track();
+ }
+}
+
+static void handle_error(GstBus * bus, GstMessage * msg, gpointer * appdata) {
+ gchar *dbg;
+ GError *err;
+
+ error = TRUE;
+
+ gst_message_parse_error (msg, &err, &dbg);
+ g_debug("player: ERROR: %s\nDEBUG: %s",err->message,dbg);
+
+ hildon_banner_show_informationf(NULL,NULL,"Error: %s",err->message);
+}
+
+static void handle_buffering(GstBus * bus, GstMessage * msg, gpointer * appdata) {
+ gint percent;
+
+ gst_message_parse_buffering (msg, &percent);
+
+ if(percent!=100) {
+ gchar* text = g_strdup_printf("Buffering %d%%", percent);
+ gtk_label_set_text(GTK_LABEL(playing_label),text);
+ g_free(text);
+ }
+}
+
+static void handle_any(GstBus * bus, GstMessage * msg, gchar *name) {
+ g_debug("handle_%s",name);
+ if(g_strcmp0(name,"duration")==0) {
+ GstFormat format;
+ gint64 duration;
+ gst_message_parse_duration(msg, &format, &duration);
+ g_debug("duration %d: %Ld",format,duration);
+ }
+}
+
+static gboolean handle_timer(gpointer* ptr) {
+ if (pipeline) {
+ GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
+ gboolean res = gst_element_query(pipeline, query);
+ if (res) {
+ GstFormat format;
+ gint64 cur;
+ gst_query_parse_position(query, &format, &cur);
+ int sec = cur / GST_SECOND;
+ gchar *text = g_strdup_printf("%u:%02u:%02u", sec / 60 / 60, (sec / 60) % 60, sec % 60);
+ gtk_label_set_text(GTK_LABEL(playing_label), text);
+ g_free(text);
+ }
+ gst_query_unref(query);
+ }
+ return TRUE;
+}
+
+void play_track(Track* track) {
+ if (pipeline) {
+ gst_element_set_state(pipeline, GST_STATE_NULL);
+ g_object_unref(GST_OBJECT(pipeline));
+ pipeline = NULL;
+ }
+
+ hildon_banner_show_informationf(NULL,NULL,"Playing %s by %s",track->name,track->artist_name);
+
+ if (0) {
+ GstElement *src, *decoder, *sink;
+ pipeline = gst_pipeline_new(NULL);
+ src = gst_element_factory_make("souphttpsrc", NULL);
+ g_object_set(G_OBJECT(src), "location", track->stream, NULL);
+ decoder = gst_element_factory_make("decodebin", NULL);
+ sink = gst_element_factory_make("alsasink", NULL);
+ gst_bin_add_many(GST_BIN(pipeline), src, decoder, sink, NULL);
+ gst_element_link_many(src, decoder, sink, NULL);
+ } else {
+ pipeline = gst_element_factory_make("playbin2", NULL);
+ g_object_set(G_OBJECT(pipeline), "uri", track->stream, NULL);
+ }
+
+ error = FALSE;
+ /* setup message handling */
+ GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
+ gst_bus_add_signal_watch_full(bus, G_PRIORITY_HIGH);
+ g_signal_connect(bus, "message::error", (GCallback) handle_error, NULL);
+ g_signal_connect(bus, "message::eos", (GCallback) handle_eos, NULL);
+ g_signal_connect(bus, "message::buffering", (GCallback) handle_buffering, NULL);
+ g_signal_connect(bus, "message::duration", (GCallback) handle_any, "duration");
+ gst_object_unref(GST_OBJECT(bus));
+
+ if(!playing_label_timer) {
+ playing_label_timer = gdk_threads_add_timeout_seconds(1, (GSourceFunc)handle_timer, NULL);
+ }
+
+ g_debug("Playing %s",track->stream);
+ gst_element_set_state(pipeline, GST_STATE_PLAYING);
+
+ state = PLAYING;
+ update_toolbar();
+
+ if (tracklist_item->data != track) {
+ tracklist_item = g_list_first(tracklist);
+ while (tracklist_item && tracklist_item->data != track) {
+ tracklist_item = g_list_next(tracklist_item);
+ }
+ }
+}
+
+void pause_track() {
+ hildon_banner_show_information(NULL,NULL,"Paused");
+
+ gst_element_set_state(pipeline,GST_STATE_PAUSED);
+
+ state = PAUSED;
+ update_toolbar();
+}
+
+
+void resume_track() {
+ gst_element_set_state(pipeline, GST_STATE_PLAYING);
+
+ state = PLAYING;
+ update_toolbar();
+}
+
+void stop_track() {
+ if (pipeline) {
+ hildon_banner_show_information(NULL,NULL,"Stopped");
+
+ gst_element_set_state(pipeline, GST_STATE_NULL);
+ g_object_unref(GST_OBJECT(pipeline));
+ pipeline = NULL;
+ }
+
+ state = STOPPED;
+ update_toolbar();
+}
+
+void next_track() {
+ if (!tracklist_item) return;
+
+ tracklist_item = g_list_next(tracklist_item);
+ if (!tracklist_item) {
+ tracklist_item = g_list_first(tracklist);
+ }
+ play_track(tracklist_item->data);
+}
+
+void prev_track() {
+ if (!tracklist_item) return;
+
+ tracklist_item = g_list_previous(tracklist_item);
+ if (!tracklist_item) {
+ tracklist_item = g_list_last(tracklist);
+ }
+ play_track(tracklist_item->data);
+}
+
+
+void on_clicked(GtkToolButton *toolbutton, gint cmd) {
+ switch (cmd) {
+ case CMD_PREV:
+ prev_track();
+ break;
+ case CMD_PLAY:
+ switch(state) {
+ case STOPPED:
+ if (tracklist_item) {
+ play_track(tracklist_item->data);
+ }
+ break;
+ case PAUSED:
+ resume_track();
+ break;
+ case PLAYING:
+ pause_track();
+ break;
+ }
+ break;
+ case CMD_STOP:
+ stop_track();
+ break;
+ case CMD_NEXT:
+ next_track();
+ break;
+ }
+}
+
+void update_toolbar() {
+ if (state == PLAYING) {
+ gtk_tool_button_set_icon_widget(play_pause_button, toolbar_data[CMD_PAUSE].icon);
+ gtk_tool_button_set_label(play_pause_button, toolbar_data[CMD_PAUSE].label);
+ gtk_widget_show_all(GTK_WIDGET(play_pause_button));
+ }
+ else if (state == PAUSED) {
+ gtk_tool_button_set_icon_widget(play_pause_button, toolbar_data[CMD_PLAY].icon);
+ gtk_tool_button_set_label(play_pause_button, toolbar_data[CMD_PLAY].label);
+ gtk_widget_show_all(GTK_WIDGET(play_pause_button));
+ }
+}
+
+GtkWidget* player_toolbar_create() {
+ if (!toolbar) {
+ GtkToolItem *toolitem;
+ int i,pos=0;
+
+ /* Create a toolbar */
+ toolbar = gtk_toolbar_new();
+
+ /* Add items to the toolbar */
+ for (i = 0; i < G_N_ELEMENTS(toolbar_data); i++) {
+ toolbar_data[i].icon = resource_get_image(toolbar_data[i].image);
+ g_object_ref(toolbar_data[i].icon);
+
+ if (i != CMD_PAUSE) {
+ toolitem = gtk_tool_button_new(toolbar_data[i].icon, toolbar_data[i].label);
+ g_signal_connect (G_OBJECT (toolitem), "clicked", G_CALLBACK (on_clicked), (gpointer) toolbar_data[i].cmd);
+ gtk_widget_show_all(GTK_WIDGET(toolitem));
+ gtk_toolbar_insert(GTK_TOOLBAR (toolbar), toolitem, pos++);
+ }
+ if (i == CMD_PLAY) {
+ play_pause_button = GTK_TOOL_BUTTON(toolitem);
+ }
+ }
+
+ toolitem = gtk_separator_tool_item_new();
+ gtk_tool_item_set_expand(toolitem,TRUE);
+ gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toolitem,pos++);
+
+ playing_label= gtk_label_new("");
+ toolitem = gtk_tool_button_new(NULL, NULL);
+ gtk_widget_set_usize((GtkWidget*)playing_label, 200, -1);
+ gtk_tool_button_set_label_widget(GTK_TOOL_BUTTON(toolitem), playing_label);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toolitem,pos++);
+
+ gtk_widget_show_all(GTK_WIDGET(toolbar));
+ }
+ update_toolbar();
+ return toolbar;
+}
+
+void player_set_track_list(GList* track_list) {
+ g_debug("player_set_track_list length:%d",g_list_length(track_list));
+
+ if (tracklist) {
+ track_list_free(tracklist);
+ tracklist = NULL;
+ }
+
+ tracklist = track_list;
+ tracklist_item = g_list_first(tracklist);
+}