Hello Emms people, While playing longer recordings I found out that emms seeking could be improved. So please find attached a patch that modifies emms-seek and emms-seek-to functions to accept timestamps in addition to seconds (as they do now). Timespec format follows ffmpeg (see ffmpeg-utils(5) and Time Duration there):
- Single number is interpreted as seconds to seek. This is equivalent to the current behavior. - Timestamp format is "hh:mm:ss" where hh part is optional. It is either relative (emms-seek) or absolute (emms-seek-to). Relative timestamp can be negative, e.g.: . "-1:14:22" means "seek 1 hour 14 minutes and 22 seconds backwards" . "23:12.5" means "seek 23 minutes and 12.5 seconds forwards" The implementation is lax: it does not do any error checking and relies on string-to-number to handle nonsensical inputs (in which case string-to-number returns zero). So one can specify meaningless timestamps like "1+:xz:-22" which is interpreted as "1:00:22" => 3622 seconds. I'm not sure if this is what we want, but OTOH I think we shouldn't be too strict either. What do you think, does this make sense? thanks, Petteri
>From cf1222e8c106272109a681fd51dea45f5e3a1fca Mon Sep 17 00:00:00 2001 From: Petteri Hintsanen <pette...@iki.fi> Date: Fri, 2 Sep 2022 16:48:59 +0300 Subject: [PATCH] dev --- emms.el | 53 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/emms.el b/emms.el index fccecb9..e6b7783 100644 --- a/emms.el +++ b/emms.el @@ -455,21 +455,50 @@ If player hasn't started, then start it now." (emms-player-pause) (emms-start))) -(defun emms-seek (seconds) - "Seek the current player SECONDS seconds. -This can be a floating point number for sub-second fractions. -It can also be negative to seek backwards." - (interactive "nSeconds to seek: ") +(defun emms-seek (duration) + "Seek the current player by DURATION from its current position. +DURATION can be: + +- A single number, in which case it is interpreted as seconds. + +- A string of form [-][HH:]MM:SS.m, where HH is hours, MM is + minutes, and SS is seconds. + +In both forms seconds can be a floating point number. A negative +value seeks backwards." + (interactive "sDuration to seek: ") (emms-ensure-player-playing-p) - (emms-player-seek seconds)) + (emms-player-seek (emms-timespec-to-secs duration))) -(defun emms-seek-to (seconds) - "Seek the current player to SECONDS seconds. -This can be a floating point number for sub-second fractions. -It can also be negative to seek backwards." - (interactive "nSeconds to seek to: ") +(defun emms-seek-to (timestamp) + "Seek the current player to TIMESTAMP. +TIMESTAMP can be: + +- A single number, in which case it is interpreted as seconds. + +- A string of form [HH:]MM:SS.m, where HH is hours, MM is + minutes, and SS is seconds. + +In both forms seconds can be a floating point number." + (interactive "sTimestamp to seek to: ") (emms-ensure-player-playing-p) - (emms-player-seek-to seconds)) + (emms-player-seek-to (emms-timespec-to-secs timestamp t))) + +(defun emms-timespec-to-secs (timespec &optional absolute) + "TODO: docstring" + (let ((tokens (split-string timespec ":"))) + (if (= (length tokens) 1) + ;; seconds only + (let ((secs (string-to-number (car tokens)))) + (if absolute (abs secs) secs)) + ;; HH:MM:SS + (let* ((sign (if (< (string-to-number (car tokens)) 0) -1 1)) + (revtokens (reverse tokens)) + (seconds (abs (string-to-number (or (pop revtokens) "0")))) + (minutes (abs (string-to-number (or (pop revtokens) "0")))) + (hours (abs (string-to-number (or (pop revtokens) "0")))) + (seekpos (* sign (+ (* 60 60 hours) (* 60 minutes) seconds)))) + (if absolute (abs seekpos) seekpos))))) (defun emms-seek-forward () "Seek ten seconds forward." -- 2.30.2