/*
* File: gstplayer.c
* Author: Alvin Delagon
* Summary: gstreamer based mp3 player with GTK+ frontend
*/
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <gst/gst.h>
GstElement *pipeline, *filesrc, *mad, *audioconvert, *alsasink;
GtkListStore *store;
enum
{
COL_NAME = 0,
NUM_COLS
};
static gboolean
cb_bus_messages (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);
g_print ("Got Bus Error: %s\n", err->message);
g_error_free (err);
g_free (debug);
gtk_main_quit ();
break;
}
case GST_MESSAGE_TAG:
{
/* For some reasons, this is not working properly */
GstTagList *tags;
gchar *artist;
gst_message_parse_tag (message, &tags);
gst_tag_list_get_string (tags, GST_TAG_ARTIST, &artist);
g_print ("File Tags:\n");
g_print ("Title: %s\n", artist);
break;
}
case GST_MESSAGE_EOS:
{
g_print ("End-of-stream. Playing next file...\n");
break;
}
default:
break;
}
return TRUE;
}
void cb_add (GtkWidget *widget, GtkWidget *list)
{
GtkWindow *window;
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Add Item To Playlist",
window,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL,
GTK_STOCK_ADD,
GTK_RESPONSE_ACCEPT,
NULL);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
gchar *filename;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
GtkTreeModel *model;
GtkTreeIter iter;
gtk_tree_view_set_model (GTK_TREE_VIEW (list), NULL);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, COL_NAME, filename, -1);
model = GTK_TREE_MODEL (store);
gtk_tree_view_set_model (GTK_TREE_VIEW (list), model);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
g_object_set (filesrc, "location", filename, NULL);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
g_free (filename);
}
gtk_widget_destroy (dialog);
}
void cb_row_activated (GtkWidget *widget, gpointer gdata)
{
g_print ("I Was activated!\n");
}
void cb_exit (GtkWidget *widget, gpointer gdata)
{
gtk_main_quit ();
}
static GtkWidget *
init_playlist (GladeXML *ui)
{
GtkCellRenderer *renderer;
GtkWidget *view;
view = glade_xml_get_widget (ui, "PlayList");
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
-1,
"Playlist",
renderer,
"text", COL_NAME,
NULL);
store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_UINT);
gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (store));
return (view);
}
int main (int argc, char *argv[])
{
GladeXML *ui;
GtkWidget *widget;
GtkWidget *playlist;
GstBus *bus;
gst_init (&argc, &argv); // gst_init should be called first before gtk_init
gtk_init (&argc, &argv);
ui = glade_xml_new ("data/gstplayer.glade", NULL, NULL);
playlist = init_playlist (ui);
filesrc = gst_element_factory_make ("filesrc", "source");
mad = gst_element_factory_make ("mad", "decoder");
audioconvert = gst_element_factory_make ("audioconvert", "converter");
alsasink = gst_element_factory_make ("alsasink", "sink");
if (!filesrc || !mad || !audioconvert || !alsasink)
{
g_print ("Failed to create 1 element");
return -1;
}
pipeline = gst_pipeline_new ("mp3-pipeline");
gst_bin_add_many (GST_BIN (pipeline), filesrc, mad, audioconvert, alsasink, NULL);
if (!gst_element_link_many (filesrc, mad, audioconvert, alsasink, NULL))
g_warning ("Failed to link elements!\n");
/* GTK+ Signal connectors */
widget = glade_xml_get_widget (ui, "MainWindow");
g_signal_connect (G_OBJECT (widget),
"delete_event",
G_CALLBACK (cb_exit),
NULL);
widget = glade_xml_get_widget (ui, "AddButton");
g_signal_connect (G_OBJECT (widget),
"clicked",
G_CALLBACK (cb_add),
playlist);
g_signal_connect (G_OBJECT (playlist),
"row-activated",
G_CALLBACK (cb_row_activated),
NULL);
/* GStreamer Signal connectors */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_signal_watch (bus);
gst_bus_add_watch (bus, cb_bus_messages, NULL);
g_object_unref (bus);
gtk_main ();
return 0;
}