emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/subed 504ac658fb 5/8: waveform: subed-waveform-preview-mse


From: ELPA Syncer
Subject: [nongnu] elpa/subed 504ac658fb 5/8: waveform: subed-waveform-preview-msecs-before / after, and more mouse commands
Date: Sun, 18 Jun 2023 16:02:31 -0400 (EDT)

branch: elpa/subed
commit 504ac658fb89a5ef73bf0bea180a0a2ed57c3432
Author: Sacha Chua <sacha@sachachua.com>
Commit: Sacha Chua <sacha@sachachua.com>

    waveform: subed-waveform-preview-msecs-before / after, and more mouse 
commands
    
    * subed/subed-waveform.el: Add more documentation.
    (subed-waveform-preview-msecs-before): New option. I decided to use
    msecs here because it's cleaner and fits into the way other parts of
    subed use msecs. I'd like to change subed-loop-seconds-before to
    subed-loop-msecs-before etc. someday...
    (subed-waveform-preview-msecs-after): New option.
    (subed-waveform-sample-msecs): New option, copied over from 
sachac/subed-waveform.
    (subed-waveform-remove): Try to remove all the overlays from
    subed-waveform, in case something has gotten very confused.
    (subed-waveform-minor-mode): Remember to put the SVG on.
    (subed-waveform-minor-mode-map): Move the keys to the minor mode map.
    (subed-waveform--start): Local variable.
    (subed-waveform--stop): Local variable.
    (subed-waveform--pixels-per-second): Useful for mouse events.
    (subed-waveform--position-to-percent): Return nil if position is nil.
    (subed-waveform--set-svg): Use subed-preview-msecs-before / after, and
    store subed-waveform--pixels-per-second.
    (subed-waveform--update-current-bar): Do this only if playback
    position is non-nil.
    (subed-waveform-svg-map): Add the button clicks to the SVG map, and
    include some of the features from sachac/subed-waveform.
    (subed-waveform--update-overlay-svg): Rename the map to 
subed-waveform-svg-map.
    (subed-waveform-put-svg): Check if we're in a valid subtitle before
    adding the overlay.
    (subed-waveform--mouse-event-to-ms): Indentation.
    (subed-waveform-reduce-start-time, subed-waveform-increase-stop-time,
    subed-waveform-split, subed-waveform--sample-timer,
    subed-waveform-jump-to-timestamp,
    subed-waveform--restore-mpv-position, subed-waveform-play-sample):
    Copied from sachac/subed-waveform with a few tweaks.
    * subed/subed.el (subed-mode-map): Remove subed-waveform keys.
---
 subed/subed-waveform.el | 293 ++++++++++++++++++++++++++++++++++++++----------
 subed/subed.el          |   3 -
 2 files changed, 232 insertions(+), 64 deletions(-)

diff --git a/subed/subed-waveform.el b/subed/subed-waveform.el
index 9980d780aa..c4b05380b6 100644
--- a/subed/subed-waveform.el
+++ b/subed/subed-waveform.el
@@ -24,8 +24,47 @@
 ;; displaying a waveform along with the current subtitle.  Use
 ;; `subed-waveform-minor-mode' to turn the waveform display on or off.
 ;; Press `C-x C-=' and `C-x C--' to make the amplitude of the
