Output
linux 系统下可执行文件。
Brief
多媒体播放器模板,使用 Gtk 构建 ui,FFmpeg做多媒体 utility ,GStreamer做多媒体框架。
结构
.
├── BUILD
├── ButtonHelper.cpp
├── ButtonHelper.h
├── CMakeLists.txt
├── DrawingAreaHelper.cpp
├── DrawingAreaHelper.h
├── layout.ui
└── main.cpp
CMakeLists.txt
# 1) cmake basic
cmake_minimum_required(VERSION 3.12) #cmake version check
set(CXX_STANDARD 17) #c++ standard version)
# 2) project info
#auto generated variables as below:
#PROJECT_NAME: "hello"
#hello_BINARY_DIR: build root dir
#hello_SOURCE_DIR: source root dir
project(hello LANGUAGES C CXX) #project name
message("build root dir: ${hello_BINARY_DIR}")
message("source root dir: ${hello_SOURCE_DIR}")
# 3) specify source files and create target
#SOURCE_FILES: all c cpp and hpp as source file
file(GLOB_RECURSE SOURCE_FILES #glob all source files(c cpp hpp , h is excluded)
${hello_SOURCE_DIR}/*.c
${hello_SOURCE_DIR}/*.cpp
${hello_SOURCE_DIR}/*.hpp
)
list(FILTER SOURCE_FILES EXCLUDE REGEX "CMakeFiles/*") #exclude cmake files from source list
message("source files: ${SOURCE_FILES}")
add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #add executable file
# 4) package dependency (pkg-config)
find_package(PkgConfig REQUIRED)
#GTK_INCLUDE_DIRS : HEADER SERARCH PATHS
#GTK_LIBRARIES : LIBRARY NAME
#GTK_LIBRARY_DIRS : LIBRARY PATHS
pkg_check_modules(GTK REQUIRED gtk+-3.0)
pkg_check_modules(GLIB REQUIRED glib-2.0)
# 5) include and link
include_directories( #head search path
${GTK_INCLUDE_DIRS}
)
link_directories( #library search path
${GTK_LIBRARY_DIRS}
)
target_link_libraries(${PROJECT_NAME} #what libraries needs to link
${GTK_LIBRARIES}
)
# 6) ADD_DEFINITIONS
ADD_DEFINITIONS(-D LINUX)
# 7) install
#install ${PROJECT_NAME} to ~/bin
set(INSTALL_PATH ~/bin)
install(
TARGETS ${PROJECT_NAME}
DESTINATION ${INSTALL_PATH}
)
#install config file to ~/bin
set(INSTALL_PATH ~/bin)
file(GLOB_RECURSE CONFIG_FILES
${hello_SOURCE_DIR}/*.ui
${hello_SOURCE_DIR}/*.ini
${hello_SOURCE_DIR}/*.conf
)
install(
FILES ${CONFIG_FILES}
DESTINATION ${INSTALL_PATH}
)
.gitignore
# ignore all first
*
# exception of "ignore all" , files with specific appendix
!*.cpp
!*.h
!*.txt
!*.ui
# exception of "ignore all" , files with specific appendix in specific dir
#!src/*.cpp
#!docs/*.md
基础代码
layout.ui
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="main_window">
<property name="title">GTK Video Player</property>
<property name="default-width">1200</property>
<property name="default-height">600</property>
<child>
<object class="GtkBox" id="main_hbox">
<property name="orientation">horizontal</property>
<property name="spacing">5</property>
<!-- Left Sidebar with scrollable content -->
<child>
<object class="GtkScrolledWindow" id="scrolled_sidebar">
<property name="width-request">150</property>
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkViewport">
<child>
<object class="GtkBox" id="sidebar">
<property name="orientation">vertical</property>
<property name="spacing">5</property>
<!-- Add 10 Buttons to the sidebar -->
<child>
<object class="GtkButton" id="Start">
<property name="label">Start</property>
</object>
</child>
<child>
<object class="GtkButton" id="Pause">
<property name="label">Pause</property>
</object>
</child>
<child>
<object class="GtkButton" id="Stop">
<property name="label">Stop</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_4">
<property name="label">Button 4</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_5">
<property name="label">Button 5</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_6">
<property name="label">Button 6</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_7">
<property name="label">Button 7</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_8">
<property name="label">Button 8</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_9">
<property name="label">Button 9</property>
</object>
</child>
<child>
<object class="GtkButton" id="button_10">
<property name="label">Button 10</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<!-- Separator between sidebar and drawing area -->
<child>
<object class="GtkSeparator" id="separator">
<property name="orientation">vertical</property>
</object>
</child>
<!-- Center Video Area -->
<child>
<object class="GtkDrawingArea" id="video_area">
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</child>
</object>
</interface>
main.cpp
#include <gtk/gtk.h>
#include "ButtonHelper.h"
#include "DrawingAreaHelper.h"
static void activate(GtkApplication *app, gpointer user_data) {
GtkBuilder *builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "layout.ui", NULL);
GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window"));
bool ret = ButtonHelper::getInstance()->SetUp(builder);
ret = DrawingAreaHelper::getInstance()->SetUp(builder);
gtk_window_set_default_size(GTK_WINDOW(window), 1440, 810); // Set window size
gtk_widget_set_size_request(window, 800, 600); // Set drawing area size
gtk_widget_show_all(window);
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
gtk_main ();
return status;
}
ButtonHelper.h
#ifndef BUTTONHELPER_H
#define BUTTONHELPER_H
#include <gtk/gtk.h>
class ButtonHelper{
private:
ButtonHelper();
~ButtonHelper();
public:
static ButtonHelper* getInstance();
bool SetUp(GtkBuilder *builder);
};
#endif
ButtonHelper.cpp
#include "ButtonHelper.h"
#include <gtk/gtk.h>
#include <cassert>
#include <string>
ButtonHelper::ButtonHelper(){
}
ButtonHelper::~ButtonHelper(){
}
ButtonHelper* ButtonHelper::getInstance(){
static ButtonHelper instance;
return &instance;
}
static void Start (GtkWidget *widget, gpointer data){
g_print ("Start\n");
}
static void Pause (GtkWidget *widget, gpointer data){
g_print ("Pause\n");
}
static void Stop (GtkWidget *widget, gpointer data){
g_print ("Stop\n");
}
bool ButtonHelper::SetUp(GtkBuilder *builder){
GtkWidget *sidebar = GTK_WIDGET(gtk_builder_get_object(builder, "sidebar"));
assert(sidebar);
GList *children = gtk_container_get_children(GTK_CONTAINER(sidebar));
assert(children);
for(GList *iter = children; iter!= NULL; iter = g_list_next(iter)){
GtkWidget *child = GTK_WIDGET(iter->data);
assert(child);
if(GTK_IS_BUTTON(child)){
const char* button_lable;
g_object_get(GTK_BUTTON(child), "label", &button_lable, NULL);
g_print ("button_lable = %s\n", button_lable);
//need to be refined with simpler implementation with Macro/template
if (std::string(button_lable) == "Start"){
g_signal_connect(GTK_BUTTON(child), "clicked", G_CALLBACK(Start), NULL);
}else if(std::string(button_lable) == "Pause"){
g_signal_connect(GTK_BUTTON(child), "clicked", G_CALLBACK(Pause), NULL);
}else if(std::string(button_lable) == "Stop"){
g_signal_connect(GTK_BUTTON(child), "clicked", G_CALLBACK(Stop), NULL);
}
}
}
}
DrawingAreaHelper.h
#ifndef DRAWING_AREA_HELPER_H
#define DRAWING_AREA_HELPER_H
#include <gtk/gtk.h>
class DrawingAreaHelper{
DrawingAreaHelper(); //constructor
~DrawingAreaHelper(); //destructor
public:
static DrawingAreaHelper* getInstance();
bool SetUp(GtkBuilder *builder);
};
#endif
DrawingAreaHelper.cpp
#include "DrawingAreaHelper.h"
#include <gtk/gtk.h>
#include <cassert>
DrawingAreaHelper::DrawingAreaHelper(){
}
DrawingAreaHelper::~DrawingAreaHelper(){
}
DrawingAreaHelper* DrawingAreaHelper::getInstance(){
static DrawingAreaHelper instance;
return &instance;
}
bool DrawingAreaHelper::SetUp(GtkBuilder *builder){
GtkWidget *drawing_area = GTK_WIDGET(gtk_builder_get_object(builder, "video_area"));
assert(drawing_area);
}
使用方法
1)保证根目录下有BUILD目录,如果没有则创建。
2)进入BUILD目录,执行 cmake ..
3)make 构建,make install 把构建结果 install 到 CMakeLists.txt 文件指定的路径。