]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond into jneeman
authorJoe Neeman <joeneeman@gmail.com>
Sun, 4 Feb 2007 09:22:35 +0000 (11:22 +0200)
committerJoe Neeman <joeneeman@gmail.com>
Sun, 4 Feb 2007 09:22:35 +0000 (11:22 +0200)
Conflicts:

lily/grob-property.cc

21 files changed:
input/mutopia/F.Schubert/morgenlied.ly
input/mutopia/R.Schumann/romanze-op28-2.ly
lily/align-interface.cc
lily/axis-group-interface.cc
lily/constrained-breaking.cc
lily/context.cc
lily/grob-property.cc
lily/include/context.hh
lily/include/grob.hh
lily/include/lily-guile-macros.hh
lily/include/prob.hh
lily/line-spanner.cc
lily/main.cc
lily/page-spacing.cc
lily/paper-column-engraver.cc
lily/prob.cc
lily/simple-spacer.cc
lily/spaceable-grob.cc
ly/graphviz.ly [new file with mode: 0644]
scm/graphviz.scm [new file with mode: 0644]
scm/lily.scm

index fafb7f39bdc84e9c82bcec66350ecd66753366cd..176b388c758ae97cedc97cb53683900ad131d07d 100644 (file)
@@ -180,10 +180,6 @@ pianoLH =  \relative c'' \repeat volta 2 {
                \override SpacingSpanner #'spacing-increment = #1.0
                \override Slur #'height-limit = #1.5
            }