-;; displayed waveform larger and smaller. Click the waveform with
-;; `mouse-1'/`mouse-2' to set the start/stop timestamp.
+;; displayed waveform larger and smaller.
+
+;; To set the start time, click the waveform with `mouse-1' (left-click).
+;; To set the stop time, use `mouse-3' (right-click).
+;; You can also adjust start/stop times with the following
+;; keybindings from `subed-mode-map':
+;; M-[ - `subed-decrease-start-time'
+;; M-] - `subed-increase-start-time'
+;; M-{ - `subed-decrease-stop-time'
+;; M-} - `subed-increase-stop-time'
+
+;; To play a sample from the middle of a waveform, middle-click on the
+;; position you would like to play.  This plays
+;; `subed-waveform-sample-msecs' milliseconds and then sets the
+;; playing position to that point.
+
+;; You can shift-drag with `mouse-1' (left mouse button) to the left
+;; of a subtitle's waveform in order to extend the view earlier and
+;; set the start time. `Shift-drag-mouse-3' (right mouse button) to
+;; extend the view later and set the stop time.
+
+;; To split a subtitle in the middle using the text at point, use
+;; S-C-mouse-2 (control-shift middle-click), which is bound to
+;; `subed-waveform-split'.
+
+;; Customization:
+
+;; Use `M-x customize-group subed-waveform' to configure options.  To
+;; change how much time you see before or after the current subtitle,
+;; set `subed-waveform-preview-msecs-before' and
+;; `subed-waveform-preview-msecs-after'. You may also want to adjust
+;; `subed-loop-seconds-before' and `subed-loop-seconds-after' if you
+;; want this to match the looping behavior toggled with
+;; `subed-toggle-loop-over-current-subtitle'. (Note the switch from
+;; milliseconds to seconds.)  The boundaries of the current subtitle
+;; as well as the current playing position are indicated with the
+;; colors set in `subed-waveform-bar-params'.
+;;
+;; To change how your adjustments affect previous/next subtitles,
+;; customize the `subed-enforce-time-boundaries' and
+;; `subed-subtitle-spacing' variables.
 
 ;; To automatically display subtitles whenever you open a subed file,
 ;; add the following to your configuration:
@@ -33,24 +72,20 @@
 ;; (with-eval-after-load 'subed
 ;;   (add-hook 'subed-mode-hook 'subed-waveform-minor-mode))
 ;;
+;; Troubleshooting:
+
 ;; If the waveform becomes corrupted or is out of sync (this may
 ;; happen for example when you modify the start/stop timestamp(s)
 ;; using Subed mode commands but then undo your changes), press `C-c
 ;; |' to redisplay it.
 
-;; Use `M-x customize-group subed-waveform' to configure.  Consider
-;; setting `subed-loop-seconds-before' and `subed-loop-seconds-after'
-;; to positive values for better experience.
-;;
 ;; If images are not displayed, you may want to make sure that
 ;; `max-image-size' is set to a value that allows short, wide images.
-;; The following code:
+;; The following code may help:
 ;;
 ;; (with-eval-after-load 'subed
 ;;   (add-hook 'subed-mode-hook (lambda () (setq-local max-image-size nil))))
 ;;
-;; may do the trick.
-;; (TODO: Set this up in the code.)
 
 ;;; Code:
 
@@ -94,6 +129,22 @@ SVG parameters of the displayed bars.  Every bar must have 
a unique
                :value-type (plist :key-type symbol :value-type string))
   :group 'subed-waveform)
 
+(defcustom subed-waveform-preview-msecs-before 2000
+  "Prelude in milliseconds displaying subtitle waveform."
+  :type 'integer
+  :group 'subed-waveform)
+
+(defcustom subed-waveform-preview-msecs-after 2000
+  "Addendum in seconds when displaying subtitle waveform."
+  :type 'integer
+  :group 'subed-waveform)
+
+(defcustom subed-waveform-sample-msecs 2000
+  "Number of milliseconds to play when jumping around a waveform.
+0 or nil means don't play a sample."
+  :type 'integer
+  :group 'subed-waveform)
+
 (defcustom subed-waveform-volume
   2.0
   "A multiplier of the volume.
@@ -113,6 +164,7 @@ rounded to the nearest multiple of this number."
 (defun subed-waveform-remove ()
   "Remove waveform overlay."
   (interactive)
+       (remove-overlays (point-min) (point-max) 'subed-waveform t)
   (when (overlayp subed-waveform--image-overlay)
     (delete-overlay subed-waveform--image-overlay)))
 
@@ -128,7 +180,8 @@ rounded to the nearest multiple of this number."
         (add-hook 'subed-subtitle-motion-hook #'subed-waveform-put-svg nil t)
         (add-hook 'after-change-motion-hook #'subed-waveform-put-svg nil t)
                                (add-hook 'subed-mpv-playback-position-hook 
#'subed-waveform--update-current-bar t)
-        (add-hook 'subed-subtitle-time-adjusted-hook #'subed-waveform-put-svg 
nil t))
+        (add-hook 'subed-subtitle-time-adjusted-hook #'subed-waveform-put-svg 
nil t)
+                               (subed-waveform-put-svg))
     (subed-waveform-remove)
     (remove-hook 'before-save-hook #'subed-waveform-remove t)
     (remove-hook 'after-save-hook #'subed-waveform-put-svg t)
@@ -137,6 +190,14 @@ rounded to the nearest multiple of this number."
                (remove-hook 'subed-mpv-playback-position-hook 
#'subed-waveform--update-current-bar t)
     (remove-hook 'after-change-motion-hook #'subed-waveform-put-svg t)))
 
+(defvar subed-waveform-minor-mode-map
+       (let ((map (make-sparse-keymap)))
+               (define-key map (kbd "C-c C-=") 
#'subed-waveform-volume-increase)
+    (define-key map (kbd "C-c C--") #'subed-waveform-volume-decrease)
+    (define-key map (kbd "C-c |") #'subed-waveform-put-svg)
+               map)
+       "Keymap for `subed-waveform-minor-mode'.")
+
 (defconst subed-waveform-volume-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "C-=") #'subed-waveform-volume-increase)
