<span style="font-size:14px;">#include "wcam.h"
__u64 clock_get_time_us()
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (__u64)ts.tv_sec * 1000000LL + (__u64)ts.tv_nsec / 1000LL;
}
void draw_video_frame(const void *p, int size, void *arg)//该显示函数用于net.c中
{
struct wcam_win *c = arg;
GdkPixbufLoader *pixbuf_loader;
GdkPixbuf *pixbuf;
GdkPixbuf *pixbuf4fullscreen = NULL;
GdkScreen *screen;
cairo_t *cr;
gchar outstr[100];
gfloat fps;
guint64 now_us;
gdk_threads_enter();
/* update frame size label */
sprintf(outstr, "%d 瀛楄妭", size);
gtk_label_set_text(GTK_LABEL(c->frmsize_label), outstr);
/* update fps label */
c->frm_cnt++;
if (c->frm_cnt == 1) {
c->last_twenty_frm_us = clock_get_time_us();
} else if (c->frm_cnt > 10) {
now_us = clock_get_time_us();
fps = 10.0 * 1000000.0 / (now_us - c->last_twenty_frm_us);
c->frm_cnt = 0;
sprintf(outstr, "%2.1f 甯?绉?, fps);
gtk_label_set_text(GTK_LABEL(c->fps_label), outstr);
}
/* update video */
pixbuf_loader = gdk_pixbuf_loader_new();
gdk_pixbuf_loader_write(pixbuf_loader, p, size, NULL); //将图像写入pixbuf_loader中
gdk_pixbuf_loader_close(pixbuf_loader, NULL);
pixbuf = gdk_pixbuf_loader_get_pixbuf(pixbuf_loader); //将图像写入pixbuf中
/*创建cairo*/
cr = gdk_cairo_create(c->video_area->window);//创建一个图像显示窗口
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);//将pixbuf中的图像导入显示窗口
cairo_paint(cr);//绘制图像到窗口上
cairo_destroy(cr);
g_object_unref(pixbuf_loader);
if (pixbuf4fullscreen)
g_object_unref(pixbuf4fullscreen);
gdk_threads_leave();
if (c->need_snapshot) { /* Maybe we should open a file_save_dialog here */
char img_path[100]; /* or maybe we should make the image_storage_path Configurable */
FILE *fp;
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
strftime(outstr, sizeof(outstr), "%F-%T", tmp);
printf(SNAPSHOT_PATH"/webcam-%s.jpg\n", outstr);
printf(SNAPSHOT_PATH"/webcam-%s.jpg", outstr);
sprintf(img_path, SNAPSHOT_PATH"/webcam-%s.jpg", outstr);
fp = fopen(img_path, "w");
fwrite(p, size, 1, fp);
fclose(fp);
c->need_snapshot = FALSE;
}
}
static void connect_handler(GtkButton *button, gpointer data)
{
struct entry_win *c = data;
const gchar *ip;
gint16 port;
ip = gtk_entry_get_text(GTK_ENTRY(c->ip_entry));//获取ip地址
port = atoi(gtk_entry_get_text(GTK_ENTRY(c->port_entry)));//获取端口
c->sock = tcp_init_net(ip,port);//连接ip和端口并返回sock描述符
c->connected = TRUE;
gtk_main_quit(); //窗口退出
}
static gboolean logo_draw(struct entry_win *c, GtkWidget* box)
{
gtk_box_pack_start_defaults(GTK_BOX(box), gtk_image_new_from_file(LOGO_IMG));//logo在wcam.h有地址
gtk_box_pack_start_defaults(GTK_BOX(box), gtk_image_new_from_file(LOGO_IMG1));//修改很方便
return TRUE;
}
static gboolean entry_area_draw(struct entry_win *c, GtkWidget* box)
{
GtkWidget *label;
GtkWidget *entry;
/* Connect to */
label = gtk_label_new("杩炴帴鍒?");//窗口边的serverip字符,"杩炴帴鍒?"不知是什么原因改变了
gtk_box_pack_start_defaults(GTK_BOX(box), label);
entry = gtk_entry_new();//创建窗口
gtk_entry_set_text(GTK_ENTRY(entry), DEF_CONN_IP);//创建entry标签text,DEF_CONN_IP在wcam.h中定义好了
gtk_entry_set_max_length(GTK_ENTRY(entry), 15);//文本entry最大长度
gtk_box_pack_start_defaults(GTK_BOX(box), entry);//把创建好的文本框放到水平容器上
c->ip_entry = entry; //ip_entry取entry字符串
/* Port */
label = gtk_label_new("绔彛:");
gtk_box_pack_start_defaults(GTK_BOX(box), label);
entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry), DEF_PORT);
gtk_entry_set_max_length(GTK_ENTRY(entry), 5);
gtk_box_pack_start_defaults(GTK_BOX(box), entry);
c->port_entry = entry;
return TRUE;
}
static gboolean
button_area_draw(struct entry_win *c, GtkWidget* box)//ok和退出按钮
{
GtkWidget *button;
/* Connect Button */
button = gtk_button_new_with_label("杩炴帴");
gtk_box_pack_start_defaults(GTK_BOX(box), button);
c->connect_button = button;
//按钮关联事件
g_signal_connect(button, "clicked", G_CALLBACK(connect_handler), c);
/* Quit Button */
button = gtk_button_new_with_label("閫€鍑?);
gtk_box_pack_start_defaults(GTK_BOX(box), button);
g_signal_connect(button, "clicked", G_CALLBACK(gtk_main_quit), NULL);
return TRUE;
}
static gboolean entry_win_draw_face(struct entry_win *c)//入口界面
{
GtkWidget *vbox;
GtkWidget *hbox;
vbox = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(c->win), vbox);
/* logo */
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start_defaults(GTK_BOX(vbox), hbox);
logo_draw(c, hbox);//draw函数是关键
/* entry */
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start_defaults(GTK_BOX(vbox), hbox);
entry_area_draw(c, hbox);
/* button */
hbox = gtk_hbutton_box_new();
gtk_box_set_spacing(GTK_BOX(hbox), 5);
gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
gtk_box_pack_start_defaults(GTK_BOX(vbox), hbox);
button_area_draw(c, hbox);
return TRUE;
}
static gboolean key_press_func(GtkWidget* widget, GdkEventKey* key, gpointer data)
{
#define KEY_ENTER 0xff0d
#define KEY_ESC 0xff1b
struct entry_win *c = data;
if (KEY_ENTER == key->keyval)
{
connect_handler(GTK_BUTTON(c->connect_button), c);
return TRUE;
} else if (KEY_ESC == key->keyval)
{
c->connected = FALSE;
gtk_main_quit();
return TRUE;
}
return FALSE;
}
entry_win_t login_create()
{
struct entry_win *c = calloc(1, sizeof(struct entry_win));
if (!c) {
perror("entry_win_create");
return NULL;
}
c->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(c->win), WIN_TITLE);
gtk_window_set_icon(GTK_WINDOW(c->win),
gdk_pixbuf_new_from_file(WIN_ICON, NULL));
gtk_window_set_position(GTK_WINDOW(c->win), GTK_WIN_POS_CENTER);
gtk_window_set_resizable(GTK_WINDOW(c->win), FALSE);
gtk_container_set_border_width(GTK_CONTAINER(c->win), 0);
g_signal_connect(GTK_OBJECT(c->win), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(c->win), "key_press_event",
G_CALLBACK(key_press_func), c);
gtk_widget_set_app_paintable(c->win, TRUE);
entry_win_draw_face(c);
gtk_widget_show_all(c->win);
return c;
}
int login_run(entry_win_t win)
{
struct entry_win *c = win;
gtk_main();//启动入口界面
return c->connected == TRUE ? 0 : -1;
}
void login_hide(entry_win_t win)
{
struct entry_win *c = win;
/*隐藏登录窗口*/
gtk_widget_hide_all(c->win);
}
/*------------主窗口-------------------*/
int entry_win_get_ip(entry_win_t win, char *ip)
{
struct entry_win *c = win;
if (c->connected == FALSE)
return -1;
strcpy(ip, gtk_entry_get_text(GTK_ENTRY(c->ip_entry)));//将ip_entry字符串化拷贝到ip
return 0;
}
int entry_win_get_port(entry_win_t win, char *port)
{
struct entry_win *c = win;
if (c->connected == FALSE)
return -1;
strcpy(port, gtk_entry_get_text(GTK_ENTRY(c->port_entry)));
return 0;
}
void main_quit(GtkWidget *Object, gpointer data)
{
gtk_main_quit();
}
static gboolean
draw_area_draw(struct wcam_win *c, GtkWidget *box)
{
c->video_area = gtk_drawing_area_new();
gtk_widget_set_size_request(c->video_area, c->video_width, c->video_height);
gtk_box_pack_start(GTK_BOX(box), c->video_area, FALSE, FALSE, 0);
gtk_widget_add_events(c->video_area, GDK_BUTTON_PRESS_MASK);
return TRUE;
}
static gboolean info_area_draw(struct wcam_win *c, GtkWidget *box)
{
GtkWidget *frame;
GtkWidget *table;
GtkWidget *label;
GtkWidget *align;
GtkWidget *separator;
gchar buf[256];
frame = gtk_frame_new("淇℃伅鍖?);
c->info_area = frame;
gtk_box_pack_start_defaults(GTK_BOX(box), frame);
table = gtk_table_new(9, 2, FALSE);
gtk_container_add(GTK_CONTAINER(frame), table);
/* VERSION & HOMEPAGE */
label = gtk_label_new("涓婚〉:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
GTK_FILL, GTK_SHRINK, 1, 1);
label = gtk_link_button_new_with_label(WCAM_HOMEPAGE, "www.enjoylinux.cn");
align = gtk_alignment_new(0, 0, 0, 0); /* 宸﹀榻?*/
gtk_container_add(GTK_CONTAINER(align), label);
gtk_table_attach(GTK_TABLE(table), align, 1, 2, 0, 1,
GTK_FILL, GTK_SHRINK, 1, 1);
label = gtk_label_new("鐗堟湰:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
GTK_FILL, GTK_SHRINK, 1, 1);
label = gtk_label_new(WCAM_VERSION);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 1, 2,
GTK_FILL, GTK_SHRINK, 8, 1);
/* IP & PORT */
label = gtk_label_new("鏈嶅姟鍣?");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
GTK_FILL, GTK_SHRINK, 1, 1);
label = gtk_label_new(c->ipaddr);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 2, 3,
GTK_FILL, GTK_SHRINK, 8, 1);
separator = gtk_hseparator_new();
gtk_table_attach(GTK_TABLE(table), separator, 0, 1, 3, 4,
GTK_FILL, GTK_SHRINK, 1, 1);
separator = gtk_hseparator_new();
gtk_table_attach(GTK_TABLE(table), separator, 1, 2, 3, 4,
GTK_FILL | GTK_EXPAND, GTK_SHRINK, 1, 1);
/* Frame Format */
label = gtk_label_new("甯ф牸寮?");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
GTK_FILL, GTK_SHRINK, 1, 1);
sprintf(buf, "%c%c%c%c", (c->video_format)&0xFF,
(c->video_format>>8)&0xFF,
(c->video_format>>16)&0xFF,
(c->video_format>>24)&0xFF);
label = gtk_label_new(buf);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 4, 5,
GTK_FILL, GTK_SHRINK, 8, 1);
/* Frame width x height */
label = gtk_label_new("甯у昂瀵?");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6,
GTK_FILL, GTK_SHRINK, 1, 1);
sprintf(buf, "%d x %d", c->video_width, c->video_height);
label = gtk_label_new(buf);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 5, 6,
GTK_FILL, GTK_SHRINK, 8, 1);
/* Frame Size */
label = gtk_label_new("甯уぇ灏?");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7,
GTK_FILL, GTK_SHRINK, 1, 1);
label = gtk_label_new("0");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 6, 7,
GTK_FILL, GTK_SHRINK, 8, 1);
c->frmsize_label = label;
/* FPS */
label = gtk_label_new("甯ч€熺巼:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 7, 8,
GTK_FILL, GTK_SHRINK, 1, 1);
label = gtk_label_new("0");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 7, 8,
GTK_FILL, GTK_SHRINK, 8, 1);
c->fps_label = label;
/* hseparator */
separator = gtk_hseparator_new();
gtk_table_attach(GTK_TABLE(table), separator, 0, 1, 8, 9,
GTK_FILL, GTK_SHRINK, 1, 1);
separator = gtk_hseparator_new();
gtk_table_attach(GTK_TABLE(table), separator, 1, 2, 8, 9,
GTK_FILL, GTK_SHRINK, 1, 1);
return TRUE;
}
static gboolean main_button_area_draw(struct wcam_win *c, GtkWidget *box)
{
GtkWidget *buttonbox;
GtkWidget *button;
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *image;
buttonbox = gtk_hbutton_box_new();
gtk_box_pack_start(GTK_BOX(box), buttonbox, FALSE, FALSE, 0);
c->button_area = buttonbox;
/* control button */
image = gtk_image_new_from_file(SETTING_BUTTON_IMG);
label = gtk_label_new("鏄剧ず鎺у埗椤?");
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start_defaults(GTK_BOX(hbox), image);
gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(button), hbox);
c->control_area_button = button;
gtk_box_pack_start_defaults(GTK_BOX(buttonbox), button);
/* snapshot button */
image = gtk_image_new_from_file(SNAP_BUTTON_IMG);
label = gtk_label_new("蹇収");
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start_defaults(GTK_BOX(hbox), image);
gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
button = gtk_button_new();
gtk_container_add(GTK_CONTAINER(button), hbox);
gtk_box_pack_start_defaults(GTK_BOX(buttonbox), button);
return TRUE;
}
static gboolean main_win_draw_face(struct wcam_win *c)
{
GtkWidget *box;
GtkWidget *hbox;
GtkWidget *hseparator;
box = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(c->win), box);
/* draw_area & info_area */
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
draw_area_draw(c, hbox);
info_area_draw(c, hbox);
/* hseparator */
hseparator=gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(box), hseparator, FALSE, TRUE, 0);
/* button_area */
main_button_area_draw(c, box);
/* control_area */
// control_area_draw(c, box);
return TRUE;
}
static gboolean main_create(struct wcam_win *c)
{
int len;
/*------------初始化----------------*/
c->video_width = 640;
c->video_height = 480;
/* 全屏 */
c->video_fullscreen = FALSE;
/* ip & port */
entry_win_get_ip(c->entry_win, c->ipaddr);
len = strlen(c->ipaddr);
c->ipaddr[len] = ':';
entry_win_get_port(c->entry_win, &c->ipaddr[len+1]);
c->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/* 璁剧疆绐楀彛鏍囬 */
gtk_window_set_title(GTK_WINDOW(c->win), WIN_TITLE);
gtk_window_set_icon(GTK_WINDOW(c->win),
gdk_pixbuf_new_from_file(WIN_ICON, NULL));
/* 绐楀彛杈规澶у皬璁剧疆涓? */
gtk_container_set_border_width(GTK_CONTAINER(c->win), 0);
g_signal_connect(c->win, "destroy",
G_CALLBACK(main_quit), c);
gtk_widget_set_app_paintable(c->win, TRUE);
main_win_draw_face(c);
gtk_widget_show_all(c->win);
gtk_widget_hide(c->win);
gtk_window_set_position(GTK_WINDOW(c->win), GTK_WIN_POS_CENTER);
gtk_widget_show(c->win);
return TRUE;
}
void main_run( )
{
gtk_main();
}
gint main(gint argc,gchar* argv[])
{
int res;
gtk_init(&argc, &argv);
g_thread_init(NULL);
gdk_threads_init();
struct wcam_win *c = calloc(1, sizeof(struct wcam_win));
c->entry_win = login_create();
res = login_run(c->entry_win);//启动入口界面
if (res == -1) {
goto err_win;
}
login_hide(c->entry_win);//关闭入口界面
net_sys_init(c);//开始接收图像数据
main_create(c);//创建主界面
main_run();//启动主窗口
err_win:
free(c->entry_win);
free(c);
return 0;
}
</span>