]> git.donarmstrong.com Git - lilypond.git/blobdiff - scm/backend-library.scm
Merge branch 'master' into beaming
[lilypond.git] / scm / backend-library.scm
index 5920c9977698adc5276f3498e4829572b54fb92d..8963fe15caf9b344f55ec26cd19a1aba39d0bcfa 100644 (file)
 ;;;;
 ;;;;  source file of the GNU LilyPond music typesetter
 ;;;; 
 ;;;;
 ;;;;  source file of the GNU LilyPond music typesetter
 ;;;; 
-;;;; (c)  2005 Jan Nieuwenhuizen <janneke@gnu.org>
-;;;; Han-Wen Nienhuys <hanwen@cs.uu.nl>
+;;;; (c) 2005--2007 Jan Nieuwenhuizen <janneke@gnu.org>
+;;;; Han-Wen Nienhuys <hanwen@xs4all.nl>
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
 ;; backend helpers.
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
 ;; backend helpers.
 
-(define-public (ly:system command)
+(define-public (ly:system command . rest)
   (let* ((status 0)
   (let* ((status 0)
-        (silenced
-         (string-append command (if (ly:get-option 'verbose)
-                                    ""
-                                    " > /dev/null 2>&1 "))))
-
+        (dev-null "/dev/null")
+        (silenced (if (or (ly:get-option 'verbose)
+                          (not (access? dev-null W_OK)))
+                      command
+                      (format #f "~a > ~a 2>&1 " command dev-null))))
     (if (ly:get-option 'verbose)
     (if (ly:get-option 'verbose)
-       (format (current-error-port) (_ "Invoking `~a'...") command))
-    
-    (set! status (system silenced))
+       (ly:message (_ "Invoking `~a'...") command))
+
+    (set! status
+         (if (pair? rest)
+             (system-with-env silenced (car rest))
+             (system silenced)))
+       
     (if (> status 0)
        (begin
     (if (> status 0)
        (begin
-         (format (current-error-port) (_ "`~a' failed (~a)") command status)
-         (newline (current-error-port))
-         
+         (ly:message (_ "`~a' failed (~a)") command status)
+         (ly:progress "\n")
          ;; hmmm.  what's the best failure option? 
          (throw 'ly-file-failed)))))
 
          ;; hmmm.  what's the best failure option? 
          (throw 'ly-file-failed)))))
 
+(define-public (system-with-env cmd env)
+
+  "Execute CMD in fork, with ENV (a list of strings) as the environment"
+  (let*
+      ;; laziness: should use execle?
+      
+      ((pid (primitive-fork)))
+    (if (= 0 pid)
+       ;; child
+       (begin
+         (environ env)
+         (system cmd))
+       
+       ;; parent
+       (cdr (waitpid pid)))))
+
 (define-public (sanitize-command-option str)
 (define-public (sanitize-command-option str)
+  "Kill dubious shell quoting"
+  
   (string-append
    "\""
   (string-append
    "\""
-   (regexp-substitute/global #f "[^- 0-9,.a-zA-Z'\"\\]" str 'pre 'post)
+   (regexp-substitute/global #f "[^-_ 0-9,.a-zA-Z'\"\\]" str 'pre 'post)
    "\""))
 
    "\""))
 
-(define-public (postscript->pdf papersizename name)
-  (let* ((cmd (format #f "ps2pdf -sPAPERSIZE=~a '~a'"
-                     (sanitize-command-option papersizename) name))
-        (pdf-name (string-append (basename name ".ps") ".pdf" )))
+(define-public (search-executable names)
+  (define (helper path lst)
+    (if (null? (cdr lst))
+       (car lst)
+       (if (search-path path (car lst)) (car lst)
+           (helper path (cdr lst)))))
+
+  (let ((path (parse-path (getenv "PATH"))))
+    (helper path names)))
+
+(define-public (search-gs)
+  
+  ;; must be sure that we don't catch stuff from old GUBs.
+  (search-executable '("gs")))
+  
+(define-public (postscript->pdf paper-width paper-height name)
+  (let* ((pdf-name (string-append
+                   (dir-basename name ".ps" ".eps")
+                   ".pdf"))
+        (is-eps (string-match "\\.eps$" name))
+        (paper-size-string (if is-eps
+                               " -dEPSCrop "
+                               (ly:format "-dDEVICEWIDTHPOINTS=~$ \
+-dDEVICEHEIGHTPOINTS=~$ "
+                                       paper-width paper-height )))
+
+        (cmd (simple-format #f
+                     "~a\
+ ~a\
+ ~a\
+ ~a\
+ -dCompatibilityLevel=1.4 \
+ -dNOPAUSE\
+ -dBATCH\
+ -r1200 \
+ -sDEVICE=pdfwrite\
+ -sOutputFile=~S\
+ -c .setpdfwrite\
+ -f ~S\
+"
+                     (search-gs)
+                     (if (ly:get-option 'verbose) "" "-q")
+                     (if (or (ly:get-option 'gs-load-fonts)
+                             (ly:get-option 'gs-load-lily-fonts))
+                             
+                         " -dNOSAFER "
+                         " -dSAFER ")
+                     paper-size-string
+                     pdf-name
+                     name)))
+    ;; The wrapper on windows cannot handle `=' signs,
+    ;; gs has a workaround with #.
+    (if (eq? PLATFORM 'windows)
+       (begin
+         (set! cmd (string-regexp-substitute "=" "#" cmd))
+         (set! cmd (string-regexp-substitute "-dSAFER " "" cmd))))
 
     (if (access? pdf-name W_OK)
        (delete-file pdf-name))
 
 
     (if (access? pdf-name W_OK)
        (delete-file pdf-name))
 
-    (format (current-error-port) (_ "Converting to `~a'...") pdf-name)
+    (ly:message (_ "Converting to `~a'...") pdf-name)
+    (ly:progress "\n")
     (ly:system cmd)))
 
     (ly:system cmd)))
 
-(define-public (postscript->png resolution papersizename name)
-  (let* ((prefix (ly:effective-prefix))
-        ;; FIXME: should scripts/ps2png.py be installed in PREFIX?
-        (ps2png-source (if prefix
-                          (format "~a/scripts/ps2png.py" prefix)
-                          "ps2png"))
-        (cmd (format #f
-                     "~a --resolution=~S --papersize=~a~a '~a'"
-                     (if (file-exists? ps2png-source)
-                         (format "python ~a" ps2png-source)
-                         "ps2png")
-                     resolution
-                     (sanitize-command-option papersizename)
-                     (if (ly:get-option 'verbose) " --verbose " "")
-                     name)))
-    ;; Do not try to guess the name of the png file
-    (format (current-error-port) (_ "Converting to `~a'...") "png")
-    (ly:system cmd)))
+(use-modules (scm ps-to-png))
+
+(define-public (postscript->png resolution paper-width paper-height name)
+  (let* ((verbose (ly:get-option 'verbose))
+        (rename-page-1 #f))
+
+    ;; Do not try to guess the name of the png file,
+    ;; GS produces PNG files like BASE-page%d.png.
+    (ly:message (_ "Converting to ~a...") "PNG")
+    (make-ps-images name
+                   #:resolution resolution
+                   #:page-width paper-width
+                   #:page-height paper-height
+                   #:rename-page-1 rename-page-1
+                   #:be-verbose verbose
+                   #:anti-alias-factor (ly:get-option 'anti-alias-factor)
+                   #:pixmap-format (ly:get-option 'pixmap-format))
+    (ly:progress "\n")))
 
 (define-public (postprocess-output paper-book module filename formats)
 
 (define-public (postprocess-output paper-book module filename formats)
-  (for-each
-   (lambda (f)
-     ((eval (string->symbol (string-append "convert-to-" f))
-           module)
-      paper-book filename))
-   
-   formats))
+  (let* ((completed (completize-formats formats))
+        (base (string-regexp-substitute "\\.[a-z]+$" "" filename))
+        (intermediate (remove (lambda (x) (member x formats)) completed)))
+    
+    (for-each (lambda (f)
+               ((eval (string->symbol (format "convert-to-~a" f))
+                      module) paper-book filename)) completed)
+    (if (ly:get-option 'delete-intermediate-files)
+       (for-each (lambda (f)
+                   (delete-file (string-append base "." f))) intermediate))))
 
 (define-public (completize-formats formats)
   (define new-fmts '())
 
 (define-public (completize-formats formats)
   (define new-fmts '())
-
   (if (member "png" formats)
       (set! formats (cons "ps" formats)))
   (if (member "pdf" formats)
       (set! formats (cons "ps" formats)))
   (if (member "png" formats)
       (set! formats (cons "ps" formats)))
   (if (member "pdf" formats)
       (set! formats (cons "ps" formats)))
-
-  (for-each
-   (lambda (x)
-     (if (member x formats) (set! new-fmts (cons x new-fmts))))
-   '("tex" "dvi" "ps" "pdf" "png"))
-
-  (reverse new-fmts))
+  (for-each (lambda (x)
+             (if (member x formats) (set! new-fmts (cons x new-fmts))))
+           '("tex" "dvi" "ps" "pdf" "png"))
+  (uniq-list (reverse new-fmts)))
 
 (define (header-to-file file-name key value)
   (set! key (symbol->string key))
   (if (not (equal? "-" file-name))
       (set! file-name (string-append file-name "." key)))
 
 (define (header-to-file file-name key value)
   (set! key (symbol->string key))
   (if (not (equal? "-" file-name))
       (set! file-name (string-append file-name "." key)))
-  (format (current-error-port)
-         (_ "Writing header field `~a' to `~a'...")
-         key
-         (if (equal? "-" file-name) "<stdout>" file-name))
+  (ly:message (_ "Writing header field `~a' to `~a'...")
+             key
+             (if (equal? "-" file-name) "<stdout>" file-name))
   (if (equal? file-name "-")
       (display value)
   (if (equal? file-name "-")
       (display value)
-      (display value (open-file file-name "w")))
-  (newline (current-error-port))
+      (let ((port (open-file file-name "w")))
+       (display value port)
+       (close-port port)))
+
+  (ly:progress "\n")
   "")
 
 (define-public (output-scopes scopes fields basename)
   "")
 
 (define-public (output-scopes scopes fields basename)