#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)
{
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);
gdk_pixbuf_loader_close(pixbuf_loader, NULL);
pixbuf = gdk_pixbuf_loader_get_pixbuf(pixbuf_loader);
/*����cairo*/
cr = gdk_cairo_create(c->video_area->window);
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
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 ", 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));
port = atoi(gtk_entry_get_text(GTK_ENTRY(c->port_entry)));
c->sock = tcp_init_net(ip,port);
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));
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("连接到:");
gtk_box_pack_start_defaults(GTK_BOX(box), label);
entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry), DEF_CONN_IP);
gtk_entry_set_max_length(GTK_ENTRY(entry), 15);
gtk_box_pack_start_defaults(GTK_BOX(box), entry);
c->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)
{
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);
/* 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)));
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;
/* fullscreen */
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));
/* 窗口边框大小设置为0 */
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;
}