@@ -200,10 +261,12 @@ and HEIGHT are dimensions in pixels."
                        (apply 'call-process subed-waveform-ffmpeg-executable 
nil t nil args)
                        (encode-coding-string (buffer-string) 'binary))))
 
-(defvar subed-waveform--start nil
+(defvar-local subed-waveform--start nil
   "Timestamp (in milliseconds) of the start of the waveform.")
-(defvar subed-waveform--stop nil
+(defvar-local subed-waveform--stop nil
   "Timestamp (in milliseconds) of the stop of the waveform.")
+(defvar-local subed-waveform--pixels-per-second nil
+       "Number of pixels used for displaying one second.")
 
 (defun subed-waveform--msecs-to-ffmpeg (msecs)
   "Convert MSECS to string in the format HH:MM:SS.MS."
@@ -212,7 +275,8 @@ and HEIGHT are dimensions in pixels."
 
 (defun subed-waveform--position-to-percent (pos start stop)
   "Return a percentage of POS relative to START/STOP."
-  (format "%s%%" (/ (* 100 (- pos start)) (- stop start))))
+       (when pos
+               (format "%s%%" (/ (* 100 (- pos start)) (- stop start)))))
 
 (defvar-local subed-waveform--pos nil
   "Buffer position of the image with the current waveform.")
@@ -229,29 +293,31 @@ and HEIGHT are dimensions in pixels."
 Set `subed-waveform--svg' and `subed-waveform--pos'."
   (save-excursion
     (let ((start (subed-subtitle-msecs-start))
-         (stop (subed-subtitle-msecs-stop)))
+                                       (stop (subed-subtitle-msecs-stop)))
       (setq subed-waveform--start
-           (max 0 (- start (* 1000 subed-loop-seconds-before))))
+                                               (floor (max 0 (- start 
subed-waveform-preview-msecs-before))))
       (setq subed-waveform--stop
-           (+ stop (* 1000 subed-loop-seconds-after)))
-      (let* ((width (string-pixel-width (make-string fill-column ?*)))
-            (height (save-excursion
-                      ;; don't count the current waveform towards the
-                      ;; line height
-                      (forward-line -1)
-                      (* 2 (line-pixel-height))))
-            (image (subed-waveform--from-file
-                    (or subed-mpv-media-file (error "No media file found"))
-                    (subed-waveform--msecs-to-ffmpeg subed-waveform--start)
-                    (subed-waveform--msecs-to-ffmpeg subed-waveform--stop)
-                    width
-                    height)))
-       (setq subed-waveform--svg (svg-create width height))
-       (svg-embed subed-waveform--svg image "image/png" t
-                  :x 0 :y 0
-                  :width "100%" :height "100%"
-                  :preserveAspectRatio "none")
-       (subed-waveform--update-bars (subed-subtitle-msecs-start))))))
+                                               (floor (+ stop 
subed-waveform-preview-msecs-after)))
+                       (when (> subed-waveform--stop subed-waveform--start)
+                               (let* ((width (string-pixel-width (make-string 
fill-column ?*)))
+                                                        (height (save-excursion
+                                                                               
                 ;; don't count the current waveform towards the
+                                                                               
                 ;; line height
+                                                                               
                 (forward-line -1)
+                                                                               
                 (* 2 (line-pixel-height))))
+                                                        (image 
(subed-waveform--from-file
+                                                                               
         (or subed-mpv-media-file (error "No media file found"))
+                                                                               
         (subed-waveform--msecs-to-ffmpeg subed-waveform--start)
+                                                                               
         (subed-waveform--msecs-to-ffmpeg subed-waveform--stop)
+                                                                               
         width
+                                                                               
         height)))
+                                       (setq subed-waveform--pixels-per-second 
(/ width (* 0.001 (- stop start))))
+                                       (setq subed-waveform--svg (svg-create 
width height))
+                                       (svg-embed subed-waveform--svg image 
"image/png" t
+                                                                               
 :x 0 :y 0
+                                                                               
 :width "100%" :height "100%"
+                                                                               
 :preserveAspectRatio "none")
+                                       (subed-waveform--update-bars 
(subed-subtitle-msecs-start)))))))
 
 (defun subed-waveform--move-bar (bar-type position)
   "Update `subed-waveform--svg', moving bar BAR-TYPE to POSITION.
@@ -292,19 +358,32 @@ the stop bar is too far to the right."
 Assume all necessary variables are already set.  This function is
 meant to be as fast as possible so that it can be called many
 times per second."
-  (subed-waveform--move-bar
-   :current
-   (subed-waveform--position-to-percent
-    subed-mpv-playback-position
-    subed-waveform--start
-    subed-waveform--stop))
+       (when subed-mpv-playback-position
+               (subed-waveform--move-bar
+                :current
+                (subed-waveform--position-to-percent
+                       subed-mpv-playback-position
+                       subed-waveform--start
+                       subed-waveform--stop)))
   (subed-waveform--update-overlay-svg))
 
