opus conversie
This commit is contained in:
+67
-26
@@ -7,6 +7,8 @@
|
||||
"private/audio.rkt"
|
||||
"private/config.rkt"
|
||||
"private/convert-place.rkt"
|
||||
"private/cover-art.rkt"
|
||||
"private/fingerprint.rkt"
|
||||
"private/hash.rkt"
|
||||
"private/log.rkt"
|
||||
"private/mail.rkt"
|
||||
@@ -18,20 +20,59 @@
|
||||
(provide manage-flac-tree
|
||||
summary->lines)
|
||||
|
||||
(define (file-info path digest)
|
||||
(list (cons 'digest digest)
|
||||
(cons 'size (file-size path))
|
||||
(define (quick-file-info path)
|
||||
(list (cons 'size (file-size path))
|
||||
(cons 'mtime (file-or-directory-modify-seconds path))))
|
||||
|
||||
(define (same-file-state? old digest)
|
||||
(define (same-quick-state? old path)
|
||||
(and old
|
||||
(equal? (alist-ref/default old 'digest #f) digest)
|
||||
(equal? (alist-ref/default old 'size #f) (file-size path))
|
||||
(equal? (alist-ref/default old 'mtime #f) (file-or-directory-modify-seconds path))
|
||||
(not (equal? (alist-ref/default old 'status #f) 'error))))
|
||||
|
||||
(define (process-one-file ks config path relpath inspect-flac-proc convert-proc summary errors)
|
||||
(define digest (file-digest path (manager-config-hash-algorithm config)))
|
||||
(define (same-signature-state? old signature)
|
||||
(and old
|
||||
(equal? (alist-ref/default old 'signature #f) signature)
|
||||
(not (equal? (alist-ref/default old 'status #f) 'error))))
|
||||
|
||||
(define (file-signature path config fingerprint-proc)
|
||||
(define mode (manager-config-change-detection config))
|
||||
(cond [(member mode '("hash" "sha256" "full-hash" "full-sha256"))
|
||||
(string-append "file:"
|
||||
(manager-config-hash-algorithm config)
|
||||
":"
|
||||
(file-digest path (manager-config-hash-algorithm config)))]
|
||||
[(member mode '("mtime-size" "quick"))
|
||||
(format "mtime-size:~a:~a" (file-size path) (file-or-directory-modify-seconds path))]
|
||||
[(member mode '("flac" "flac-streaminfo"))
|
||||
(string-append "flac-streaminfo:" (flac-streaminfo-fingerprint path))]
|
||||
[(or (member mode '("flac-taglib" "taglib+flac" "taglib-flac")) (not mode))
|
||||
(string-append "flac-taglib:" (fingerprint-proc path))]
|
||||
[else
|
||||
(error 'file-signature "unsupported change-detection mode: ~a" mode)]))
|
||||
|
||||
(define (state-info path signature status sample-rate extra)
|
||||
(append (quick-file-info path)
|
||||
(list (cons 'signature signature)
|
||||
(cons 'status status)
|
||||
(cons 'sample-rate sample-rate))
|
||||
extra))
|
||||
|
||||
(define (maybe-set-sidecar-picture! path relpath)
|
||||
(with-handlers ([exn:fail? (lambda (e)
|
||||
(warn-alm "could not set sidecar cover for ~a: ~a" relpath (exn-message e))
|
||||
#f)])
|
||||
(define cover (ensure-flac-sidecar-picture! path))
|
||||
(when cover (info-alm "embedded sidecar cover in ~a from ~a" relpath cover))
|
||||
cover))
|
||||
|
||||
(define (process-one-file ks config path relpath inspect-flac-proc fingerprint-proc convert-proc summary errors)
|
||||
;; Only invokes TagLib when a sidecar cover/folder image exists in the same directory.
|
||||
;; This keeps the cheap mtime/size fast path cheap for most directories, but still
|
||||
;; lets the manager repair missing embedded artwork before fingerprinting.
|
||||
(maybe-set-sidecar-picture! path relpath)
|
||||
(define old (state-get-file ks relpath #f))
|
||||
(cond [(same-file-state? old digest)
|
||||
(cond [(same-quick-state? old path)
|
||||
(info-alm "unchanged: ~a" relpath)
|
||||
(values (summary-inc (summary-inc summary 'seen) 'unchanged) errors)]
|
||||
[else
|
||||
@@ -41,7 +82,7 @@
|
||||
(lambda (e)
|
||||
(err-alm "error for ~a: ~a" relpath (exn-message e))
|
||||
(state-set-file! ks relpath
|
||||
(append (file-info path digest)
|
||||
(append (quick-file-info path)
|
||||
(list (cons 'status 'error)
|
||||
(cons 'message (exn-message e)))))
|
||||
(values (summary-inc summary2 'errors)
|
||||
@@ -49,35 +90,33 @@
|
||||
(cons 'message (exn-message e)))
|
||||
errors)))])
|
||||
(define sample-rate (inspect-flac-proc path))
|
||||
(cond [(> sample-rate (manager-config-max-sample-rate config))
|
||||
(define signature (file-signature path config fingerprint-proc))
|
||||
(cond [(same-signature-state? old signature)
|
||||
(info-alm "unchanged fingerprint: ~a" relpath)
|
||||
(state-set-file! ks relpath (state-info path signature 'unchanged sample-rate '()))
|
||||
(values (summary-inc summary2 'unchanged) errors)]
|
||||
[(> sample-rate (manager-config-max-sample-rate config))
|
||||
(if (manager-config-dry-run? config)
|
||||
(begin
|
||||
(warn-alm "dry-run: would convert ~a from ~a Hz to ~a Hz" relpath sample-rate (manager-config-max-sample-rate config))
|
||||
(state-set-file! ks relpath
|
||||
(append (file-info path digest)
|
||||
(list (cons 'status 'dry-run)
|
||||
(cons 'sample-rate sample-rate))))
|
||||
(state-info path signature 'dry-run sample-rate '()))
|
||||
(values (summary-inc (summary-inc summary2 'skipped) 'dry-run) errors))
|
||||
(begin
|
||||
(info-alm "converting ~a from ~a Hz to ~a Hz" relpath sample-rate (manager-config-max-sample-rate config))
|
||||
(let* ((result (convert-proc path
|
||||
(manager-config-max-sample-rate config)
|
||||
(manager-config-compression-level config)))
|
||||
(new-digest (file-digest path (manager-config-hash-algorithm config)))
|
||||
(new-sample-rate (inspect-flac-proc path)))
|
||||
(new-sample-rate (inspect-flac-proc path))
|
||||
(new-signature (file-signature path config fingerprint-proc)))
|
||||
(state-set-file! ks relpath
|
||||
(append (file-info path new-digest)
|
||||
(list (cons 'status 'converted)
|
||||
(cons 'old-sample-rate sample-rate)
|
||||
(cons 'sample-rate new-sample-rate)
|
||||
(cons 'encoder-result result))))
|
||||
(state-info path new-signature 'converted new-sample-rate
|
||||
(list (cons 'old-sample-rate sample-rate)
|
||||
(cons 'encoder-result result))))
|
||||
(values (summary-inc summary2 'converted) errors))))]
|
||||
[else
|
||||
(info-alm "ok: ~a (~a Hz)" relpath sample-rate)
|
||||
(state-set-file! ks relpath
|
||||
(append (file-info path digest)
|
||||
(list (cons 'status 'ok)
|
||||
(cons 'sample-rate sample-rate))))
|
||||
(state-set-file! ks relpath (state-info path signature 'ok sample-rate '()))
|
||||
(values (summary-inc summary2 'ok) errors)]))]))
|
||||
|
||||
(define (drop-removed! ks current-relpaths summary)
|
||||
@@ -92,8 +131,9 @@
|
||||
|
||||
(define (manage-flac-tree base-directory
|
||||
#:inspect-flac-proc [inspect-flac-proc inspect-flac-sample-rate]
|
||||
#:fingerprint-proc [fingerprint-proc flac-taglib-fingerprint]
|
||||
#:convert-proc [convert-proc convert-flac-to-target-in-place])
|
||||
(define base-dir (simple-form-path base-directory))
|
||||
(define base-dir (filesystem-path base-directory))
|
||||
(unless (directory-exists? base-dir)
|
||||
(raise-argument-error 'manage-flac-tree "existing directory" base-directory))
|
||||
(define config (load-manager-config base-dir))
|
||||
@@ -101,13 +141,14 @@
|
||||
(info-alm "base directory: ~a" base-dir)
|
||||
(info-alm "state file: ~a" (manager-config-state-file config))
|
||||
(info-alm "ini file: ~a" (manager-config-ini-file config))
|
||||
(info-alm "change detection: ~a" (manager-config-change-detection config))
|
||||
(define ks (open-manager-state (manager-config-state-file config)))
|
||||
(define files (find-flac-files base-dir))
|
||||
(define relpaths (map (lambda (p) (relpath-string base-dir p)) files))
|
||||
(define summary0 (drop-removed! ks relpaths (make-empty-summary)))
|
||||
(define-values (summary errors)
|
||||
(for/fold ([summary summary0] [errors '()]) ([p (in-list files)] [rel (in-list relpaths)])
|
||||
(process-one-file ks config p rel inspect-flac-proc convert-proc summary errors)))
|
||||
(process-one-file ks config p rel inspect-flac-proc fingerprint-proc convert-proc summary errors)))
|
||||
(define errors* (reverse errors))
|
||||
(with-handlers ([exn:fail? (lambda (e) (err-alm "mail report failed: ~a" (exn-message e)) (void))])
|
||||
(maybe-send-report-mail config summary errors*))
|
||||
|
||||
Reference in New Issue
Block a user