Već duže vrijeme sakupljam kako stvari/djelove tako i programe/alate za realizaciju jednog skromnog projekta. Veliki sam poštovaoc softwarea pod GPL licencom tako da će i ovaj moj projekat biti dostupan pod uslovima koji su navedeni u GPL licenci. Dakle želim da napravim RC autić na kom će da se nalazi ruter koji je flešovan sa OperWrt/LEDE firmwareom i na kom će da bude prikopčana IP kamera čiji stream možete da gledate u web pretraživaču u realnom vremenu. Takođe na lap-topu će da se nalazi mala GUI aplikacija napisana u C/GTK-u momoću koje će mo da upravljamo RC autićem. Server koji će da se nalazi na ruteru možete da pogledate u mom predhodom postu Kako dodati aplikaciju u OpenWrt-u pa ću u ovom postu samo objaviti kod GUI aplikacije koja će da se nalazi na lap-top računaru
#include
#include
#include
#include
#include
GtkWidget *button_l;
GtkWidget *button_r;
GtkWidget *button_up;
GtkWidget *connect_button;
GtkWidget *label1;
GtkWidget *ip_entry;
gboolean left_arrow_pressed = FALSE;
gboolean right_arrow_pressed = FALSE;
gboolean up_arrow_pressed = FALSE;
guint key_check_timer = 0;
int sock = -1;
pthread_t recv_thread;
void *recv_thread_func(void *arg) {
char buffer[1024] = {0};
while (1) {
int valread = read(sock, buffer, 1024);
if (valread > 0) {
buffer[valread] = '\0';
gdk_threads_add_idle((GSourceFunc)gtk_label_set_text, label1);
gdk_threads_add_idle((GSourceFunc)g_strdup_printf, g_strdup(buffer));
} else {
break;
}
}
return NULL;
}
void send_message(const char *message) {
if (sock != -1) {
send(sock, message, strlen(message), 0);
}
}
void set_button_icon(GtkWidget *button, const gchar *icon_name) {
GdkPixbuf *icon = gdk_pixbuf_new_from_file(icon_name, NULL);
if (icon == NULL) {
g_printerr("Error loading image: %s\n", icon_name);
return;
}
GtkWidget *current_image_widget = gtk_button_get_image(GTK_BUTTON(button));
GtkWidget *new_image = gtk_image_new_from_pixbuf(icon);
gtk_button_set_image(GTK_BUTTON(button), new_image);
g_object_unref(icon);
if (current_image_widget != NULL && GTK_IS_IMAGE(current_image_widget)) {
GdkPixbuf *current_pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(current_image_widget));
if (current_pixbuf != NULL && G_IS_OBJECT(current_pixbuf)) {
g_object_unref(current_pixbuf);
}
}
}
gboolean check_key_states(gpointer user_data) {
if (left_arrow_pressed) {
send_message("left");
g_print("Left arrow key held down.\n");
}
if (right_arrow_pressed) {
send_message("right");
g_print("Right arrow key held down.\n");
}
if (up_arrow_pressed) {
send_message("up");
g_print("Up arrow key held down.\n");
}
return TRUE;
}
gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
if (event->keyval == GDK_KEY_Left) {
if (!left_arrow_pressed) {
left_arrow_pressed = TRUE;
g_print("Left arrow key pressed.\n");
set_button_icon(button_l, "pressed_icon_l.png");
}
return TRUE;
} else if (event->keyval == GDK_KEY_Right) {
if (!right_arrow_pressed) {
right_arrow_pressed = TRUE;
g_print("Right arrow key pressed.\n");
set_button_icon(button_r, "pressed_icon_r.png");
}
return TRUE;
} else if (event->keyval == GDK_KEY_Up) {
if (!up_arrow_pressed) {
up_arrow_pressed = TRUE;
g_print("Up arrow key pressed.\n");
set_button_icon(button_up, "pressed_icon_up.png");
}
return TRUE;
}
return FALSE;
}
gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {
if (event->keyval == GDK_KEY_Left) {
left_arrow_pressed = FALSE;
set_button_icon(button_l, "initial_icon_l.png");
return TRUE;
} else if (event->keyval == GDK_KEY_Right) {
right_arrow_pressed = FALSE;
set_button_icon(button_r, "initial_icon_r.png");
return TRUE;
} else if (event->keyval == GDK_KEY_Up) {
up_arrow_pressed = FALSE;
set_button_icon(button_up, "initial_icon_up.png");
return TRUE;
}
return FALSE;
}
void set_label_color(GtkWidget *label, const gchar *color) {
GtkCssProvider *provider = gtk_css_provider_new();
gchar *css = g_strdup_printf("label { color: %s; }", color);
gtk_css_provider_load_from_data(provider, css, -1, NULL);
GtkStyleContext *context = gtk_widget_get_style_context(label);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
g_free(css);
g_object_unref(provider);
}
void on_connect_button_clicked(GtkWidget *widget, gpointer user_data) {
if (sock == -1) {
const gchar *ip_address = gtk_entry_get_text(GTK_ENTRY(ip_entry));
struct sockaddr_in serv_addr;
fd_set fdset;
struct timeval tv;
int flags, res, valopt;
socklen_t lon;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
g_printerr("Socket creation error\n");
return;
}
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5555);
if (inet_pton(AF_INET, ip_address, &serv_addr.sin_addr) <= 0) {
g_printerr("Invalid address/ Address not supported\n");
return;
}
res = connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (res < 0) {
if (errno == EINPROGRESS) {
FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_sec = 5; // 5 seconds timeout
tv.tv_usec = 0;
res = select(sock + 1, NULL, &fdset, NULL, &tv);
if (res < 0 && errno != EINTR) {
g_printerr("Select error\n");
close(sock);
sock = -1;
return;
} else if (res > 0) {
lon = sizeof(int);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
g_printerr("getsockopt error\n");
close(sock);
sock = -1;
return;
}
if (valopt) {
g_printerr("Connection error: %d - %s\n", valopt, strerror(valopt));
close(sock);
sock = -1;
gtk_label_set_text(GTK_LABEL(label1), "Server not found");
set_label_color(label1, "red");
return;
}
} else {
g_printerr("Connection timed out\n");
close(sock);
sock = -1;
gtk_label_set_text(GTK_LABEL(label1), "Server not found");
set_label_color(label1, "red");
return;
}
} else {
g_printerr("Connection error\n");
close(sock);
sock = -1;
return;
}
}
fcntl(sock, F_SETFL, flags); // Set back to blocking mode
gtk_button_set_label(GTK_BUTTON(connect_button), "Disconnect");
gtk_label_set_text(GTK_LABEL(label1), "Connected");
set_label_color(label1, "green");
send_message("HI");
if (pthread_create(&recv_thread, NULL, recv_thread_func, NULL) != 0) {
g_printerr("Failed to create receive thread\n");
}
} else {
close(sock);
sock = -1;
gtk_button_set_label(GTK_BUTTON(connect_button), "Connect");
gtk_label_set_text(GTK_LABEL(label1), "Disconnected");
set_label_color(label1, "red");
pthread_cancel(recv_thread);
}
}
int main(int argc, char *argv[]) {
GtkBuilder *builder;
GtkWidget *window;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "GladeUI_3.glade", NULL);
gtk_builder_connect_signals(builder, NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
button_l = GTK_WIDGET(gtk_builder_get_object(builder, "button_l"));
button_r = GTK_WIDGET(gtk_builder_get_object(builder, "button_r"));
button_up = GTK_WIDGET(gtk_builder_get_object(builder, "button_up"));
connect_button = GTK_WIDGET(gtk_builder_get_object(builder, "connect"));
label1 = GTK_WIDGET(gtk_builder_get_object(builder, "label1"));
ip_entry = GTK_WIDGET(gtk_builder_get_object(builder, "ip_adress"));
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_default_size(GTK_WINDOW(window), 600, 500);
set_button_icon(button_l, "initial_icon_l.png");
set_button_icon(button_r, "initial_icon_r.png");
set_button_icon(button_up, "initial_icon_up.png");
g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL);
g_signal_connect(window, "key-release-event", G_CALLBACK(on_key_release), NULL);
g_signal_connect(connect_button, "clicked", G_CALLBACK(on_connect_button_clicked), NULL);
key_check_timer = g_timeout_add(100, check_key_states, NULL);
gtk_widget_show(window);
gtk_main();
g_object_unref(builder);
if (sock != -1) {
close(sock);
}
return 0;
}
Sledeći kod je iz GUI builder koji se zove Glade, samo ga sačuvajte pod imenom GladeUI_3.glade
I da olakšamo sebi život tu je i Makefile
PROG = gtk_tcp_client_with_timeout
CC = gcc
CFLAGS = `pkg-config --cflags gtk+-3.0`
LIBS = `pkg-config --libs gtk+-3.0`
${PROG}: ${PROG}.c
${CC} $(CFLAGS) -o ${PROG} ${PROG}.c ${LIBS} -export-dynamic -rdynamic
clean:
rm ${PROG}
I tu je 6 sličica koje grafički prikazuju da je strelica pritisnuta






Нема коментара:
Постави коментар