[置顶] 基于Gstreamer和Gtk的一个简单的MP3播放器

安装Gstreamer插件,配置好环境,代码如下:

/*myplayer.c*/
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <signal.h>
#include <string.h>

GstElement *pipeline, *source,*decoder,*sink;
GMainLoop *loop = NULL;  

//暂停恢复开关按钮回调
void toggle_button_callback(GtkWidget *widget,gpointer data)
{
    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
    {
	gst_element_set_state(pipeline,GST_STATE_PAUSED);
	GstStateChangeReturn statechange;
	statechange = gst_element_set_state(pipeline, GST_STATE_PAUSED);
	g_print("Pause\n");
    }
    else
    {
	g_print("pause was pressed\n");
	gst_element_set_state(pipeline,GST_STATE_PLAYING);
	g_print("恢复播放\n");
    }
}

//play回调
void callback_play(GtkWidget *widget,gpointer data)
{
    if(!GST_IS_ELEMENT(pipeline))
    {
	pipeline = gst_pipeline_new ("gst-player");
	source = gst_element_factory_make("filesrc","file-source");	
	decoder = gst_element_factory_make("mad","mad-decoder");
	sink = gst_element_factory_make("autoaudiosink","audio-output");
    }
    g_print("play was pressed\n");
    gst_element_set_state(pipeline,GST_STATE_PLAYING);
    g_print("Running\n");
    g_main_loop_run(loop);
}

//stop回调
void callback_stop(GtkWidget *widget,gpointer data)
{
    GtkWidget *tgbt=data;
    g_print("stop was pressed\n");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tgbt), FALSE);

    gst_element_set_state(pipeline,GST_STATE_NULL);
    g_main_loop_quit(loop); //退出循环
	// gst_object_unref(GST_OBJECT(pipeline));//不用销毁管道
    g_print("Deleting pipeline\n");
    g_print("stop\n");    
}

//关闭回调
void delete_event(GtkWidget *widget,GdkEvent *event,gpointer data)
{   
    if(GST_IS_ELEMENT(pipeline))
    {
    g_main_loop_quit(loop);
        gst_element_set_state(pipeline,GST_STATE_NULL);
    }
    gtk_main_quit();
    g_print("quit was pressed\n");
    g_print("quit\n");
}

//菜单基本回调
static void print_hello(GtkWidget *w,gpointer data)
{
    g_message("Hello\n");
}

GtkWidget *FileSelection;
GtkWidget *ok_button;

char str[100];

//文件选择窗口回调
//Open
void OpenFile(GtkWidget *FileSelection,gpointer data)
{
//先关闭文件
    gst_element_set_state(pipeline,GST_STATE_NULL);
    g_main_loop_quit(loop); 

    GtkWidget *widget =(GtkWidget*)data;
    g_print("%s\n",gtk_file_selection_get_filename(GTK_FILE_SELECTION(widget)));

    strcpy(str,gtk_file_selection_get_filename(GTK_FILE_SELECTION(widget)));
    gtk_widget_destroy(widget);
    g_object_set (G_OBJECT (source),"location",(char*)str,NULL); 
    g_print("fileselection was pressed\n");
}
//Cancel
void callback_fileselection_cancel(GtkWidget *FileSelection,gpointer data)
{
    GtkWidget * widget = (GtkWidget*)data;
    gtk_widget_destroy(widget);
    g_print("fileselection cancel was pressed\n");
    g_print("fileselection quit\n");
}

//文件选择构件
void button_event(GtkWidget *widget,gpointer *data)
{
    FileSelection=gtk_file_selection_new("select file");
    gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSelection),"*.mp3");
    g_signal_connect(G_OBJECT(((GtkFileSelection*)FileSelection)->ok_button),"clicked",G_CALLBACK(OpenFile),FileSelection);
    g_signal_connect(G_OBJECT(((GtkFileSelection*)FileSelection)->cancel_button),"clicked",G_CALLBACK(callback_fileselection_cancel),FileSelection);				
    gtk_widget_show(FileSelection);
}

//MENU
static GtkItemFactoryEntry menu_items[]={
    {	"/_File",	    NULL,	    	NULL,0,"<Branch>"},
    {	"/File/_Open",	"<control>O",   button_event,0,NULL},
    {	"/File/_Quit",	"<control>Q",   delete_event,0,NULL},
    {	"/_Help",	    NULL,	    	NULL,0,"<Branch>"},
    {	"/_Help/About",	NULL,	    	NULL,0,NULL},
};

void get_main_menu(GtkWidget *window,GtkWidget **menubar)
{
    GtkItemFactory *item_factory;
    GtkAccelGroup *accel_group;
    gint nmenu_items=sizeof(menu_items)/sizeof(menu_items[0]);
    accel_group=gtk_accel_group_new();
    item_factory=gtk_item_factory_new(GTK_TYPE_MENU_BAR,"<main>",accel_group);
    gtk_item_factory_create_items(item_factory,nmenu_items,menu_items,NULL);
    gtk_window_add_accel_group(GTK_WINDOW(window),accel_group);
    if(menubar)
	*menubar=gtk_item_factory_get_widget(item_factory,"<main>");
}

