diff options
Diffstat (limited to 'src/nanolight.c')
-rw-r--r-- | src/nanolight.c | 616 |
1 files changed, 2 insertions, 614 deletions
diff --git a/src/nanolight.c b/src/nanolight.c index 80bf874..aea925c 100644 --- a/src/nanolight.c +++ b/src/nanolight.c @@ -33,8 +33,8 @@ #define _(x) gettext(x) #include "nanolight.h" -#include "command.h" #include "scanout.h" +#include "display.h" static void show_help(const char *s) { @@ -43,223 +43,6 @@ static void show_help(const char *s) " -h, --help Display this help message.\n")); } -#define OVERALL_BORDER (20.0) -#define OVERALL_SPLIT (0.5) -#define FIXTURE_BORDER (5.0) - -enum attr_class key_attrs[] = { - 0, - ATT_INTENSITY, /* F1 */ - ATT_TILT, /* F2 */ - ATT_STROBE, /* F3 */ - ATT_CYAN, /* F4 */ - ATT_MAGENTA, /* F5 */ - ATT_YELLOW, /* F6 */ - ATT_GOBO, /* F7 */ - ATT_RGOBO, /* F8 */ - ATT_PRISM, /* F9 */ - ATT_FOCUS, /* F10 */ - ATT_ZOOM, /* F11 */ - ATT_ZOOM, /* F12 */ -}; - -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 int fixture_selected(struct nanolight *nl, struct fixture *fix) -{ - int i; - for ( i=0; i<nl->n_sel; i++ ) { - if ( &nl->fixtures[nl->selection[i]] == fix ) return 1; - } - return 0; -} - - -static int find_attribute(struct fixture *fix, enum attr_class cls, int *n) -{ - int j; - for ( j=0; j<fix->cls->n_attrs; j++ ) { - if ( fix->cls->attrs[j].cls == cls ) { - *n = j; - return 1; - } - } - return 0; -} - - -static void draw_fixture(cairo_t *cr, PangoContext *pc, PangoFontDescription *fontdesc, - struct nanolight *nl, struct fixture *fix) -{ - PangoLayout *layout; - const double w = 40.0; - const double h = 3.0/2.0*w; - char tmp[32]; - int n; - - /* Pan/tilt (underneath rectangle) */ - if ( find_attribute(fix, ATT_PAN, &n) ) { - double x = w*fix->attr_vals[n] / 65535; - cairo_move_to(cr, x, -1.0); - cairo_line_to(cr, x, h+1.0); - cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - } - if ( find_attribute(fix, ATT_TILT, &n) ) { - double y = h*(1.0 - (double)fix->attr_vals[n] / 65535); - cairo_move_to(cr, -1.0, y); - cairo_line_to(cr, w+1.0, y); - cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - } - - cairo_rectangle(cr, 0.0, 0.0, w, h); - if ( fixture_selected(nl, fix) ) { - cairo_set_source_rgba(cr, 0.3, 0.3, 0.9, 0.9); - } else { - cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 0.9); - } - cairo_fill_preserve(cr); - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - - /* Label */ - layout = pango_layout_new(pc); - 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); -} - - -static const char *attr_text(enum attr_class cls) -{ - switch ( cls ) { - case ATT_INTENSITY : return "Intensity"; - case ATT_PAN : return "(pan)"; - case ATT_TILT : return "Pan/tilt"; - case ATT_STROBE : return "Strobe"; - case ATT_CYAN : return "Cyan"; - case ATT_MAGENTA : return "Magenta"; - case ATT_YELLOW : return "Yellow"; - case ATT_RGOBO : return "RGobo"; - case ATT_GOBO : return "Gobo"; - case ATT_PRISM : return "Prism"; - case ATT_FOCUS : return "Focus"; - case ATT_ZOOM : return "Zoom"; - } - return "(unknown)"; -} - - -static gboolean draw_sig(GtkWidget *widget, cairo_t *cr, struct nanolight *nl) -{ - int w, h; - int ch; - int i; - PangoContext *pc; - PangoFontDescription *fontdesc; - double x, y; - PangoRectangle cursor; - - w = gtk_widget_get_allocated_width(widget); - h = gtk_widget_get_allocated_height(widget); - pc = gtk_widget_get_pango_context(widget); - - /* Overall background */ - cairo_set_source_rgb(cr, 0.0, 0.0, 0.2); - cairo_paint(cr); - - /* Separator between fixture and cue areas */ - cairo_move_to(cr, w*OVERALL_SPLIT, OVERALL_BORDER); - cairo_line_to(cr, w*OVERALL_SPLIT, h - OVERALL_BORDER); - cairo_set_line_width(cr, 3.0); - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - cairo_stroke(cr); - - /* Fixtures */ - cairo_save(cr); - 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; - } - } - cairo_restore(cr); - - /* Command line */ - pango_layout_set_text(nl->layout, nl->cmdline, -1); - cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - cairo_save(cr); - cairo_translate(cr, OVERALL_BORDER, h - OVERALL_BORDER - 20.0); - cairo_move_to(cr, 0.0, 0.0); - pango_cairo_show_layout(cr, nl->layout); - pango_layout_get_cursor_pos(nl->layout, nl->cursor_idx, &cursor, NULL); - x = pango_units_to_double(cursor.x); - y = pango_units_to_double(cursor.y); - ch = pango_units_to_double(cursor.height); - cairo_move_to(cr, x, y); - cairo_line_to(cr, x, y+ch); - cairo_set_line_width(cr, 3.0); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - cairo_set_source_rgb(cr, 0.8, 0.4, 0.4); - cairo_stroke(cr); - cairo_restore(cr); - - /* Selected attribute indicator */ - if ( nl->n_sel > 0 ) { - pango_layout_set_text(nl->sa_layout, attr_text(nl->sel_attr), -1); - cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); - pango_layout_set_width(nl->sa_layout, pango_units_from_double(200.0)); - cairo_move_to(cr, w - 200.0 - OVERALL_BORDER, h-OVERALL_BORDER-20.0); - pango_cairo_show_layout(cr, nl->sa_layout); - } - - return FALSE; -} - static struct fixture *create_fixture(struct nanolight *nl, struct fixture_class *cls, const char *label, int universe, int base_addr) @@ -297,383 +80,6 @@ static struct fixture *create_fixture(struct nanolight *nl, struct fixture_class } -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'; - nl->cursor_idx = 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); - nl->cursor_idx += strlen(str); - redraw(nl); - return FALSE; -} - - -static size_t delete_char(char *str) -{ - char *last; - size_t len; - if ( str[0] == '\0' ) return 0; - last = g_utf8_find_prev_char(str, str+strlen(str)); - len = strlen(last); - last[0] = '\0'; - return len; -} - - -static void cap_value(struct fixture *fix, int n, signed int *v) -{ - if ( *v < 0 ) *v = 0; - if ( fix->cls->attrs[n].props & ATTR_16BIT ) { - if ( *v > 65535 ) *v = 65535; - } else { - if ( *v > 255 ) *v = 255; - } -} - - -static void set_start_attrs(struct nanolight *nl, enum attr_class cls) -{ - int i; - for ( i=0; i<nl->n_sel; i++ ) { - int n; - struct fixture *fix = &nl->fixtures[nl->selection[i]]; - if ( find_attribute(fix, cls, &n) ) { - fix->attr_vals_start[n] = fix->attr_vals[n]; - } - } - - /* If altering tilt, also change pan */ - if ( cls == ATT_TILT ) { - set_start_attrs(nl, ATT_PAN); - } -} - - -static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, struct nanolight *nl) -{ -#if 0 - GdkSeat *seat; - GdkWindow *win = gtk_widget_get_window(nl->da); - - seat = gdk_display_get_default_seat(gdk_display_get_default()); - nl->pointer = gdk_seat_get_pointer(seat); -#endif - - set_start_attrs(nl, nl->sel_attr); - - nl->x_orig = event->x; - nl->y_orig = event->y; - nl->dragging = 1; - - return FALSE; -} - - -static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event, struct nanolight *nl) -{ - nl->dragging = 0; - return FALSE; -} - - -static double maybe_fine(struct fixture *fix, int n, double inc, int shift) -{ - if ( !(fix->cls->attrs[n].props & ATTR_16BIT) ) return inc; - if ( shift ) return inc; - return inc * 100.0; -} - - -static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, struct nanolight *nl) -{ - int i; - double x_inc, y_inc; - int shift; - - if ( !nl->dragging ) return FALSE; - - x_inc = (event->x - nl->x_orig)/3; - y_inc = (nl->y_orig - event->y)/3; /* Mouse up means increase */ - - shift = event->state & GDK_SHIFT_MASK; - if ( shift != nl->fine ) { - nl->fine = shift; - set_start_attrs(nl, nl->sel_attr); - nl->x_orig = event->x; - nl->y_orig = event->y; - return FALSE; - } - - if ( nl->sel_attr == ATT_TILT ) { - for ( i=0; i<nl->n_sel; i++ ) { - int n; - struct fixture *fix = &nl->fixtures[nl->selection[i]]; - if ( find_attribute(fix, ATT_PAN, &n) ) { - double inc = maybe_fine(fix, n, x_inc, - event->state & GDK_SHIFT_MASK); - signed int nv = fix->attr_vals_start[n] + inc; - cap_value(fix, n, &nv); - fix->attr_vals[n] = nv; - } - if ( find_attribute(fix, ATT_TILT, &n) ) { - double inc = maybe_fine(fix, n, y_inc, - event->state & GDK_SHIFT_MASK); - signed int nv = fix->attr_vals_start[n] + inc; - cap_value(fix, n, &nv); - fix->attr_vals[n] = nv; - } - } - } else { - for ( i=0; i<nl->n_sel; i++ ) { - int n; - struct fixture *fix = &nl->fixtures[nl->selection[i]]; - if ( find_attribute(fix, nl->sel_attr, &n) ) { - double inc = maybe_fine(fix, n, y_inc, - event->state & GDK_SHIFT_MASK); - signed int nv = fix->attr_vals_start[n] + inc; - cap_value(fix, n, &nv); - if ( !(fix->cls->attrs[n].props & ATTR_STOP) ) { - fix->attr_vals[n] = nv; - } else { - printf("Can't change step attr with mouse\n"); - } - } - } - } - - redraw(nl); - return FALSE; -} - - -static void change_stop_attr(struct nanolight *nl, signed int inc) -{ - int i; - for ( i=0; i<nl->n_sel; i++ ) { - - struct fixture *fix = &nl->fixtures[nl->selection[i]]; - int n; - - if ( find_attribute(fix, nl->sel_attr, &n) ) { - signed int nv; - if ( !(fix->cls->attrs[n].props & ATTR_STOP) ) { - printf("Can't change continuous attr with keys\n"); - continue; - } - nv = fix->attr_vals[n] + inc; - if ( (nv>=0) && (nv<fix->cls->attrs[n].n_stops) ) { - fix->attr_vals[n] = nv; - } - } - - } - redraw(nl); -} - -static void home_value(struct nanolight *nl) -{ - int i; - for ( i=0; i<nl->n_sel; i++ ) { - - struct fixture *fix = &nl->fixtures[nl->selection[i]]; - int n; - - if ( nl->sel_attr == ATT_TILT ) { - if ( find_attribute(fix, ATT_PAN, &n) ) { - fix->attr_vals[n] = fix->cls->attrs[n].home; - } - if ( find_attribute(fix, ATT_TILT, &n) ) { - fix->attr_vals[n] = fix->cls->attrs[n].home; - } - nl->dragging = 0; - } else { - if ( find_attribute(fix, nl->sel_attr, &n) ) { - fix->attr_vals[n] = fix->cls->attrs[n].home; - } - } - - } - redraw(nl); -} - - -static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, struct nanolight *nl) -{ - gboolean r; - int claim = 1; - - switch ( event->keyval ) { - - case GDK_KEY_Left : - break; - - case GDK_KEY_Right : - break; - - case GDK_KEY_Up : - change_stop_attr(nl, +1); - break; - - case GDK_KEY_Down : - change_stop_attr(nl, -1); - break; - - case GDK_KEY_Return : - execute_command(nl); - break; - - case GDK_KEY_Escape : - nl->cmdline[0] = '\0'; - nl->cursor_idx = 0; - nl->n_sel = 0; - nl->dragging = 0; - break; - - case GDK_KEY_BackSpace : - nl->cursor_idx -= delete_char(nl->cmdline); - break; - - case GDK_KEY_KP_Enter : - printf("Go!\n"); - break; - - case GDK_KEY_KP_Add : - printf("Stop/back!\n"); - break; - - case GDK_KEY_Home : - home_value(nl); - break; - - case GDK_KEY_F1 : - nl->sel_attr = key_attrs[1]; - nl->dragging = 0; - break; - - case GDK_KEY_F2 : - nl->sel_attr = key_attrs[2]; - nl->dragging = 0; - break; - - case GDK_KEY_F3 : - nl->sel_attr = key_attrs[3]; - nl->dragging = 0; - break; - - case GDK_KEY_F4 : - nl->sel_attr = key_attrs[4]; - nl->dragging = 0; - break; - - case GDK_KEY_F5 : - nl->sel_attr = key_attrs[5]; - nl->dragging = 0; - break; - - case GDK_KEY_F6 : - nl->sel_attr = key_attrs[6]; - nl->dragging = 0; - break; - - case GDK_KEY_F7 : - nl->sel_attr = key_attrs[7]; - nl->dragging = 0; - break; - - case GDK_KEY_F8 : - nl->sel_attr = key_attrs[8]; - nl->dragging = 0; - break; - - case GDK_KEY_F9 : - nl->sel_attr = key_attrs[9]; - nl->dragging = 0; - break; - - case GDK_KEY_F10 : - nl->sel_attr = key_attrs[10]; - nl->dragging = 0; - break; - - case GDK_KEY_F11 : - nl->sel_attr = key_attrs[11]; - nl->dragging = 0; - break; - - case GDK_KEY_F12 : - nl->sel_attr = key_attrs[12]; - nl->dragging = 0; - break; - - default : - claim = 0; - break; - - } - - if ( !claim ) { - /* 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 ) claim = 1; - } else { - redraw(nl); - } - - if ( claim ) return TRUE; - return FALSE; -} - - -static gint realise_sig(GtkWidget *da, struct nanolight *nl) -{ - GdkWindow *win = gtk_widget_get_window(da); - PangoContext *pc; - PangoFontDescription *fontdesc; - - /* 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); - g_signal_connect(G_OBJECT(da), "button-press-event", G_CALLBACK(button_press_sig), nl); - g_signal_connect(G_OBJECT(da), "button-release-event", G_CALLBACK(button_release_sig), nl); - g_signal_connect(G_OBJECT(da), "motion-notify-event", G_CALLBACK(motion_sig), nl); - - pc = gtk_widget_get_pango_context(da); - fontdesc = pango_font_description_from_string("Comfortaa Bold 16"); - - nl->layout = pango_layout_new(pc); - pango_layout_set_alignment(nl->layout, PANGO_ALIGN_LEFT); - pango_layout_set_font_description(nl->layout, fontdesc); - - nl->sa_layout = pango_layout_new(pc); - pango_layout_set_alignment(nl->sa_layout, PANGO_ALIGN_RIGHT); - pango_layout_set_font_description(nl->sa_layout, fontdesc); - - return FALSE; -} - - static gboolean scanout_cb(gpointer data) { scanout_all((struct nanolight *)data); @@ -687,8 +93,6 @@ int main(int argc, char *argv[]) struct fixture_class cls; struct attribute attrs[128]; int c; - GtkWidget *mainwindow; - GtkWidget *da; gtk_init(&argc, &argv); @@ -813,23 +217,7 @@ int main(int argc, char *argv[]) /* Set up output */ g_timeout_add(100, scanout_cb, &nl); - /* Create main window */ - mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); - 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_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_BUTTON_MOTION_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); + create_main_window(&nl); gtk_main(); return 0; |