From 734c10ca9fd162b8e722301252fb1903bd90ac16 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Wed, 16 Nov 2022 15:08:52 +0800 Subject: bongo: subtitle display * bongo.el (durand-bongo-sub-tick, durand-bongo-sub-mode) (durand-bongo-sub-mode-map, durand-bongo-sub-stop) (durand-bongo-sub-prepare-file-buffer, durand-bongo-sub) (durand-bongo--mpv-socket-filter, bongo-sub-redisplay) (bongo-sub-status-string): It seems to be a working implementation of display of subtitles. But I still need to test more to see if it really works. --- bongo.el | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 11 deletions(-) diff --git a/bongo.el b/bongo.el index 902433f..a0a6753 100644 --- a/bongo.el +++ b/bongo.el @@ -772,7 +772,7 @@ will do the right renaming." (defun durand-bongo-sub-tick (player) "Tick when playing subtitles." - (if (or (null bongo-sub-buffer) + (if (or (null durand-bongo-sub-buffer) (not (bongo-player-running-p player)) (and (bongo-player-get player 'socket) (not (equal (process-status (bongo-player-get player 'socket)) @@ -798,6 +798,78 @@ will do the right renaming." ((and bongo-player (eq (car bongo-player) 'mpv)) (durand-bongo-sub-start-timer bongo-player))))) +(define-derived-mode durand-bongo-sub-mode special-mode "Bongo Sub" + "Major mode for displaying subtitles in accordance with Bongo." + (set 'buffer-undo-list t) + (set 'cursor-type nil)) + +(define-key durand-bongo-sub-mode-map (vector ?s) + #'durand-bongo-sub-stop) + +(defun durand-bongo-sub-stop () + "Stop everything related to displaying subtitles." + (interactive) + (durand-bongo-sub-stop-timer) + (with-bongo-playlist-buffer + (bongo-player-put bongo-player 'sub-time nil) + (cond + ((buffer-live-p + (bongo-player-get bongo-player 'sub-file-buffer nil)) + (kill-buffer + (bongo-player-get bongo-player 'sub-file-buffer nil)) + (bongo-player-put bongo-player 'sub-file-buffer nil))) + (cond + ((buffer-live-p durand-bongo-sub-buffer) + (kill-buffer durand-bongo-sub-buffer) + (setq durand-bongo-sub-buffer nil))))) + +(defun durand-bongo-sub-prepare-file-buffer () + "Prepare the subtitles file buffer for the currently playing song." + (let* ((file-name (or (bongo-player-get bongo-player 'file-name) + (user-error "No file found"))) + (file-name-se (file-name-sans-extension file-name)) + (sub-file-name (format "%s.srt" file-name-se)) + (sub-exists-p (file-exists-p sub-file-name)) + (sub-file-buffer + (bongo-player-get bongo-player 'sub-file-buffer))) + (cond + ((not sub-exists-p) + (user-error "No subtitles file found for the current song."))) + (cond + ((not (buffer-live-p sub-file-buffer)) + (setq sub-file-buffer (get-buffer-create " * Bongo Sub File*")) + (bongo-player-put bongo-player + 'sub-file-buffer sub-file-buffer))) + (with-current-buffer sub-file-buffer + ;; The first line is the current song's file name. + (goto-char (point-min)) + (cond + ((not (looking-at-p + (rx-to-string (list 'seq file-name 'eol) t))) + (insert file-name ?\n) + (insert-file-contents sub-file-name)))) + sub-file-buffer)) + +(defun durand-bongo-sub () + "Display subtitles in a separate buffer." + (setq durand-bongo-sub-buffer + (get-buffer-create durand-bongo-sub-buffer-name)) + (cond + ((null (get-buffer-window durand-bongo-sub-buffer)) + (let ((durand-window-max-height 0.01)) + (display-buffer + durand-bongo-sub-buffer + (list (list #'display-buffer-reuse-window + #'display-buffer-in-side-window) + (cons 'side 'bottom) + (cons 'window-height + #'durand-fit-window-to-buffer-with-max)))))) + (with-bongo-playlist-buffer (durand-bongo-sub-prepare-file-buffer)) + (set-buffer durand-bongo-sub-buffer) + (durand-bongo-sub-mode) + (bongo-sub-redisplay) + (durand-bongo-sub-start-timer-maybe)) + ;;;; My custom filter ;; To handle subtitle events @@ -821,10 +893,10 @@ PROCESS is the socket which returned the OUTPUT." ;; Use request-id to identify the type of response (pcase (bongo-alist-get parsed-response 'request_id) (`"sub-pos" (progn - (message "data = %S" (bongo-alist-get parsed-response 'data)) - ;; (durand-bongo-update-sub-time - ;; player - ;; (bongo-alist-get parsed-response 'data)) + ;; (message "data = %S" (bongo-alist-get parsed-response 'data)) + (durand-bongo-update-sub-time + player + (bongo-alist-get parsed-response 'data)) )) (`"time-pos" (progn (bongo-player-update-elapsed-time player @@ -876,11 +948,12 @@ is the value of PLAYER's `time-update-delay-after-seek' property." "Update the Bongo Subtitle buffer to reflect the current time." (interactive) (unless bongo-sub-redisplaying - (let ((bongo-sub-redisplaying t)) + (let ((bongo-sub-redisplaying t) + (sub (or (bongo-sub-status-string (window-width)) ""))) (let ((inhibit-read-only t)) - (set-buffer bongo-sub-buffer) + (set-buffer durand-bongo-sub-buffer) (delete-region (point-min) (point-max)) - (insert (bongo-sub-status-string (window-width))))))) + (insert sub))))) ;;;; Display string @@ -933,9 +1006,16 @@ TIME must be a list of two to four elements." (let ((fb (bongo-player-get bongo-player 'sub-file-buffer)) (time (bongo-player-get bongo-player 'sub-time)) found start start-sub end end-sub) - (setq time - (parse-time-string - (format-seconds "%.2h:%.2m:%.2s" time))) + (setq + time + (let ((fake-time + (parse-time-string + (format-seconds "%.2h:%.2m:%.2s" time)))) + (encode-time + (append + (mapcar (lambda (ele) (or ele 0)) + (durand-take 6 fake-time)) + (nthcdr 6 fake-time))))) (with-current-buffer fb (goto-char (point-min)) (save-match-data -- cgit v1.2.3-18-g5258