GTK開發視頻播放器


按照第三方庫和軟件包:

 sudo apt-get install libgtk-3-dev
 sudo apt-get install libgtk-3-doc
 sudo apt-get install vlc libvlc-dev

其中使用了gtk第三方庫,具體API請看官網https://developer.gnome.org/gtk3/stable/index.html

 

gtk構建gtk界面

#include<gtk/gtk.h>
#include<gdk/gdkx.h>
#include<glib.h>

#define BORDER_WIDTH 6

int main(int argc, char *argv[])
{
    GtkWidget *window,
                *vbox,
                *hbox,
                *menubar,
                *filemenu,
                *fileitem,
                *filemenu_openitem,
                *hbuttonbox,
                *player_widget,
                *stop_button,
                *full_screen_button,
                *preocess_scale,
                *playpause_button,
                *process_scale,
                *play_icon_image,
                *pause_icon_image,
                *stop_icon_image;
    GtkAdjustment *process_adjust;

    /*
    每個gtk程序都必須要有的
    *兩個參數對應main函數的兩個參數
    *用於在命令行執行程序時解析參數
    */
    gtk_init(&argc, &argv);

    /*
    創建一個window並完成初始化,如設置為頂層窗口,寬度和高度、標題等
    *並綁定destroy信號,以便在關閉gtk窗口時程序可以完全退出
    */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 0);
    gtk_window_set_title(GTK_WINDOW(window), "GTK+ libVLC Demo");

    /*
    * 創建一個方向垂直間距為0的box容器,並添加到前面創建的window里
    */
    vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add(GTK_CONTAINER(window), vbox);

    /*
    * 創建一個menubar和兩個menuitem分別為菜單里“文件”和“打開”
    * 由於他們是上下級菜單的關系
    * 所以需要一個單獨menu來防止“open_menu_item”,也就是代碼中的filemenu_openitem
    * */
    menubar = gtk_menu_bar_new();
    fileitem = gtk_menu_item_new_with_label("File");
    filemenu_openitem = gtk_menu_item_new_with_label("Open");
    filemenu = gtk_menu_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), filemenu_openitem);

    /*
    * 將filemenu設置為上一級fileitem的子菜單,
    * 然后將fileitem添加到menumbar,最后將menumbar添加到vbox中
    * */
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileitem), filemenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileitem);
    gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);

    /*
    *創建一個draw_area控件,用作視頻播放顯示區域,並放進vbox中
    * */
    player_widget = gtk_drawing_area_new();
    gtk_box_pack_start(GTK_BOX(vbox), player_widget, TRUE, TRUE, 0);

    /*
    *再創建一個hbox作為vbox的子容器,一個hbuttonbox作為hbox的子容器
    * hbutton里面放置兩個button
    * 再將一個scale(滾動條,用作視頻播放進度條)添加到hbox,再將hbox放到最外面的vbox中
    * */
    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    hbuttonbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
    gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox), BORDER_WIDTH);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_START);

    playpause_button = gtk_button_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON);
    stop_button = gtk_button_new_from_icon_name("media-playback-stop", GTK_ICON_SIZE_BUTTON);

    gtk_box_pack_start(GTK_BOX(hbuttonbox), playpause_button, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), stop_button, FALSE, FALSE, 0);  
    gtk_box_pack_start(GTK_BOX(hbox), hbuttonbox, FALSE, FALSE, 0); 

    process_adjust = gtk_adjustment_new(0.00, 0.00, 100.00, 1.00, 0.00, 0.00);
    process_scale = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, process_adjust);
    gtk_box_pack_start(GTK_BOX(hbox), process_scale, TRUE, TRUE, 0);
    gtk_scale_set_draw_value (GTK_SCALE(process_scale), FALSE);
    gtk_scale_set_has_origin (GTK_SCALE(preocess_scale), 0);
    gtk_scale_set_value_pos(GTK_SCALE(process_scale), 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);

    //顯示所有控件,並運行gtk程序
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

編譯運行:

gcc gui.c -o gui `pkg-config --libs --cflags gtk+-3.0`

./gui

運行結果:

 

播放視頻:
在以上代碼基礎上添加播放視頻功能:

makefiel

CFLAGS=`pkg-config --cflags gtk+-3.0 libvlc`
LIBS=`pkg-config --libs gtk+-3.0 libvlc`

all:
    gcc vlcgtk.c -o vlcgtk -Wall $(LIBS) $(CFLAGS)
clean:
    rm vlcgtk

 

源碼

#include<stdlib.h>
#include<gtk/gtk.h>
#include<gdk/gdkx.h>
#include<glib.h>
#include <glib/gi18n.h>
#include<vlc/vlc.h>

#define BORDER_WIDTH 6

void destroy(GtkWidget *widget, gpointer data);
void player_widget_on_realize(GtkWidget *widget, gpointer data);
void on_open(GtkWidget *widget, gpointer data);
void open_media(const char *uri);
void on_playpause(GtkWidget *widget, gpointer data);
void on_stop(GtkWidget *widget, gpointer data);
void play(void);
void pause_player(void);

gboolean _update_scale(gpointer data);
void on_value_change(GtkWidget *widget, gpointer data);

libvlc_media_t *media;
libvlc_media_player_t *media_player;
//libvlc_instance_t *vlc_inst;
libvlc_instance_t *vlc_inst;

GtkWidget *playpause_button, *play_icon_image, *pause_icon_image, *stop_icon_image,
            *process_scale;
GtkAdjustment *process_adjueset;

float video_length, current_play_time;

int main(int argc, char *argv[])
{
    GtkWidget *window,
                *vbox,
                *hbox,
                *menubar,
                *filemenu,
                *fileitem,
                *filemenu_openitem,
                *player_widget,
                *hbuttonbox,
                *stop_button;
    
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
    g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 0);
    gtk_window_set_title(GTK_WINDOW(window), "GTK+ libVLC Demo");

    vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, FALSE);
    gtk_container_add(GTK_CONTAINER(window), vbox);
    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, FALSE);

    menubar = gtk_menu_bar_new();
    filemenu = gtk_menu_new();
    fileitem = gtk_menu_item_new_with_label("File");
    filemenu_openitem = gtk_menu_item_new_with_label("Open");
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), filemenu_openitem);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileitem), filemenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileitem);

    gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
    g_signal_connect(filemenu_openitem, "activate", G_CALLBACK(on_open), window);

    player_widget = gtk_drawing_area_new();
    gtk_box_pack_start(GTK_BOX(vbox), player_widget, TRUE, TRUE, 0);

    playpause_button = gtk_button_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON);
    stop_button = gtk_button_new_from_icon_name("media-playback-stop", GTK_ICON_SIZE_BUTTON);

    //信號處理函數
    g_signal_connect(playpause_button, "clicked", G_CALLBACK(on_playpause), NULL);
    g_signal_connect(stop_button, "clicked", G_CALLBACK(on_stop), NULL);

    hbuttonbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
    gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox), BORDER_WIDTH);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_START);

    gtk_box_pack_start(GTK_BOX(hbuttonbox), playpause_button, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), stop_button, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), hbuttonbox, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), hbox, FALSE, TRUE, 0);

    vlc_inst = libvlc_new(0, NULL);
    media_player = libvlc_media_player_new(vlc_inst);
    g_signal_connect(G_OBJECT(player_widget), "realize", 
                    G_CALLBACK(player_widget_on_realize), media_player);
                                
    process_adjueset = gtk_adjustment_new(0.00, 0.00, 100.00, 1.00, 0.00, 0.00);
    process_scale = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, process_adjueset);

    gtk_box_pack_start(GTK_BOX(hbox), process_scale, TRUE, TRUE, 0);
    gtk_scale_set_draw_value (GTK_SCALE(process_scale), FALSE);
    gtk_scale_set_has_origin(GTK_SCALE(process_scale), TRUE);
    gtk_scale_set_value_pos(GTK_SCALE(process_scale), 5);
    g_signal_connect(G_OBJECT(process_scale), "value_changend", G_CALLBACK(on_value_change), NULL);

    gtk_widget_show_all(window);
    gtk_main();

    libvlc_media_player_release(media_player);
    libvlc_release(vlc_inst);
    return 0;
}

