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);
}
原文地址:https://www.cnblogs.com/wanghao-boke/p/12164797.html