-(defconst subed-waveform-map
-  (let ((subed-waveform-map (make-keymap)))
-    (define-key subed-waveform-map [mouse-1] #'subed-waveform-set-start)
-    (define-key subed-waveform-map [mouse-3] #'subed-waveform-set-stop)
-    subed-waveform-map)
+(defvar subed-waveform-svg-map
+  (let ((subed-waveform-svg-map (make-keymap)))
+    (define-key subed-waveform-svg-map [mouse-1] #'subed-waveform-set-start)
+               (define-key subed-waveform-svg-map [mouse-2] 
#'subed-waveform-jump-to-timestamp)
+    (define-key subed-waveform-svg-map [mouse-3] #'subed-waveform-set-stop)
+    (define-key subed-waveform-svg-map [down-mouse-3] #'ignore)
+               (define-key subed-waveform-svg-map [C-mouse-2] #'ignore)
+    (define-key subed-waveform-svg-map [S-mouse-3] #'ignore)
+    (define-key subed-waveform-svg-map [C-mouse-3] #'ignore)
+    (define-key subed-waveform-svg-map [S-down-mouse-1] #'ignore)
+    (define-key subed-waveform-svg-map [S-drag-mouse-1] 
#'subed-waveform-reduce-start-time)
+    (define-key subed-waveform-svg-map [S-down-mouse-3] #'ignore)
+    (define-key subed-waveform-svg-map [S-drag-mouse-3] 
#'subed-waveform-increase-stop-time)
+    (define-key subed-waveform-svg-map [S-C-down-mouse-2] 
#'subed-waveform-split)
+    (define-key subed-waveform-svg-map [S-mouse-1] #'ignore)
+    (define-key subed-waveform-svg-map [C-mouse-1] #'ignore)
+    subed-waveform-svg-map)
   "A keymap for clicking on the waveform.")
 
 (defun subed-waveform--update-overlay-svg ()
@@ -313,10 +392,10 @@ Assume `subed-waveform--svg' is already set."
   (overlay-put subed-waveform--image-overlay
               'before-string
               (propertize
-               " "
-               'display (svg-image subed-waveform--svg)
-               'pointer 'arrow
-               'keymap subed-waveform-map)))
+                                       " "
+                                       'display (svg-image subed-waveform--svg)
+                                       'pointer 'arrow
+                                       'keymap subed-waveform-svg-map)))
 
 (defun subed-waveform-put-svg (&rest _)
   "Put an overlay with the SVG in the current subtitle.
@@ -324,15 +403,19 @@ Set the relevant variables if necessary.
 This function ignores arguments and can be used in hooks."
   (interactive)
   (setq subed-waveform--pos (subed-jump-to-subtitle-text))
-  (if (overlayp subed-waveform--image-overlay)
-      (move-overlay subed-waveform--image-overlay
-                                                                               
subed-waveform--pos subed-waveform--pos)
-    (setq subed-waveform--image-overlay
-                                       (make-overlay subed-waveform--pos 
subed-waveform--pos))
-    (overlay-put subed-waveform--image-overlay
-                                                                'after-string
-                                                                "\n"))
-  (subed-waveform--set-svg))
+       (when subed-waveform--pos
+               (if (overlayp subed-waveform--image-overlay)
+                               (move-overlay subed-waveform--image-overlay
+                                                                               
        subed-waveform--pos subed-waveform--pos)
+                       (setq subed-waveform--image-overlay
+                                               (make-overlay 
subed-waveform--pos subed-waveform--pos))
+                       (overlay-put subed-waveform--image-overlay 
'subed-waveform t)
+                       (overlay-put subed-waveform--image-overlay
+                                                                        
'after-string
+                                                                        "\n"))
+               (subed-waveform--set-svg)))
+
+;;; Adjusting based on the mouse
 
 (defun subed-waveform--mouse-event-to-ms (event)
   "Return the millisecond position of EVENT."
@@ -340,9 +423,9 @@ This function ignores arguments and can be used in hooks."
          (width (car (elt (cadr event) 9))))
     (* subed-waveform-timestamp-resolution
        (round (+ (* (/ (* 1.0 x) width)
-                   (- subed-waveform--stop subed-waveform--start))
-                subed-waveform--start)
-             subed-waveform-timestamp-resolution))))
+                                                                               
(- subed-waveform--stop subed-waveform--start))
+                                                                
subed-waveform--start)
+                                                       
subed-waveform-timestamp-resolution))))
 
 (defun subed-waveform-set-start (event)
   "Set the start timestamp in the place clicked."
@@ -356,5 +439,93 @@ This function ignores arguments and can be used in hooks."
   (subed-set-subtitle-time-stop (subed-waveform--mouse-event-to-ms event))
   (subed-waveform--update-bars (subed-subtitle-msecs-start)))
 
+(defun subed-waveform-reduce-start-time (event)
+  "Make this subtitle start `subed-milliseconds-adjust' milliseconds earlier."
+  (interactive "e")
+  (save-excursion
+               (when subed-waveform--pixels-per-second
+           (let* ((x1 (car (elt (elt event 2) 2)))
+                                                (x2 (car (elt (elt event 1) 
2)))
+                                                (msecs
+                                                       (floor (* 1000 (/ (- x1 
x2)     ; pixels moved
+                                                                               
                                                
subed-waveform--pixels-per-second)))))
+                               (subed-adjust-subtitle-time-start msecs)))))
+
+(defun subed-waveform-increase-stop-time (event)
+  "Make this subtitle stop later.
+If called from a mouse drag EVENT, adjust it proportionally to
+what is displayed.  If not, adjust it
+by `subed-milliseconds-adjust' milliseconds."
+  (interactive "e")
+  (save-excursion
+    (when subed-waveform--pixels-per-second
+           (let* ((x1 (car (elt (elt event 2) 2)))
+                                                (x2 (car (elt (elt event 1) 
2)))
+                                                (msecs
+                                                       (floor (* 1000 (/ (- x1 
x2)     ; pixels moved
+                                                                               
                                                
subed-waveform--pixels-per-second)))))
+                               (subed-adjust-subtitle-time-stop msecs)))))
+
+(defun subed-waveform-split (event)
+  "Split the current subtitle.
+Use the selected timestamp as the start time of the next subtitle, leaving a 
gap of
+`subed-subtitle-spacing'."
+  (interactive "e")
+  (save-excursion
+    (let ((ms (subed-waveform--mouse-event-to-ms event)))
+      (subed-split-subtitle (- ms (subed-subtitle-msecs-start))))))
+
+;;; Sampling
+
+(defvar-local subed-waveform--sample-timer nil "Timer used for sampling.
+Resets MPV position when done.")
+
+(defun subed-waveform-jump-to-timestamp (event)
+  "Jump to the timestamp at EVENT and play a short sample.
+The `subed-waveform-sample-msecs' variable specifies the duration
+of the sample.  Jump to the specified position afterwards so that
+you can use it in `subed-split-subtitle' and other commands."
+  (interactive "e")
+  (let* ((ms (subed-waveform--mouse-event-to-ms event))
+         (ts (subed-msecs-to-timestamp ms)))
+    (subed-mpv-jump ms)
+    (message "%s" ts)
+    (if (> (or subed-waveform-sample-msecs 0) 0)
+        (subed-waveform-play-sample
+         ms
+         (min
+          (- subed-waveform--stop ms)
+          subed-waveform-sample-msecs))
+      (subed-mpv-jump ms))))
+
+(defun subed-waveform--restore-mpv-position (reset-msecs)
+  "Jump back to RESET-MSECS."
+  (subed-mpv-pause)
+  (subed-mpv-jump reset-msecs)
+  (when subed-waveform--enable-point-to-player-sync-after-sample
+    (subed-enable-sync-point-to-player t))
+  (when subed-waveform--enable-loop-over-current-subtitle-after-sample
+    (subed-enable-loop-over-current-subtitle t))
+  (setq subed-waveform--enable-loop-over-current-subtitle-after-sample nil
+        subed-waveform--enable-point-to-player-sync-after-sample nil))
+
+(defun subed-waveform-play-sample (msecs &optional duration-ms)
+  "Play starting at MSECS position for DURATION-MS seconds.
+If DURATION is unspecified, use `subed-waveform-sample-msecs.'"
+  (subed-mpv-jump msecs)
+  (subed-mpv-unpause)
+  (when (subed-loop-over-current-subtitle-p)
+    (setq subed-waveform--enable-loop-over-current-subtitle-after-sample t)
+    (subed-disable-loop-over-current-subtitle t))
+  (when (subed-sync-point-to-player-p)
+    (setq subed-waveform--enable-point-to-player-sync-after-sample t)
+    (subed-disable-sync-point-to-player t))
+  (if (timerp subed-waveform--sample-timer) (cancel-timer 
subed-waveform--sample-timer))
+  (setq subed-waveform--sample-timer
+        (run-at-time (/ (or duration-ms subed-waveform-sample-msecs) 1000.0) 
nil
+                     #'subed-waveform--restore-mpv-position
+                     msecs)))
+
+
 (provide 'subed-waveform)
 ;;; subed-waveform.el ends here
diff --git a/subed/subed.el b/subed/subed.el
index 0c1d8c06b8..5d76a03567 100644
--- a/subed/subed.el
+++ b/subed/subed.el
@@ -82,9 +82,6 @@
     (define-key subed-mode-map (kbd "C-c ]") 
#'subed-copy-player-pos-to-stop-time)
     (define-key subed-mode-map (kbd "C-c .") 
#'subed-toggle-sync-point-to-player)
     (define-key subed-mode-map (kbd "C-c ,") 
#'subed-toggle-sync-player-to-point)
-    (define-key subed-mode-map (kbd "C-c C-=") 
#'subed-waveform-volume-increase)
-    (define-key subed-mode-map (kbd "C-c C--") 
#'subed-waveform-volume-decrease)
-    (define-key subed-mode-map (kbd "C-c |") #'subed-waveform-put-svg)
     (define-key subed-mode-map (kbd "C-c C-t") (let ((html-tag-keymap 
(make-sparse-keymap)))
                                                                                
     (define-key html-tag-keymap (kbd "C-t") #'subed-insert-html-tag)
                                                                                
     (define-key html-tag-keymap (kbd "C-i") #'subed-insert-html-tag-italic)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]