Skip to content

Instantly share code, notes, and snippets.

@dradtke
Created April 1, 2014 04:28
Show Gist options
  • Select an option

  • Save dradtke/9907728 to your computer and use it in GitHub Desktop.

Select an option

Save dradtke/9907728 to your computer and use it in GitHub Desktop.
Full working example from "Message Passing in C."
#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