-           \context {
-               \PianoStaff
-               \override VerticalAlignment #'forced-distance = #10
-           }
        }
        \midi {
          \context {
index 770a6c0b2cd9007e3e31187d2d88e36ff7444f77..0721b1f7861897df7b71d030960d45218d25ff61 100644 (file)
@@ -283,10 +283,6 @@ leftb =  \transpose c cis {
       \Score
       \override SpacingSpanner #'common-shortest-duration = #(ly:make-moment 1 8)
     }
-    \context {
-      \PianoStaff
-      \override VerticalAlignment #'forced-distance = #13.0
-    }
   }
   
   \midi {
index 786e91010bf00c10c9958306893a4caf72ab0588..9424877f5ee8b28c0279711bd18609433892fec8 100644 (file)
@@ -125,8 +125,6 @@ get_skylines (Grob *me,
          Skyline_pair *skys = Skyline_pair::unsmob (g->get_property ("skylines"));
          if (skys)
            skylines = *skys;
-         else
-           programming_error ("no skylines for alignment-child\n");
 
          /* this is perhaps an abuse of minimum-?-extent: maybe we should create
             another property? But it seems that the only (current) use of
index 19340c0c1dde0101a17e7c18de73382b759beb01..7f6d1ef6b527af167bd0941630f6dae90ec348ac 100644 (file)
@@ -437,9 +437,7 @@ add_grobs_of_one_priority (Skyline_pair *const skylines,
          if (b[X_AXIS][LEFT] - 2*horizon_padding < last_affected_position[dir])
            continue;
 
-         if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ())
-           warning (_f ("outside-staff object %s has an empty extent", elements[i]->name ().c_str ()));
-         else
+         if (!b[X_AXIS].is_empty () && !b[Y_AXIS].is_empty ())
            {
              boxes.clear ();
              boxes.push_back (b);
index 714f8ce6eed9dc5332489d3513918fe03f591121..c688be6a1b54237b859f52375f086e9e9275da07 100644 (file)
@@ -301,6 +301,17 @@ Constrained_breaking::Constrained_breaking (Paper_score *ps, vector<vsize> const
   initialize ();
 }
 
+static SCM
+min_permission (SCM perm1, SCM perm2)
+{
+  if (perm1 == ly_symbol2scm ("force"))
+    return perm2;
+  if (perm1 == ly_symbol2scm ("allow")
+     && perm2 != ly_symbol2scm ("force"))
+    return perm2;
+  return SCM_EOL;
+}
+
 /* find the forces for all possible lines and cache ragged_ and ragged_right_ */
 void
 Constrained_breaking::initialize ()
@@ -354,6 +365,13 @@ Constrained_breaking::initialize ()
          line.break_permission_ = c->get_property ("line-break-permission");
          line.page_permission_ = c->get_property ("page-break-permission");
          line.turn_permission_ = c->get_property ("page-turn-permission");
+         
+         /* turn permission should always be stricter than page permission
+            and page permission should always be stricter than line permission */
+         line.page_permission_ = min_permission (line.break_permission_,
+                                                 line.page_permission_);
+         line.turn_permission_ = min_permission (line.page_permission_,
+                                                 line.turn_permission_);
 
          max_ext = max (max_ext, extent.length ());
          line.extent_ = extent;
index da83c9a98c07dc7242d3e84ae32420fe0dd939bb..3c982751fd6635e1822ad525a54471a2fb893a07 100644 (file)
@@ -460,6 +460,13 @@ Context::add_alias (SCM sym)
   aliases_ = scm_cons (sym, aliases_);
 }
 
+/* we don't (yet) instrument context properties */
+void
+Context::instrumented_set_property (SCM sym, SCM val, const char*, int, const char*)
+{
+  internal_set_property (sym, val);
+}
+
 void
 Context::internal_set_property (SCM sym, SCM val)
 {
index e7b59d954d6559d1babf22a0a0d173c0e1de8b38..084ea42fbdb60ede609beddcf35b61cf8889f876 100644 (file)
 
 #ifndef NDEBUG
 static SCM modification_callback = SCM_EOL;
+static SCM cache_callback = SCM_EOL;
 
 LY_DEFINE (ly_set_grob_modification_callback, "ly:set-grob-modification-callback",
           1, 0, 0, (SCM cb),
           "Specify a procedure that will be called every time lilypond modifies "
           "a grob property. The callback will receive as arguments "
-          "the grob that is being modified, the name of the C++ file in which "
-          "the modification was requested, the line number in the C++ file in "
-          "which the modification was requested, the property to be changed and "
+          "the grob that is being modified, "
+          "the name of the C++ file in which the modification was requested, "
+          "the line number in the C++ file in which the modification was requested, "
+          "the name of the function in which the modification was requested, "
+          "the property to be changed and "
           "the new value for the property.")
 {
   LY_ASSERT_TYPE (ly_is_procedure, cb, 1);
@@ -37,46 +40,29 @@ LY_DEFINE (ly_set_grob_modification_callback, "ly:set-grob-modification-callback
   modification_callback = cb;
   return SCM_UNSPECIFIED;
 }
-#endif
 
-SCM
-Grob::get_property_alist_chain (SCM def) const
+LY_DEFINE (ly_set_property_cache_callback, "ly:set-property-cache-callback",
+          1, 0, 0, (SCM cb),
+          "Specify a procedure that will be called whenever lilypond calculates "
+          "a callback function and caches the result. The callback will "
+          "receive as arguments "
+          "the grob whose property it is, "
+          "the name of the property, "
+          "the name of the callback that calculated the property and "
+          "the new (cached) value of the property.")
 {
-  return scm_list_n (mutable_property_alist_,
-                    immutable_property_alist_,
-                    def,
-                    SCM_UNDEFINED);
+  LY_ASSERT_TYPE (ly_is_procedure, cb, 1);
+  
+  cache_callback = cb;
+  return SCM_UNSPECIFIED;
 }
 
-
-extern void check_interfaces_for_property (Grob const *me, SCM sym);
-
-#if 0
-
-/*
-  We can't change signatures depending on NDEBUG, since NDEBUG comes
-  over the command line and may be different per .cc file.  This
-  should be done through the macro expansion of get_property ().
- */
 void
-Grob::internal_set_property (SCM sym, SCM v, char const *file, int line, char const *fun)
+Grob::instrumented_set_property (SCM sym, SCM v,
+                                char const *file,
+                                int line,
+                                char const *fun)
 {
-  SCM grob_p = ly_lily_module_constant ("ly:grob?");
-  SCM grob_list_p = ly_lily_module_constant ("grob-list?");
-  SCM type = scm_object_property (sym, ly_symbol2scm ("backend-type?"));
-
-  if (type == grob_p
-      || type == grob_list_p
-      || (unsmob_grob (v) && ly_symbol2scm ("cause") != sym))
-    {
-      scm_display (scm_list_2 (sym, type), scm_current_output_port ());
-      assert (0);
-    }
-  
-  internal_set_value_on_alist (&mutable_property_alist_,
-                              sym, v);
-
-
   if (ly_is_procedure (modification_callback))
     scm_apply_0 (modification_callback,
                 scm_list_n (self_scm (),
@@ -84,8 +70,21 @@ Grob::internal_set_property (SCM sym, SCM v, char const *file, int line, char co
                             scm_from_int (line),
                             scm_from_locale_string (fun),
                             sym, v, SCM_UNDEFINED));
+  internal_set_property (sym, v);
 }
-#else
+#endif
+
+SCM
+Grob::get_property_alist_chain (SCM def) const
+{
+  return scm_list_n (mutable_property_alist_,
+                    immutable_property_alist_,
+                    def,
+                    SCM_UNDEFINED);
+}
+
+extern void check_interfaces_for_property (Grob const *me, SCM sym);
+
 void
 Grob::internal_set_property (SCM sym, SCM v)
 {
@@ -93,7 +92,6 @@ Grob::internal_set_property (SCM sym, SCM v)
                               sym, v);
 
 }
-#endif
 
 void
 Grob::internal_set_value_on_alist (SCM *alist, SCM sym, SCM v)
@@ -213,7 +211,18 @@ Grob::try_callback_on_alist (SCM *alist, SCM sym, SCM proc)
        *alist = scm_assq_remove_x (*alist, marker);
     }
   else
-    internal_set_value_on_alist (alist, sym, value);
+    {
+#ifndef NDEBUG
+      if (ly_is_procedure (cache_callback))
+       scm_apply_0 (cache_callback,
+                    scm_list_n (self_scm (),
+                                sym,
+                                proc,
+                                value,
+                                SCM_UNDEFINED));
+#endif
+      internal_set_value_on_alist (alist, sym, value);
+    }
   
   return value;
 }
index 31b7baf19fedf4defcc43f84662959dc64802fc4..88019f4b88929324e051f3d563921b7e8a249bc1 100644 (file)
@@ -85,6 +85,7 @@ public:
   Context *where_defined (SCM name_sym, SCM *value) const;
   void unset_property (SCM var_sym);
 
+  void instrumented_set_property (SCM, SCM, const char*, int, const char*);
   void internal_set_property (SCM var_sym, SCM value);
 
   Context *create_context (Context_def *, string, SCM);
index 8fc0abc4e333203ef76f4376e7f0080128b4b10c..433ea7ec436a363bd3d40cab9ae70e8493b74c09 100644 (file)
@@ -84,6 +84,7 @@ public:
   SCM internal_get_object (SCM symbol) const;
   void internal_set_object (SCM sym, SCM val);
   void internal_del_property (SCM symbol);
+  void instrumented_set_property (SCM, SCM, char const*, int, char const*);
   void internal_set_property (SCM sym, SCM val);
 
   /* messages */  
index 6b0a60a2f041271bded2b8d938afb3acaeacc7c7..86d2517dee175fac6e1e8f7abd51d853900a3acd 100644 (file)
@@ -195,7 +195,7 @@ void ly_check_name (string cxx, string fname);
   TODO: include modification callback support here, perhaps
   through intermediate Grob::instrumented_set_property( .. __LINE__ ).
  */
-#define set_property(x, y) internal_set_property (ly_symbol2scm (x), y)  
+#define set_property(x, y) instrumented_set_property (ly_symbol2scm (x), y, __FILE__, __LINE__, __FUNCTION__)
 #else
 #define set_property(x, y) internal_set_property (ly_symbol2scm (x), y)
 #endif
index 839edd4abacdff4c1be17a8cabd93267d66ef271..b01fb4d42d6e8acc0ea9d389499c2c5f2ba037ca 100644 (file)
@@ -42,6 +42,7 @@ public:
   SCM type () const { return type_; }
   SCM get_property_alist (bool mutble) const;
   SCM internal_get_property (SCM sym) const;
+  void instrumented_set_property (SCM, SCM, const char*, int, const char*);
   void internal_set_property (SCM sym, SCM val);
 };
 DECLARE_UNSMOB(Prob,prob);
index db36434b04b252e7a33da6d629d94609ef29f9b2..f6315451724d0c6a7224ad6fdfdd10ccb9c2cf22 100644 (file)
@@ -36,7 +36,9 @@ public:
 static Grob *
 line_spanner_common_parent (Grob *me)
 {
-  Grob *common = find_fixed_alignment_parent (me);
+  /* FIXME: what is the right thing to do here, now that PianoStaves don't
+     have fixed spacing? */
+  Grob *common = 0; //find_fixed_alignment_parent (me);
   if (!common)
     {
       common = Staff_symbol_referencer::get_staff_symbol (me);
index 28f3587f3f198e6570620228cb36182660c85ff0..fd61dbb8c6c49be9779c28eeee0dccb0c5dc9aeb 100644 (file)
@@ -617,3 +617,25 @@ main (int argc, char **argv)
   /* Only reachable if GUILE exits.  That is an error.  */
   return 1;
 }
+
+SCM atexit_list = SCM_EOL;
+
+LY_DEFINE (ly_atexit, "ly:atexit",
+          2, 0, 0, (SCM proc, SCM args),
+          "Just before exiting, call the procedure given. "
+"If this is called multiple times, the procedures are called "
+"in LIFO order.")
+{
+  atexit_list = scm_cons (scm_cons (proc, args), atexit_list);
+  scm_gc_protect_object (atexit_list);
+  return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_do_atexit, "ly:do-atexit",
+          0, 0, 0, (),
+          "Call the atexit procedures.")
+{
+  for (SCM s = atexit_list; scm_is_pair (s); s = scm_cdr (s))
+    scm_apply_0 (scm_caar (s), scm_cdar (s));
+  return SCM_UNSPECIFIED;
+}
index 0b8f8295d6b8b446369ca82139771b9c93ef28c2..7803cc06f23034f87e31ea2910b12391ff758ae6 100644 (file)
@@ -91,7 +91,7 @@ compress_lines (const vector<Line_details> &orig)
 
   for (vsize i = 0; i < orig.size (); i++)
     {
-      if (ret.size () && ret.back ().page_permission_ == SCM_EOL)
+      if (ret.size () && !scm_is_symbol (ret.back ().page_permission_))
        {
          Line_details const &old = ret.back ();
          Line_details compressed = orig[i];
index 6a765628aa892424c8e9a81f94ad2d5eaeeb57b9..2df287aa371cf07a7d289c485981508d7c90e099 100644 (file)
@@ -191,9 +191,12 @@ Paper_column_engraver::stop_translation_timestep ()
     {
       command_column_->set_property ("page-break-permission", SCM_EOL);
       command_column_->set_property ("line-break-permission", SCM_EOL);
-      if (break_events_.size ())
-       warning (_f ("break event at moment %d/%d was overridden by some other event, are you using bar checks?",
-                    now_mom ().num (), now_mom ().den ()));
+      for (vsize i = 0; i < break_events_.size (); i++)
+       {
+         SCM perm = break_events_[i]->get_property ("permission");
+         if (perm == ly_symbol2scm ("force") || perm == ly_symbol2scm ("allow"))
+           warning (_f ("forced break was overridden by some other event, should you be using bar checks?"));
+       }
     }
   else if (Paper_column::is_breakable (command_column_))
     {
index ce51546d8e0f83f50582e840cecb25b9b09988de..4e068fa4d45301a7b19daea13b277e55e7795353 100644 (file)
@@ -157,6 +157,13 @@ Prob::internal_get_property (SCM sym) const
   return (s == SCM_BOOL_F) ? SCM_EOL : scm_cdr (s);
 }
 
+/* We don't (yet) instrument probs */
+void
+Prob::instrumented_set_property (SCM sym, SCM val, const char*, int, const char*)
+{
+  internal_set_property (sym, val);
+}
+
 void
 Prob::internal_set_property (SCM sym, SCM val) 
 {
index 9200554822b87030d8e0b6c452fd7b3fe5ba859a..3f4e678cd6d4ddf1c60f56ea69cc085eaba4999a 100644 (file)
@@ -274,7 +274,7 @@ bool
 Spring_description::is_sane () const
 {
   return (inverse_hooke_ >= 0)
-    && ideal_ > 0
+    && ideal_ >= 0
     && !isinf (ideal_) && !isnan (ideal_)
     && (inverse_hooke_ == 0.0 || fabs (inverse_hooke_) > 1e-8)
     ;
index ad6e7d61812bb9f959c6a5c806c50cd9f1abfdfc..806e300cfa5ff714b4ffb9c38192ccae35aec3e4 100644 (file)
@@ -59,7 +59,7 @@ void
 Spaceable_grob::add_spring (Grob *me, Grob *other,
                            Real distance, Real inverse_strength)
 {
-  if (distance <= 0.0 || inverse_strength < 0.0)
+  if (distance < 0.0 || inverse_strength < 0.0)
     {
       programming_error ("adding reverse spring, setting to unit");
       distance = 1.0;
diff --git a/ly/graphviz.ly b/ly/graphviz.ly
new file mode 100644 (file)
index 0000000..f488fd2
--- /dev/null
@@ -0,0 +1,69 @@
+\version "2.11.15"
+
+#(use-modules (scm graphviz))
+
+#(define last-grob-action '())
+
+#(define sym-blacklist '())
+#(define sym-whitelist '())
+
+#(define file-line-blacklist '())
+#(define file-line-whitelist '())
+
+#(define grob-blacklist '())
+#(define grob-whitelist '())
+
+#(define (blacklist-symbol sym)
+  (set! sym-blacklist (cons sym sym-blacklist)))
+
+#(define (whitelist-symbol sym)
+  (set! sym-whitelist (cons sym sym-whitelist)))
+
+#(define graph (make-graph "graph.dot"))
+
+% an event is relevant if
+% (it is on some whitelist or all whitelists are empty)
+% and
+% (it isn't on any blacklist)
+
+#(define (relevant? grob file line prop)
+  (let ((file-line `(,file . ,line)))
+   (and
+    (or
+     (= 0 (length file-line-whitelist) (length sym-whitelist))
+     (memq prop sym-whitelist)
+     (member file-line file-line-whitelist))
+    (and
+     (not (memq prop sym-blacklist))
+     (not (member file-line file-line-blacklist))))))
+
+#(define (grob-event-node grob label cluster)
+  (let ((node-id (add-node graph label cluster))
+       (prev (assv grob last-grob-action)))
+   (if (pair? prev)
+       (add-edge graph (cdr prev) node-id))
+   (set! last-grob-action (assv-set! last-grob-action grob node-id))))
+
+#(define (truncate-value val)
+  (let ((val-str (format "~a" val)))
+   (string-take val-str (min 50 (string-length val-str)))))
+
+#(define (grob-mod grob file line func prop val)
+  (let* ((val-str (truncate-value val))
+        (label (format "~a\\n~a:~a\\n~a <- ~a" grob file line prop val-str)))
+   (if (relevant? grob file line prop)
+       (grob-event-node grob label file))))
+
+#(define (grob-cache grob prop callback value)
+  (let* ((val-str (truncate-value value))
+        (label (format "caching ~a.~a\\n~a -> ~a" grob prop callback value)))
+   (if (relevant? grob #f #f prop)
+       (grob-event-node grob label #f))))
+
+#(define (grob-create grob file line func)
+  (let ((label (format "~a\\n~a:~a" grob file line)))
+   (grob-event-node grob label file)))
+
+#(ly:set-grob-modification-callback grob-mod)
+#(ly:set-property-cache-callback grob-cache)
+%#(ly:set-grob-creation-callback grob-create)
diff --git a/scm/graphviz.scm b/scm/graphviz.scm
new file mode 100644 (file)
index 0000000..8ad3600
--- /dev/null
@@ -0,0 +1,63 @@
+;;;; graphviz.scm -- utilities for creating graphviz output
+;;;;
+;;;;  source file of the GNU LilyPond music typesetter
+;;;;
+;;;; (c) 2007 Joe Neeman <joeneeman@gmail.com>
+
+
+(define-module (scm graphviz)
+  #:use-module (lily)
+  #:export (make-graph add-node add-edge add-cluster))
+
+(define (make-graph filename)
+  (let ((empty-graph (list->vector (list filename '() '() '()))))
+    (ly:atexit write-graph (list empty-graph))
+    empty-graph))
+
+(define (filename g) (vector-ref g 0))
+(define (nodes g) (vector-ref g 1))
+(define (edges g) (vector-ref g 2))
+(define (clusters g) (vector-ref g 3))
+
+(define (add-cluster graph node-id cluster-name)
+  (let* ((cs (clusters graph))
+        (cluster (assq cluster-name cs))
+        (already-in-cluster (if cluster
+                                (cdr cluster)
+                                '())))
+    (vector-set! graph 3 (assq-set! cs
+                                   cluster-name
+                                   (cons node-id already-in-cluster)))))
+
+(define (add-node graph label . cluster-name)
+  (let* ((ns (nodes graph))
+         (id (length ns)))
+    (vector-set! graph 1 (cons `(,id . ,label) ns))
+    (if (and (not (null? cluster-name))
+            (string? (car cluster-name)))
+       (add-cluster graph id (car cluster-name)))
+    id))
+
+(define (add-edge graph node1 node2)
+  (vector-set! graph 2 (cons `(,node1 . ,node2) (edges graph))))
+
+(define (write-graph graph)
+  (let ((out (open-file (filename graph) "w"))
+       (ns (nodes graph))
+       (es (edges graph))
+       (cs (clusters graph)))
+    (ly:message (format "writing graph ~s..." (filename graph)))
+    (display "digraph G {\nrankdir=\"LR\"\nnode [shape=rectangle]\n" out)
+    (map (lambda (n) (display (format "~a [label=\"~a\"]\n" (car n) (cdr n)) out))
+        ns)
+    (map (lambda (e) (display (format "~a -> ~a\n" (car e) (cdr e)) out))
+        es)
+    (map (lambda (c)
+         (display (format "subgraph cluster_~a {\nlabel= \"~a\"\ncolor=blue\n"
+                          (string-filter (car c) char-alphabetic?)
+                          (car c))
+                  out)
+         (map (lambda (n) (display (format "~a\n" n) out)) (cdr c))
+         (display "}\n" out))
+        cs)
+    (display "}" out)))
index b366507f5d1a05e909d7772a89795f80dc45135c..bccfc72d1d6d801f6fdf6f0f3dcfe403ab1f2c3d 100644 (file)
@@ -634,6 +634,7 @@ The syntax is the same as `define*-public'."
          (ly:error (_ "failed files: ~S") (string-join failed))
          (exit 1))
        (begin
+         (ly:do-atexit)
          ;; HACK: be sure to exit with single newline
          (ly:message "")
          (exit 0)))))