diff --git a/.gitignore b/.gitignore
index ba7b6ba..996cd59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
/libtool
/rtbuf
/rtbuf-gtk
+/rtbuf_gtk_resources.c
/rtbuf_music_type
/rtbuf_music_type.h
/rtbuf_portaudio_type
diff --git a/Makefile.am b/Makefile.am
index 56d6552..75aa87d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,7 +41,19 @@ bin_PROGRAMS += rtbuf-gtk
rtbuf_gtk_CFLAGS = ${GTK3_CFLAGS}
rtbuf_gtk_LDADD = ${GTK3_LIBS} librtbuf.la
rtbuf_gtk_SOURCES = \
- rtbuf_gtk.c
+ rtbuf_lib.c \
+ rtbuf_gtk.c \
+ rtbuf_gtk_resources.c \
+ rtbuf_widget.c
+include_HEADERS += \
+ rtbuf_lib.h
+rtbuf_gtk_UI = \
+ rtbuf_input.ui \
+ rtbuf_modular.ui \
+ rtbuf_output.ui \
+ rtbuf_widget.ui
+rtbuf_gtk_resources.c: rtbuf_gtk.gresource.xml ${rtbuf_gtk_UI}
+ glib-compile-resources rtbuf_gtk.gresource.xml --target=rtbuf_gtk_resources.c --generate-source
endif # ENABLE_GTK3
if ENABLE_RTBUF
diff --git a/rtbuf.glade b/rtbuf.glade
deleted file mode 100644
index ef6003a..0000000
--- a/rtbuf.glade
+++ /dev/null
@@ -1,386 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.1 -->
-<interface>
- <requires lib="gtk+" version="3.20"/>
- <object class="GtkBox" id="input">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkCheckButton" id="input_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="input_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">input</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="input_value">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">0.5</property>
- <property name="width_chars">9</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="input_min">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_frame">False</property>
- <property name="width_chars">9</property>
- <property name="text" translatable="yes">0.0</property>
- <property name="caps_lock_warning">False</property>
- <property name="input_purpose">number</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkScale" id="input_slider">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="round_digits">1</property>
- <property name="digits">3</property>
- <property name="draw_value">False</property>
- <property name="value_pos">left</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="input_max">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_frame">False</property>
- <property name="width_chars">9</property>
- <property name="text" translatable="yes">1.0</property>
- <property name="input_purpose">number</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">5</property>
- </packing>
- </child>
- </object>
- <object class="GtkWindow" id="modular">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child type="titlebar">
- <placeholder/>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkMenuBar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkMenuItem">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">_File</property>
- <property name="use_underline">True</property>
- <child type="submenu">
- <object class="GtkMenu">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-new</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-open</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-save</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-save-as</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkSeparatorMenuItem">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem" id="quit">
- <property name="label">gtk-quit</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkMenuItem">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">_Edit</property>
- <property name="use_underline">True</property>
- <child type="submenu">
- <object class="GtkMenu">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-cut</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-copy</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-paste</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-delete</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkMenuItem">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">_View</property>
- <property name="use_underline">True</property>
- </object>
- </child>
- <child>
- <object class="GtkMenuItem">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">_Help</property>
- <property name="use_underline">True</property>
- <child type="submenu">
- <object class="GtkMenu">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImageMenuItem">
- <property name="label">gtk-about</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkLayout" id="modular_layout">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <child>
- <placeholder/>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <object class="GtkBox" id="output">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkLabel" id="output_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">output</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="output_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <object class="GtkBox" id="rtbuf">
- <property name="width_request">100</property>
- <property name="height_request">80</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkLabel" id="rtbuf_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">rtbuf</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="rtbuf_inputs">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="rtbuf_outputs">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
-</interface>
diff --git a/rtbuf_gtk.c b/rtbuf_gtk.c
index c344d63..d95504b 100644
--- a/rtbuf_gtk.c
+++ b/rtbuf_gtk.c
@@ -1,71 +1,172 @@
#include <gtk/gtk.h>
#include <stdio.h>
+#include "rtbuf.h"
+#include "rtbuf_lib.h"
+#include "rtbuf_widget.h"
-GObject *modular;
-GObject *modular_layout;
+GtkBuilder *builder = NULL;
+GtkWindow *modular = NULL;
+GtkLayout *modular_layout = NULL;
+GtkMenu *library_menu = NULL;
+
+RtbufWidget * rtbuf_gtk_modular_layout_new (s_rtbuf *rtb,
+ const gint x, const gint y)
+{
+ RtbufWidget *widget = rtbuf_widget_new(rtb, "rtbuf");
+ gtk_layout_put(modular_layout, GTK_WIDGET(widget), x, y);
+ return widget;
+}
+
+RtbufWidget * rtbuf_gtk_new (gchar *library, gchar *proc,
+ const gint x, const gint y)
+{
+ int i;
+ s_rtbuf_lib *rl = 0;
+ s_rtbuf_proc *rp = 0;
+ s_rtbuf *rtb = 0;
+ printf("rtbuf-gtk new %s %s\n", library, proc);
+ i = rtbuf_lib_find(library);
+ if (i < 0) {
+ printf("load %s\n", library);
+ if (!(rl = rtbuf_lib_load(library))) {
+ fprintf(stderr, "rtbuf-gtk: load failed: '%s'\n", library);
+ return NULL;
+ }
+ }
+ else
+ rl = &g_rtbuf_lib[i];
+ i = rtbuf_lib_find_proc(rl, proc);
+ if (i < 0) {
+ fprintf(stderr, "rtbuf-gtk new: not found %s %s\n", library, proc);
+ return NULL;
+ }
+ rp = rl->proc[i];
+ i = rtbuf_new(rp);
+ if (i < 0) {
+ fprintf(stderr, "rtbuf-gtk new rtbuf_new failed: %s %s\n", library, proc);
+ return NULL;
+ }
+ rtb = &g_rtbuf[i];
+ return rtbuf_gtk_modular_layout_new(rtb, x, y);
+}
+
+void rtbuf_gtk_library_menu_activate (GtkMenuItem *menuitem,
+ gpointer data)
+{
+ gchar *proc;
+ gchar *library = (gchar*) data;
+ g_object_get(menuitem, "label", &proc, NULL);
+ rtbuf_gtk_new(library, proc, 100, 100);
+ g_free(proc);
+}
+
+void rtbuf_gtk_library_menu_library_item (GtkWidget *menuitem, gpointer data)
+{
+ gchar *library = (gchar*) data;
+ g_signal_connect(menuitem, "activate", G_CALLBACK(rtbuf_gtk_library_menu_activate), library);
+}
+
+void rtbuf_gtk_library_menu_library (GtkWidget *menuitem, gpointer data)
+{
+ GtkContainer *submenu;
+ gchar *library;
+ (void) data;
+ g_object_get(menuitem,
+ "label", &library,
+ "submenu", &submenu,
+ NULL);
+ gtk_container_foreach(submenu,
+ rtbuf_gtk_library_menu_library_item,
+ library);
+ g_object_unref(G_OBJECT(submenu));
+}
+
+void rtbuf_gtk_library_menu ()
+{
+ library_menu = GTK_MENU(gtk_builder_get_object(builder, "library_menu"));
+ gtk_container_foreach(GTK_CONTAINER(library_menu),
+ rtbuf_gtk_library_menu_library,
+ NULL);
+}
void rtbuf_gtk_modular_close (GtkWidget *widget,
- gpointer user_data)
+ gpointer data)
{
+ (void) widget;
+ (void) data;
printf("rtbuf-gtk modular close\n");
gtk_main_quit();
}
-gboolean rtbuf_gtk_modular_popup (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data)
+gboolean rtbuf_gtk_modular_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data)
{
- if (event->button == 3) {
- printf("rtbuf-gtk modular popup\n");
+ (void) data;
+ if ((GtkLayout*) widget == modular_layout) {
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+ cairo_paint(cr);
+ GTK_WIDGET_GET_CLASS(widget)->draw(widget, cr);
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
-gboolean rtbuf_gtk_modular_draw (GtkWidget *widget,
- cairo_t *cr,
- gpointer user_data)
+gboolean rtbuf_gtk_modular_popup (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
{
(void) widget;
- (void) cr;
- (void) user_data;
- printf("rtbuf-gtk modular draw\n");
- return TRUE;
+ (void) data;
+ if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
+ printf("rtbuf-gtk modular popup\n");
+ gtk_menu_popup(library_menu, NULL, NULL, NULL, NULL, event->button, event->time);
+ return TRUE;
+ }
+ return FALSE;
}
-void rtbuf_gtk_modular_window (GtkBuilder *builder)
+void rtbuf_gtk_modular ()
{
GObject *button;
- modular = gtk_builder_get_object(builder, "modular");
- g_signal_connect(modular, "destroy", G_CALLBACK(rtbuf_gtk_modular_close), NULL);
+ modular = GTK_WINDOW(gtk_builder_get_object(builder, "modular"));
+ g_signal_connect(modular, "destroy",
+ G_CALLBACK(rtbuf_gtk_modular_close), NULL);
button = gtk_builder_get_object(builder, "quit");
- g_signal_connect(button, "activate", G_CALLBACK(rtbuf_gtk_modular_close), NULL);
+ g_signal_connect(button, "activate",
+ G_CALLBACK(rtbuf_gtk_modular_close), NULL);
+
+ modular_layout = GTK_LAYOUT(gtk_builder_get_object(builder, "modular_layout"));
+ gtk_widget_add_events(GTK_WIDGET(modular_layout), GDK_BUTTON_PRESS_MASK);
+ g_signal_connect(modular_layout, "button-press-event",
+ G_CALLBACK(rtbuf_gtk_modular_popup), NULL);
+ g_signal_connect(modular_layout, "draw",
+ G_CALLBACK(rtbuf_gtk_modular_draw), NULL);
- modular_layout = gtk_builder_get_object(builder, "modular_layout");
- gtk_widget_add_events(modular_layout, GDK_BUTTON_PRESS_MASK);
- g_signal_connect(modular_layout, "button-press-event", G_CALLBACK(rtbuf_gtk_modular_popup), NULL);
- g_signal_connect(modular_layout, "draw", G_CALLBACK(rtbuf_gtk_modular_draw), NULL);
+ rtbuf_gtk_library_menu();
}
-int main (int argc, char *argv[])
+int rtbuf_gtk_builder ()
{
- GtkBuilder *builder;
GError *error = NULL;
-
- gtk_init(&argc, &argv);
-
- /* Construct a GtkBuilder instance and load our UI description */
builder = gtk_builder_new ();
- if (gtk_builder_add_from_file(builder, "rtbuf.glade", &error) == 0) {
- g_printerr("Error loading file: %s\n", error->message);
+ if (gtk_builder_add_from_resource(builder, "/rtbuf/rtbuf_modular.ui", &error) == 0) {
+ g_printerr("Error loading resource /rtbuf/rtbuf_modular.ui: %s\n", error->message);
g_clear_error(&error);
return 1;
}
+ return 0;
+}
- rtbuf_gtk_modular_window(builder);
-
+int main (int argc, char *argv[])
+{
+ librtbuf_init();
+ gtk_init(&argc, &argv);
+ if (rtbuf_gtk_builder())
+ return 1;
+ rtbuf_gtk_modular();
gtk_main ();
-
return 0;
}
diff --git a/rtbuf_gtk.gresource.xml b/rtbuf_gtk.gresource.xml
new file mode 100644
index 0000000..01eccf8
--- /dev/null
+++ b/rtbuf_gtk.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/rtbuf/">
+ <file preprocess="xml-stripblanks">rtbuf_input.ui</file>
+ <file preprocess="xml-stripblanks">rtbuf_modular.ui</file>
+ <file preprocess="xml-stripblanks">rtbuf_output.ui</file>
+ <file preprocess="xml-stripblanks">rtbuf_widget.ui</file>
+ </gresource>
+</gresources>
diff --git a/rtbuf_input.ui b/rtbuf_input.ui
new file mode 100644
index 0000000..54b7308
--- /dev/null
+++ b/rtbuf_input.ui
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="RtbufInput" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="input_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="input_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">input</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="input_value">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">0.5</property>
+ <property name="width_chars">9</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="input_min">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_frame">False</property>
+ <property name="width_chars">9</property>
+ <property name="text" translatable="yes">0.0</property>
+ <property name="caps_lock_warning">False</property>
+ <property name="input_purpose">number</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="input_slider">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="round_digits">1</property>
+ <property name="digits">3</property>
+ <property name="draw_value">False</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="input_max">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_frame">False</property>
+ <property name="width_chars">9</property>
+ <property name="text" translatable="yes">1.0</property>
+ <property name="input_purpose">number</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/rtbuf_modular.ui b/rtbuf_modular.ui
new file mode 100644
index 0000000..028bc16
--- /dev/null
+++ b/rtbuf_modular.ui
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkWindow" id="modular">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkMenuBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-new</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-open</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-save-as</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="quit">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-cut</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-copy</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-paste</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Library</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="library_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">signal</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">sinus</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkLayout" id="modular_layout">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="width">8192</property>
+ <property name="height">8192</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/rtbuf_output.ui b/rtbuf_output.ui
new file mode 100644
index 0000000..6c0e8c3
--- /dev/null
+++ b/rtbuf_output.ui
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="RtbufOutput" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="output_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="output_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">output</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/rtbuf_widget.c b/rtbuf_widget.c
new file mode 100644
index 0000000..5ea255e
--- /dev/null
+++ b/rtbuf_widget.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <gtk/gtk.h>
+#include "rtbuf_widget.h"
+#include "rtbuf.h"
+
+struct _RtbufWidgetPrivate {
+ s_rtbuf *rtbuf;
+ GtkLabel *label;
+ GtkBox *inputs;
+ GtkBox *outputs;
+};
+
+enum {
+ PROP_0,
+ PROP_LABEL,
+ PROP_RTBUF,
+ LAST_PROP
+};
+
+static GParamSpec *rtbuf_widget_props[LAST_PROP];
+
+static void rtbuf_widget_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void rtbuf_widget_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void rtbuf_widget_finalize (GObject *object);
+static gboolean rtbuf_widget_draw (GtkWidget *widget, cairo_t *cr);
+
+G_DEFINE_TYPE_WITH_PRIVATE (RtbufWidget, rtbuf_widget, GTK_TYPE_BOX)
+
+static void
+rtbuf_widget_class_init (RtbufWidgetClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*) klass;
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ printf("rtbuf_widget class init\n");
+ gobject_class->finalize = rtbuf_widget_finalize;
+ gobject_class->set_property = rtbuf_widget_set_property;
+ gobject_class->get_property = rtbuf_widget_get_property;
+ rtbuf_widget_props[PROP_LABEL] =
+ g_param_spec_string("label",
+ "Label",
+ "Text of the frame's label",
+ NULL,
+ G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+ rtbuf_widget_props[PROP_RTBUF] =
+ g_param_spec_pointer("rtbuf",
+ "Rtbuf",
+ "Pointer to a s_rtbuf",
+ G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+ g_object_class_install_properties(gobject_class, LAST_PROP, rtbuf_widget_props);
+ widget_class->draw = rtbuf_widget_draw;
+ gtk_widget_class_set_template_from_resource(widget_class,
+ "/rtbuf/rtbuf_widget.ui");
+ gtk_widget_class_bind_template_child_private(widget_class,
+ RtbufWidget, label);
+ gtk_widget_class_bind_template_child_private(widget_class,
+ RtbufWidget, inputs);
+ gtk_widget_class_bind_template_child_private(widget_class,
+ RtbufWidget, outputs);
+}
+
+static void
+rtbuf_widget_init (RtbufWidget *widget)
+{
+ RtbufWidgetPrivate *priv;
+ printf("rtbuf_widget init\n");
+ priv = rtbuf_widget_get_instance_private(widget);
+ gtk_widget_init_template(GTK_WIDGET(widget));
+}
+
+static void
+rtbuf_widget_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ RtbufWidget *widget = RTBUF_WIDGET(object);
+ RtbufWidgetPrivate *priv = rtbuf_widget_get_instance_private(widget);
+ switch (prop_id) {
+ case PROP_LABEL:
+ rtbuf_widget_set_label(widget, g_value_get_string(value));
+ break;
+ case PROP_RTBUF:
+ priv->rtbuf = g_value_get_pointer(value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+rtbuf_widget_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ RtbufWidget *widget = RTBUF_WIDGET(object);
+ RtbufWidgetPrivate *priv = rtbuf_widget_get_instance_private(widget);
+ switch (prop_id) {
+ case PROP_LABEL:
+ g_value_set_string(value, rtbuf_widget_get_label(widget));
+ break;
+ case PROP_RTBUF:
+ g_value_set_pointer(value, priv->rtbuf);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+rtbuf_widget_finalize (GObject *object)
+{
+ RtbufWidget *widget = RTBUF_WIDGET(object);
+ RtbufWidgetPrivate *priv = rtbuf_widget_get_instance_private(widget);
+ g_clear_object(&priv->label);
+ g_clear_object(&priv->inputs);
+ g_clear_object(&priv->outputs);
+ G_OBJECT_CLASS(rtbuf_widget_parent_class)->finalize(object);
+}
+
+static gboolean
+rtbuf_widget_draw (GtkWidget *widget, cairo_t *cr)
+{
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+ cairo_paint(cr);
+ GTK_WIDGET_GET_PARENT_CLASS(widget)->draw(widget, cr);
+}
+
+RtbufWidget *
+rtbuf_widget_new (s_rtbuf *rtb, const gchar *label)
+{
+ return (RtbufWidget*) g_object_new(RTBUF_WIDGET_TYPE,
+ "label", label,
+ "rtbuf", rtb,
+ NULL);
+}
+
+void rtbuf_widget_set_label (RtbufWidget *widget,
+ const gchar *label)
+{
+ g_return_if_fail(IS_RTBUF_WIDGET(widget));
+ if (label) {
+ RtbufWidgetPrivate *priv = rtbuf_widget_get_instance_private(widget);
+ if (GTK_IS_LABEL(priv->label))
+ gtk_label_set_text(priv->label, label);
+ }
+}
+
+const gchar *
+rtbuf_widget_get_label (RtbufWidget *widget)
+{
+ RtbufWidgetPrivate *priv;
+ g_return_val_if_fail(IS_RTBUF_WIDGET(widget), NULL);
+ priv = rtbuf_widget_get_instance_private(widget);
+ if (GTK_IS_LABEL(priv->label))
+ return gtk_label_get_text(priv->label);
+ else
+ return NULL;
+}
diff --git a/rtbuf_widget.h b/rtbuf_widget.h
new file mode 100644
index 0000000..9a6dd41
--- /dev/null
+++ b/rtbuf_widget.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 Thomas de Grivel <thoxdg@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef RTBUF_WIDGET_H
+#define RTBUF_WIDGET_H
+
+#include "rtbuf.h"
+
+#define RTBUF_WIDGET_TYPE (rtbuf_widget_get_type ())
+#define RTBUF_WIDGET(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), RTBUF_WIDGET_TYPE, RtbufWidget))
+#define RTBUF_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RTBUF_WIDGET_TYPE, RtbufWidgetClass))
+#define IS_RTBUF_WIDGET(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), RTBUF_WIDGET_TYPE))
+#define IS_RTBUF_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RTBUF_WIDGET_TYPE))
+#define RTBUF_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RTBUF_WIDGET_TYPE, RtbufWidgetClass))
+
+typedef struct _RtbufWidget RtbufWidget;
+typedef struct _RtbufWidgetClass RtbufWidgetClass;
+typedef struct _RtbufWidgetPrivate RtbufWidgetPrivate;
+
+struct _RtbufWidget {
+ GtkBox box;
+};
+
+struct _RtbufWidgetClass {
+ GtkBoxClass parent_class;
+};
+
+RtbufWidget * rtbuf_widget_new (s_rtbuf *rtb, const gchar *label);
+void rtbuf_widget_set_label (RtbufWidget *widget, const gchar *label);
+const gchar * rtbuf_widget_get_label (RtbufWidget *widget);
+
+#endif
diff --git a/rtbuf_widget.ui b/rtbuf_widget.ui
new file mode 100644
index 0000000..5df0c3a
--- /dev/null
+++ b/rtbuf_widget.ui
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <template class="RtbufWidget" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">rtbuf</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="inputs">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="outputs">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </template>
+</interface>