Created
April 1, 2014 04:28
-
-
Save dradtke/9907728 to your computer and use it in GitHub Desktop.
Full working example from "Message Passing in C."
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <glib.h> | |
| #include <gtk/gtk.h> | |
| #include <libsoup/soup.h> | |
| #define PORT 42025 | |
| /* --- App --- */ | |
| typedef struct { | |
| GtkWidget *window; | |
| SoupServer *server; | |
| GAsyncQueue *channel; | |
| } App; | |
| /* --- Message --- */ | |
| typedef enum { | |
| MESSAGE_CHANGE_TITLE | |
| } message_type_t; | |
| typedef struct { | |
| message_type_t type; | |
| gpointer data; | |
| } Message; | |
| void free_message(Message *msg) | |
| { | |
| if (msg->data) | |
| g_free(msg->data); | |
| g_free(msg); | |
| } | |
| /* --- Routes --- */ | |
| static void route_change_title(SoupServer *server, | |
| SoupMessage *soup_msg, | |
| const char *path, | |
| GHashTable *query, | |
| SoupClientContext *client, | |
| gpointer user_data) | |
| { | |
| App *app = (App*)user_data; | |
| char *new_title = g_strdup(path + 15); | |
| Message *msg = g_new(Message, 1); | |
| msg->type = MESSAGE_CHANGE_TITLE; | |
| msg->data = new_title; | |
| g_async_queue_push(app->channel, msg); | |
| soup_message_set_status(soup_msg, SOUP_STATUS_OK); | |
| } | |
| /* --- Idle --- */ | |
| static gboolean on_idle(gpointer user_data) | |
| { | |
| App *app = (App*)user_data; | |
| Message *msg; | |
| if ((msg = g_async_queue_try_pop(app->channel)) != NULL) { | |
| switch (msg->type) { | |
| case MESSAGE_CHANGE_TITLE: | |
| gtk_window_set_title(GTK_WINDOW(app->window), (char*)msg->data); | |
| break; | |
| } | |
| free_message(msg); | |
| } | |
| return TRUE; | |
| } | |
| /* --- Server --- */ | |
| static gpointer server_main(gpointer user_data) | |
| { | |
| App *app = (App*)user_data; | |
| GMainContext *context = g_main_context_new(); | |
| app->server = soup_server_new( | |
| SOUP_SERVER_PORT, PORT, | |
| SOUP_SERVER_ASYNC_CONTEXT, context, | |
| NULL | |
| ); | |
| if (!app->server) | |
| return NULL; | |
| g_async_queue_ref(app->channel); | |
| soup_server_add_handler(app->server, "/gui/set-title/", route_change_title, app, NULL); | |
| g_print("listening on port %d\n", soup_server_get_port(app->server)); | |
| soup_server_run(app->server); | |
| g_print("shutting down server\n"); | |
| g_async_queue_unref(app->channel); | |
| return NULL; | |
| } | |
| /* --- GUI --- */ | |
| static void gui_main(int *argc, char **argv[], App *app) | |
| { | |
| gtk_init(argc, argv); | |
| app->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
| g_signal_connect(app->window, "destroy", gtk_main_quit, NULL); | |
| gtk_widget_show_all(app->window); | |
| gtk_main(); | |
| } | |
| /* --- Main --- */ | |
| int main(int argc, char *argv[]) | |
| { | |
| App *app = g_new(App, 1); | |
| app->channel = g_async_queue_new(); | |
| g_async_queue_ref(app->channel); | |
| /* Start the server in a new thread */ | |
| GThread *server_thread = g_thread_new("server", server_main, app); | |
| /* Idly listen for server requests */ | |
| g_idle_add(on_idle, app); | |
| /* Start the GUI (needs to be done in the main thread) */ | |
| gui_main(&argc, &argv, app); | |
| soup_server_quit(app->server); | |
| g_thread_join(server_thread); | |
| g_async_queue_unref(app->channel); | |
| g_free(app); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment