diff options
Diffstat (limited to 'src/nanolight.c')
-rw-r--r-- | src/nanolight.c | 207 |
1 files changed, 195 insertions, 12 deletions
diff --git a/src/nanolight.c b/src/nanolight.c index 4c657df..6cb06e6 100644 --- a/src/nanolight.c +++ b/src/nanolight.c @@ -33,6 +33,7 @@ #define _(x) gettext(x) #include "nanolight.h" +#include "command.h" static void show_help(const char *s) { @@ -43,12 +44,28 @@ static void show_help(const char *s) #define OVERALL_BORDER (20.0) #define OVERALL_SPLIT (0.5) +#define FIXTURE_BORDER (5.0) + +static double get_attr_val(struct fixture *fix, enum attr_class acls) +{ + int i; + for ( i=0; i<fix->cls->n_attrs; i++ ) { + if ( fix->cls->attrs[i].cls == acls ) { + int max = 255; + if ( fix->cls->attrs[i].props & ATTR_16BIT ) max = 65535; + return (double)fix->attr_vals[i] / max; + } + } + return 0.0; +} + static void draw_fixture(cairo_t *cr, PangoContext *pc, PangoFontDescription *fontdesc, - struct nanolight *nl, struct fixture *fx) + struct nanolight *nl, struct fixture *fix) { PangoLayout *layout; - const double w = nl->fixture_width; + const double w = 40.0; + char tmp[32]; cairo_rectangle(cr, 0.5, 0.5, w, 3.0/2.0*w); cairo_set_source_rgb(cr, 0.3, 0.3, 0.3); @@ -57,13 +74,28 @@ static void draw_fixture(cairo_t *cr, PangoContext *pc, PangoFontDescription *fo cairo_set_line_width(cr, 1.0); cairo_stroke(cr); + /* Label */ layout = pango_layout_new(pc); - pango_layout_set_text(layout, fx->label, -1); - pango_layout_set_width(layout, w*PANGO_SCALE); + pango_layout_set_text(layout, fix->label, -1); + pango_layout_set_width(layout, (w*PANGO_SCALE)-4.0); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_set_font_description(layout, fontdesc); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_move_to(cr, 0.0, 2.0); pango_cairo_show_layout(cr, layout); + g_object_unref(layout); + + /* Intensity */ + snprintf(tmp, 32, "%.0f %%", get_attr_val(fix, ATT_INTENSITY)*100.0); + layout = pango_layout_new(pc); + pango_layout_set_text(layout, tmp, -1); + pango_layout_set_width(layout, (w*PANGO_SCALE)-4.0); + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + pango_layout_set_font_description(layout, fontdesc); + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_move_to(cr, 0.0, 15.0); + pango_cairo_show_layout(cr, layout); + g_object_unref(layout); } @@ -73,11 +105,12 @@ static gboolean draw_sig(GtkWidget *widget, cairo_t *cr, struct nanolight *nl) int i; PangoContext *pc; PangoFontDescription *fontdesc; + PangoLayout *layout; + double x, y; w = gtk_widget_get_allocated_width(widget); h = gtk_widget_get_allocated_height(widget); pc = gtk_widget_get_pango_context(widget); - fontdesc = pango_font_description_from_string("Comfortaa Bold 14"); /* Overall background */ cairo_set_source_rgb(cr, 0.0, 0.0, 0.2); @@ -93,11 +126,153 @@ static gboolean draw_sig(GtkWidget *widget, cairo_t *cr, struct nanolight *nl) /* Fixtures */ cairo_translate(cr, OVERALL_BORDER, OVERALL_BORDER); + x = FIXTURE_BORDER; + y = FIXTURE_BORDER; + fontdesc = pango_font_description_from_string("Comfortaa Bold 8"); for ( i=0; i<nl->n_fixtures; i++ ) { + cairo_save(cr); + cairo_translate(cr, x, y); + cairo_scale(cr, nl->fixture_width/40.0, nl->fixture_width/40.0); draw_fixture(cr, pc, fontdesc, nl, &nl->fixtures[i]); + cairo_restore(cr); + x += nl->fixture_width + FIXTURE_BORDER*2; + if ( x + nl->fixture_width + FIXTURE_BORDER*2 > w*OVERALL_SPLIT ) { + x = FIXTURE_BORDER; + y += nl->fixture_width*3.0/2.0 + FIXTURE_BORDER*2; + } } /* Command line */ + layout = pango_layout_new(pc); + fontdesc = pango_font_description_from_string("Comfortaa Bold 16"); + pango_layout_set_text(layout, nl->cmdline, -1); + pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); + pango_layout_set_font_description(layout, fontdesc); + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_move_to(cr, 0.0, h - OVERALL_BORDER*2 - 20.0); + pango_cairo_show_layout(cr, layout); + g_object_unref(layout); + + return FALSE; +} + + +static struct fixture *create_fixture(struct nanolight *nl, struct fixture_class *cls, + const char *label, int base_addr) +{ + struct fixture *fix; + + if ( nl->n_fixtures == nl->max_fixtures ) { + struct fixture *fixtures_new; + fixtures_new = realloc(nl->fixtures, (64+nl->max_fixtures)*sizeof(struct fixture)); + if ( fixtures_new == NULL ) return NULL; + nl->fixtures = fixtures_new; + nl->max_fixtures += 64; + } + + fix = &nl->fixtures[nl->n_fixtures++]; + fix->label = strdup(label); + fix->base_addr = base_addr; + fix->cls = cls; + fix->attr_vals = calloc(cls->n_attrs, sizeof(int)); + if ( fix->attr_vals == NULL ) { + nl->n_fixtures--; + return NULL; + } + return fix; +} + + +static void redraw(struct nanolight *nl) +{ + gint w, h; + w = gtk_widget_get_allocated_width(GTK_WIDGET(nl->da)); + h = gtk_widget_get_allocated_height(GTK_WIDGET(nl->da)); + gtk_widget_queue_draw_area(GTK_WIDGET(nl->da), 0, 0, w, h); +} + + +static void execute_command(struct nanolight *nl) +{ + if ( command_run(nl->cmdline, nl) == 0 ) { + nl->cmdline[0] = '\0'; + } + redraw(nl); +} + + +static gboolean im_commit_sig(GtkIMContext *im, gchar *str, struct nanolight *nl) +{ + size_t cmd_len = strlen(nl->cmdline); + if ( cmd_len+strlen(str) > 1023 ) return FALSE; + strcat(nl->cmdline, str); + redraw(nl); + return FALSE; +} + + +static void delete_char(char *str) +{ + char *last; + if ( str[0] == '\0' ) return; + last = g_utf8_find_prev_char(str, str+strlen(str)); + last[0] = '\0'; +} + + +static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, struct nanolight *nl) +{ + gboolean r; + int claim = 0; + + /* Throw the event to the IM context and let it sort things out */ + r = gtk_im_context_filter_keypress(GTK_IM_CONTEXT(nl->im_context), event); + if ( r ) return FALSE; /* IM ate it */ + + switch ( event->keyval ) { + + case GDK_KEY_Left : + claim = 1; + break; + + case GDK_KEY_Right : + claim = 1; + break; + + case GDK_KEY_Return : + execute_command(nl); + claim = 1; + break; + + case GDK_KEY_Escape : + nl->cmdline[0] = '\0'; + redraw(nl); + claim = 1; + break; + + case GDK_KEY_BackSpace : + delete_char(nl->cmdline); + claim = 1; + redraw(nl); + break; + + } + + if ( claim ) return TRUE; + return FALSE; +} + + +static gint realise_sig(GtkWidget *da, struct nanolight *nl) +{ + GdkWindow *win = gtk_widget_get_window(da); + + /* Keyboard and input method stuff */ + nl->im_context = gtk_im_multicontext_new(); + gtk_im_context_set_client_window(GTK_IM_CONTEXT(nl->im_context), win); + gdk_window_set_accept_focus(win, TRUE); + g_signal_connect(G_OBJECT(nl->im_context), "commit", G_CALLBACK(im_commit_sig), nl); + g_signal_connect(G_OBJECT(da), "key-press-event", G_CALLBACK(key_press_sig), nl); return FALSE; } @@ -106,7 +281,6 @@ static gboolean draw_sig(GtkWidget *widget, cairo_t *cr, struct nanolight *nl) int main(int argc, char *argv[]) { struct nanolight nl; - struct fixture fix; struct fixture_class cls; struct attribute attrs[3]; int c; @@ -163,21 +337,30 @@ int main(int argc, char *argv[]) cls.attrs[2].props = ATTR_16BIT; cls.attrs[2].addr_offset = 2; - nl.n_fixtures = 1; - nl.fixtures = &fix; - fix.label = "mh1"; - fix.cls = &cls; - nl.fixture_width = 80.0; + nl.fixtures = NULL; + nl.n_fixtures = 0; + nl.max_fixtures = 0; + nl.cmdline[0] = '\0'; + + create_fixture(&nl, &cls, "mh1", 1); + create_fixture(&nl, &cls, "mh2", 52); + create_fixture(&nl, &cls, "mh3", 103); + create_fixture(&nl, &cls, "mh4", 154)->attr_vals[0]=255; mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_fullscreen(GTK_WINDOW(mainwindow)); + //gtk_window_fullscreen(GTK_WINDOW(mainwindow)); g_signal_connect_swapped(G_OBJECT(mainwindow), "destroy", gtk_main_quit, NULL); da = gtk_drawing_area_new(); + nl.da = da; gtk_container_add(GTK_CONTAINER(mainwindow), GTK_WIDGET(da)); + gtk_widget_set_can_focus(GTK_WIDGET(da), TRUE); + gtk_widget_add_events(da, GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); g_signal_connect(G_OBJECT(da), "draw", G_CALLBACK(draw_sig), &nl); + g_signal_connect(G_OBJECT(da), "realize", G_CALLBACK(realise_sig), &nl); + gtk_widget_grab_focus(GTK_WIDGET(da)); gtk_widget_show_all(mainwindow); gtk_main(); |