void destroy(GtkWidget *widget, gpointer data)
{
    gtk_main_quit();
}

void player_widget_on_realize(GtkWidget *widget, gpointer data)
{
    libvlc_media_player_set_xwindow((libvlc_media_player_t*)data, GDK_WINDOW_XID(gtk_widget_get_window(widget)));
}

//信號處理函數
void on_open(GtkWidget *widget, gpointer data)
{
    GtkWidget *dialog;
    GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;

    dialog = gtk_file_chooser_dialog_new("open file", GTK_WINDOW(widget), action, 
                _("Cancle"), GTK_RESPONSE_CANCEL, _("Open"), GTK_RESPONSE_ACCEPT, NULL);

    if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
    {
        char *uri;
        uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
        open_media(uri);
        g_free(uri);
    }

    gtk_widget_destroy(dialog);
}

//傳入視頻文件uri,使用libvlc播放視頻文件
void open_media(const char *uri)
{

    media = libvlc_media_new_location(vlc_inst, uri);
    libvlc_media_player_set_media(media_player, media);

    current_play_time = 0.0f;
    gtk_scale_set_value_pos(GTK_SCALE(process_scale), current_play_time);
    play();
    g_timeout_add(500, _update_scale, process_scale);
    libvlc_media_release(media);
}

//使用libvlc傳入當前的播放器,獲取播放狀態
void on_playpause(GtkWidget *widget, gpointer data)
{
    if (libvlc_media_player_is_playing(media_player) == 1)
    {
        pause_player();
    }
    else
    {
        play();
    }
    
}

void on_stop(GtkWidget *widget, gpointer data)
{
    pause_player();
    libvlc_media_player_stop(media_player);
}

//該函數為一個GSourceFunc函數類型,要求必須要有返回值,返回類型為gboolen
//如果下次繼續執行該定時,須返回`G\_SOURCE\_CONTINUE`,否則返回`G\_SOURCE\_REMOVE`
gboolean _update_scale(gpointer data)
{
    video_length = libvlc_media_player_get_length(media_player);
    current_play_time = libvlc_media_player_get_time(media_player);

    g_signal_handlers_block_by_func(G_OBJECT(process_scale), on_value_change, NULL);
    gtk_adjustment_set_value(process_adjueset, current_play_time/video_length*100);
    g_signal_handlers_unblock_by_func(G_OBJECT(process_scale), on_value_change, NULL);
    return G_SOURCE_CONTINUE;
}

//通過adjuest對象獲取拖動到的進度數值(根據之前設定為1-100的范圍)
//然后使用libvlc設定播放位置(根據百分百設定,故要除以100)
void on_value_change(GtkWidget *widget, gpointer data)
{
    float scale_value = gtk_adjustment_get_value(process_adjueset);
    libvlc_media_player_set_position(media_player, scale_value/100);
}

//play函數播放視頻,並將播放按鈕的圖標換成暫停的圖標
void play(void)
{
    libvlc_media_player_play(media_player);
    pause_icon_image = gtk_image_new_from_icon_name("media-playback-pause", GTK_ICON_SIZE_BUTTON);
    gtk_button_set_image(GTK_BUTTON(playpause_button), pause_icon_image);
}

void pause_player(void)
{
    libvlc_media_player_pause(media_player);
    play_icon_image = gtk_image_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON);
    gtk_button_set_image(GTK_BUTTON(playpause_button), play_icon_image);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM