Нестандартный ввод событий устройства для GTK

#c #gtk #hardware

#c #gtk #аппаратное обеспечение

Вопрос:

Я использую GTK в качестве пользовательского интерфейса к аппаратному обеспечению (3D-принтеру). Аппаратное обеспечение может создавать события в результате взаимодействия пользователя с машиной (не с графическим интерфейсом). Например, они могут удалить панель сборки, которая отключает переключатель, таким образом посылая сигнал в мою программу о том, что это произошло, но как мне заставить gtk_main() распознать, что это событие произошло?

Другими словами, как мне заставить gtk_main() отслеживать нестандартные события ввода устройства?

Ответ №1:

Вы можете использовать пользовательские действия, предоставляемые GtkApplication.

В любом случае вы должны самостоятельно реализовать код мониторинга, либо путем опроса состояния вашего оборудования, либо с использованием более продвинутых методов (если это возможно).

 /* gcc -o monitor monitor.c $(pkg-config --cflags --libs gtk -3.0) */

#include <gtk/gtk.h>

static void
startup(GtkApplication *application)
{
    GAction *action;

    /* plate-removed is a custom action */
    action = G_ACTION(g_simple_action_new("plate-removed", NULL));
    g_action_map_add_action(G_ACTION_MAP(application), action);
    g_object_unref(action);

    /* You can connect your callbacks to the GAction::activate signal */
    action = g_action_map_lookup_action(G_ACTION_MAP(application), "plate-removed");
    g_signal_connect_swapped(action, "activate",
                             G_CALLBACK(g_print), "Plate has been removedn");
}

static gpointer
worker_thread(gpointer user_data)
{
    GApplication *application = G_APPLICATION(user_data);
    for (;;) {
        g_usleep(g_random_int_range(500000, 5000000));
        /* Event occurred: emit the signal */
        g_action_group_activate_action(G_ACTION_GROUP(application),
                                       "plate-removed", NULL);
    }
    return NULL;
}

static gboolean
polling_loop(gpointer user_data)
{
    GApplication *application = G_APPLICATION(user_data);
    if (g_random_int_range(1, 20) == 8) {
        /* Event occurred: emit the signal */
        g_action_group_activate_action(G_ACTION_GROUP(application),
                                       "plate-removed", NULL);
    }
    return G_SOURCE_CONTINUE;
}

static void
activate(GtkApplication *application)
{
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_application_add_window(application, GTK_WINDOW(window));
    gtk_widget_show_all(window);

    /* You can use whatever you want to monitor your hardware, in particular
     * a polling loop or a worker thread */
    g_timeout_add(50, polling_loop, application);
    /* g_thread_new("WorkerThread", worker_thread, application); */
}

int
main(int argc, char *argv[])
{
    GtkApplication *application;
    int retval;

    application = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
    g_signal_connect(application, "startup", G_CALLBACK(startup), NULL);
    g_signal_connect(application, "activate", G_CALLBACK(activate), NULL);
    retval = g_application_run(G_APPLICATION(application), argc, argv);
    g_object_unref(application);

    return retval;
}