static gboolean bus_call(GstBus *bus,GstMessage *msg,gpointer data)
{
    GMainLoop *loop=data;
    switch (GST_MESSAGE_TYPE(msg))
    {
	case GST_MESSAGE_EOS:
	    g_print("End-of_stream\n");
	    g_main_loop_quit(loop);
	    break;
	case GST_MESSAGE_ERROR:
	{
	    gchar *debug;
	    GError *err;
	    gst_message_parse_error(msg,&err,&debug);
	    g_free(debug);
	    g_print("Error: %s\n",err->message);
	    g_error_free(err);
	    g_main_loop_quit(loop);
	    break;
	}
	default:
	    break;
    }
    return TRUE;
}

static void new_pad(GstElement *element,GstPad *pad,gpointer data)
{
    GstPad *sinkpad;
    g_print ("Dynamic pad created,linking parser/decoder\n");
    sinkpad=gst_element_get_pad(decoder,"sink");
    gst_pad_link(pad,sinkpad);
    gst_object_unref(sinkpad);
}

int main(int argc,char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *table;
    GtkWidget *toggle_button;
   
    gtk_init(&argc,&argv);

    window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),"MP3 Player");
    gtk_widget_set_size_request(GTK_WIDGET(window),300,60);
    g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL);      

	//menu创建
    GtkWidget *main_vbox;
    GtkWidget *menubar;
    main_vbox=gtk_vbox_new(FALSE,1);
    gtk_container_add(GTK_CONTAINER(window),main_vbox);
    
    get_main_menu(window,&menubar);
    gtk_box_pack_start(GTK_BOX(main_vbox),menubar,FALSE,TRUE,0);
    gtk_widget_show(menubar);
    gtk_widget_show(main_vbox);   
   
    table = gtk_hbox_new(0, 3);
	gtk_box_pack_start_defaults(GTK_BOX(main_vbox), table);  	
   	gtk_widget_set_size_request(GTK_WIDGET(table),300,30);  

    button=gtk_button_new_with_label("播放");
    g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback_play),(gpointer)"播放");
    gtk_box_pack_start_defaults(GTK_BOX(table), button);
    gtk_widget_show(button);
        
    toggle_button=gtk_toggle_button_new_with_label("暂停/恢复");
    g_signal_connect(G_OBJECT(toggle_button),"clicked",G_CALLBACK(toggle_button_callback),(gpointer)"暂停/恢复");
   	gtk_box_pack_start_defaults(GTK_BOX(table), toggle_button);
    gtk_widget_show(toggle_button);

    button=gtk_button_new_with_label("停止");
    g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(callback_stop),(gpointer)toggle_button);
    gtk_box_pack_start_defaults(GTK_BOX(table), button);
    gtk_widget_show(button);

    gtk_widget_show(table);
    gtk_widget_show(window);

	//gst部分
    GstBus *bus;

	//初始化
    gst_init (&argc,&argv);
    loop=g_main_loop_new(NULL,FALSE);
/*
//检查输入
    if(argc!=2)
    {
	g_print("Usage: %s<Mp3/Vorbis filename>\n",argv[0]);
	return -1;
    }
 */   
	//创建元件
    pipeline = gst_pipeline_new("audio-player");
    source = gst_element_factory_make("filesrc","file-source");
    decoder = gst_element_factory_make("mad","mad-decoder");
	sink = gst_element_factory_make("autoaudiosink","audio-output");
	//gst_element_factory_make("alsasink","alsa-output");
       
	//异常处理
   if(!pipeline||!source||!decoder||!sink)
    {
	g_print("One element could not be created\n");
	return -1;
    }
	
    //得到 管道的消息总线
    bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
    //添加消息监视器
    gst_bus_add_watch(bus,bus_call,loop);
    gst_object_unref(bus);
    //把组件添加到管道中.管道是一个特殊的组件,可以更好的让数据流动
    gst_bin_add_many(GST_BIN(pipeline),source,decoder,sink,NULL);
    //依次连接组件
    gst_element_link_many(source,decoder,sink,NULL);
    
    //开始播放
    g_print("Running\n");                 
    g_signal_connect(decoder,"pad_added",G_CALLBACK(new_pad),NULL);
    
    gtk_main();
    return 0;
}

终端里编译:

gcc -o myplayer myplayer.c `pkg-config --cflags --libs gtk+-2.0` `pkg-config --cflags --libs gstreamer-0.10`

运行:

 ./myplayer

运行结果如图:




你可能感兴趣的:(object,null,callback,button,Signal,gtk)