GUI: use quantization setting to choose grid to draw
authorStefan Westerfeld <stefan@space.twc.de>
Mon, 16 May 2011 14:31:46 +0000 (16:31 +0200)
committerStefan Westerfeld <stefan@space.twc.de>
Mon, 16 May 2011 14:31:46 +0000 (16:31 +0200)
beast-gtk/bstpianoroll.c
beast-gtk/bstpianoroll.h
beast-gtk/bstpianorollctrl.c

index 11b7d2d..807bc96 100644 (file)
@@ -85,6 +85,7 @@ static void   bst_piano_roll_hsetup                   (BstPianoRoll           *self,
                                                         guint                   ppb,
                                                         guint                   bpt,
                                                          guint                   tpqn,
+                                                        guint                   quant,
                                                         guint                   max_ticks,
                                                         gfloat                  hzoom);
 
@@ -160,8 +161,8 @@ bst_piano_roll_init (BstPianoRoll *self)
   self->bpt = 1;
   self->max_ticks = 1;
   self->hzoom = 1;
-  self->draw_qn_grid = TRUE;
-  self->draw_qqn_grid = TRUE;
+  self->draw_beat_grid = TRUE;
+  self->draw_quant_grid = TRUE;
   self->release_closes_toplevel = TRUE;
   self->min_note = SFI_MIN_NOTE;
   self->max_note = SFI_MAX_NOTE;
@@ -172,7 +173,7 @@ bst_piano_roll_init (BstPianoRoll *self)
   self->selection_duration = 0;
   self->selection_min_note = 0;
   self->selection_max_note = 0;
-  bst_piano_roll_hsetup (self, 384, 4, 384, 800 * 384, 1);
+  bst_piano_roll_hsetup (self, 384, 4, 384, BST_QUANTIZE_NOTE_8, 800 * 384, 1);
   
   bst_ascii_pixbuf_ref ();
 }
@@ -314,7 +315,7 @@ coord_to_tick (BstPianoRoll *self,
 
 #define        CROSSING_TACT           (1)
 #define        CROSSING_BEAT           (2)
-#define        CROSSING_QNOTE_Q        (3)
+#define        CROSSING_QUANT          (3)
 
 static guint
 coord_check_crossing (BstPianoRoll *self,
@@ -338,9 +339,9 @@ coord_check_crossing (BstPianoRoll *self,
       lq = ltick / self->ppb;
       rq = rtick / self->ppb;
       break;
-    case CROSSING_QNOTE_Q:
-      lq = ltick * 4 / self->ppb;
-      rq = rtick * 4 / self->ppb;
+    case CROSSING_QUANT:
+      lq = ltick / self->quant_ticks;
+      rq = rtick / self->quant_ticks;
       break;
     }
   
@@ -742,7 +743,7 @@ bst_piano_roll_draw_canvas (GxkScrollCanvas *scc,
               gdk_gc_set_line_attributes (draw_gc, line_width, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
               gdk_draw_line (drawable, draw_gc, i, area->y, i, area->y + area->height - 1);
             }
-          else if (pass == 1 && self->draw_qn_grid && coord_check_crossing (self, i, CROSSING_BEAT))
+          else if (pass == 1 && self->draw_beat_grid && coord_check_crossing (self, i, CROSSING_BEAT))
             {
               GdkGC *draw_gc = COLOR_GC_VGRID (self);
               guint8 dash[3] = { 2, 2, 0 };
@@ -752,7 +753,7 @@ bst_piano_roll_draw_canvas (GxkScrollCanvas *scc,
               gdk_draw_line (drawable, draw_gc, i, area->y, i, area->y + area->height - 1);
               gdk_gc_set_line_attributes (draw_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
             }
-          else if (pass == 1 && self->draw_qqn_grid && coord_check_crossing (self, i, CROSSING_QNOTE_Q))
+          else if (pass == 1 && self->draw_quant_grid && coord_check_crossing (self, i, CROSSING_QUANT))
             {
               GdkGC *draw_gc = COLOR_GC_VGRID (self);
               guint8 dash[3] = { 1, 1, 0 };
@@ -892,7 +893,7 @@ bst_piano_roll_draw_hpanel (GxkScrollCanvas *scc,
   for (i = area->x; i < area->x + area->width; i++)
     {
       /* drawing qnote numbers is not of much use if we can't even draw
-       * the qnote quarter grid, so we special case draw_qqn_grid here
+       * the beat grid, so we special case draw_quant_grid here
        */
       if (coord_check_crossing (self, i, CROSSING_TACT))
        {
@@ -911,7 +912,7 @@ bst_piano_roll_draw_hpanel (GxkScrollCanvas *scc,
                             i - rect.width / 2, (height - rect.height) / 2,
                             PLAYOUT_HPANEL (self));
        }
-      else if (self->draw_qqn_grid && coord_check_crossing (self, i, CROSSING_BEAT))
+      else if (self->draw_quant_grid && coord_check_crossing (self, i, CROSSING_BEAT))
        {
           guint next_pixel, tact = coord_to_tick (self, i, TRUE) + 1, beat = tact;
 
@@ -1031,6 +1032,7 @@ bst_piano_roll_hsetup (BstPianoRoll *self,
                       guint         ppb,
                       guint         bpt,
                        guint         tpqn,
+                       guint         quant,
                       guint         max_ticks,
                       gfloat        hzoom)
 {
@@ -1038,6 +1040,7 @@ bst_piano_roll_hsetup (BstPianoRoll *self,
   uint old_ppb = self->ppb;
   guint old_bpt = self->bpt;
   uint old_tpqn = self->tpqn;
+  guint old_quant = self->quant;
   guint old_max_ticks = self->max_ticks;
   gfloat old_hzoom = self->hzoom;
   gdouble old_hpos = pixels_to_ticks (self, scc->hadjustment->value);
@@ -1051,16 +1054,37 @@ bst_piano_roll_hsetup (BstPianoRoll *self,
   self->ppb = MAX (ppb, 1);
   self->bpt = MAX (bpt, 1);
   self->tpqn = MAX (tpqn, 1);
+  self->quant = quant;
   self->max_ticks = MAX (max_ticks, 1);
   self->hzoom = CLAMP (hzoom, 0.01, 100);
-  
+
   if (old_ppb != self->ppb ||
       old_bpt != self->bpt ||
       old_tpqn != self->tpqn ||
+      old_quant != self->quant ||
       old_hzoom != self->hzoom)
     {
-      self->draw_qn_grid = ticks_to_pixels (self, self->ppb) >= 3;
-      self->draw_qqn_grid = ticks_to_pixels (self, self->ppb / 4) >= 5;
+      /* compute quant_ticks from quant  */
+      if (self->quant == BST_QUANTIZE_TACT)
+        {
+          self->quant_ticks = self->ppb * self->bpt;
+        }
+      else if (self->quant == BST_QUANTIZE_NONE)
+        {
+          self->quant_ticks = self->tpqn / 4;
+        }
+      else
+        {
+          self->quant_ticks = self->tpqn * 4 / self->quant;
+        }
+
+      self->draw_beat_grid = ticks_to_pixels (self, self->ppb) >= 3;
+      self->draw_quant_grid = ticks_to_pixels (self, self->quant_ticks) >= 5;
+      while (!self->draw_quant_grid && self->quant_ticks * 2 < self->ppb)
+        {
+          self->quant_ticks *= 2;
+          self->draw_quant_grid = ticks_to_pixels (self, self->quant_ticks) >= 5;
+        }
       gtk_widget_queue_draw (GTK_WIDGET (self));
       scc->hadjustment->value = ticks_to_pixels (self, old_hpos); // fix start position when hzoom changes
       X_OFFSET (self) = GXK_SCROLL_CANVAS (self)->hadjustment->value;
@@ -1080,7 +1104,7 @@ bst_piano_roll_set_hzoom (BstPianoRoll *self,
   GxkScrollCanvas *scc = GXK_SCROLL_CANVAS (self);
   g_return_val_if_fail (BST_IS_PIANO_ROLL (self), 0);
   
-  bst_piano_roll_hsetup (self, self->ppb, self->bpt, self->tpqn, self->max_ticks, hzoom);
+  bst_piano_roll_hsetup (self, self->ppb, self->bpt, self->tpqn, self->quant, self->max_ticks, hzoom);
   guint i;
   /* readjust markers */
   for (i = 0; i < scc->n_markers; i++)
@@ -1183,7 +1207,7 @@ piano_roll_time_signature_changed (BstPianoRoll *self)
     {
       SfiInt numerator, denominator, tpqn;
       bse_proxy_get (self->song, "numerator", &numerator, "denominator", &denominator, "tpqn", &tpqn, NULL);
-      bst_piano_roll_hsetup (self, tpqn * 4 / denominator, numerator, tpqn, self->max_ticks, self->hzoom);
+      bst_piano_roll_hsetup (self, tpqn * 4 / denominator, numerator, tpqn, self->quant, self->max_ticks, self->hzoom);
     }
 }
 
@@ -1206,7 +1230,7 @@ piano_roll_range_changed (BstPianoRoll *self)
 {
   guint max_ticks;
   bse_proxy_get (self->proxy, "last-tick", &max_ticks, NULL);
-  bst_piano_roll_hsetup (self, self->ppb, self->bpt, self->tpqn, MAX (max_ticks, 1), self->hzoom);
+  bst_piano_roll_hsetup (self, self->ppb, self->bpt, self->tpqn, self->quant, MAX (max_ticks, 1), self->hzoom);
 }
 
 static void
@@ -1476,6 +1500,13 @@ bst_piano_roll_set_marker (BstPianoRoll          *self,
     piano_roll_move_marker (self, marker);
 }
 
+void
+bst_piano_roll_set_quant (BstPianoRoll          *self,
+                          guint                  quant)
+{
+  bst_piano_roll_hsetup (self, self->ppb, self->bpt, self->tpqn, quant, self->max_ticks, self->hzoom);
+}
+
 static void
 bst_piano_roll_class_init (BstPianoRollClass *class)
 {
index 67b5696..6bbb974 100644 (file)
@@ -68,6 +68,8 @@ struct _BstPianoRoll
   guint          tpqn;          /* ticks per quarter note */
   guint                 ppb;           /* parts per beat */
   guint                 bpt;           /* beats per tact */
+  guint          quant;         /* quantization */
+  guint          quant_ticks;   /* ticks per quantization step */
   guint                 max_ticks;     /* in ticks */
   gfloat        hzoom;
 
@@ -76,8 +78,8 @@ struct _BstPianoRoll
   gint           start_note;
   guint          start_valid : 1;
 
-  guint                 draw_qn_grid : 1;
-  guint                 draw_qqn_grid : 1;
+  guint                 draw_beat_grid : 1;
+  guint                 draw_quant_grid : 1;
 
   /* slight hack */
   guint          release_closes_toplevel : 1;
@@ -129,6 +131,8 @@ void    bst_piano_roll_set_marker               (BstPianoRoll          *self,
                                                  guint                  mark_index,
                                                  guint                  position,
                                                  BstPianoRollMarkerType mtype);
+void    bst_piano_roll_set_quant                (BstPianoRoll          *self,
+                                                 guint                  quant);
 
      
 G_END_DECLS
index 51778e1..24a1294 100644 (file)
@@ -170,6 +170,13 @@ controller_reset_canvas_cursor (BstPianoRollController *self)
   controller_update_canvas_cursor (self, self->canvas_rtools->action_id);
 }
 
+static void
+controller_change_quantization (BstPianoRollController *self)
+{
+  bst_piano_roll_set_quant (self->proll, QUANTIZATION (self));
+}
+
+
 BstPianoRollController*
 bst_piano_roll_controller_new (BstPianoRoll *proll)
 {
@@ -199,6 +206,9 @@ bst_piano_roll_controller_new (BstPianoRoll *proll)
   /* quantization selection */
   self->quant_rtools = gxk_action_group_new ();
   gxk_action_group_select (self->quant_rtools, BST_QUANTIZE_NOTE_8);
+  g_signal_connect_swapped (self->quant_rtools, "changed",
+                            G_CALLBACK (controller_change_quantization), self);
+  controller_change_quantization (self);
   /* update from action group */
   g_signal_connect_swapped (self->canvas_rtools, "changed",
                             G_CALLBACK (controller_reset_canvas_cursor), self);