;;; eev-audiovideo.el -- elisp hyperlinks to audio and video files.
;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
;;
;; This file is part of GNU eev.
;;
;; GNU eev is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 20210618
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;;
;; (find-audiovideo-intro)
;;; Commentary:
;; This file implements links to audio or video files _at certain time
;; offsets_. Here are two examples, in a long syntax:
;;
;; (find-video "~/eev-videos/Punch_and_Judy_Mark_Poulton-K6LmZ0A1s9U.mp4")
;; (find-video "~/eev-videos/Punch_and_Judy_Mark_Poulton-K6LmZ0A1s9U.mp4" "1:17")
;;
;; There are also the usual shorter hyperlinks, like this,
;;
;; (find-punchandjudyvideo "1:04" "right position")
;;
;; and a very compact syntax, used by `eev-avadj-mode', in which `M-p'
;; plays the default audio or video file at the first time offset that
;; can the parsed in the current line (the "time from BOL"). See:
;;
;; (find-audiovideo-intro)
;; (find-audiovideo-intro "1. Time offsets")
;; (find-audiovideo-intro "4. Short hyperlinks to audio and video files")
;; (find-audiovideo-intro "4.3. A demo")
;; (find-audiovideo-intro "4.4. The default audio/video file")
;; (find-audiovideo-intro "4.4. The default audio/video file" "`M-p'")
;;
;; NOTE: I am not aware of other packages - for emacs or not - that
;; implement links that play audio or video files at given time
;; offsets... but in 2020jan03 a guy called stardiviner sent this
;; proposal to the Org mailing list:
;;
;; https://lists.gnu.org/archive/html/emacs-orgmode/2020-01/msg00007.html
;; Historical note:
;;
;; I wrote a first version of this in 2011 or 2012, and some time
;; later a friend - Rafael Duarte Pinheiro - helped me to create a way
;; to play my indexed audios in a browser. Here is an example:
;;
;; http://angg.twu.net/audios/2011dec13-ict.html
;;
;; I used these indexed audios to show what was happening in the
;; banana meetings of the Banana Institute of Science and Technology
;; of the banana campus in which I work, that is part of a banana
;; university in a banana republic.
;;
;; My tools for indexed audios later became one third of my "tools for
;; activists", that are documented here:
;;
;; http://angg.twu.net/ferramentas-para-ativistas.html#audios-introducao
;;
;; but everything there is in Portuguese.
;;
;; In 2014 I had a burn-out and stopped working on these tools for
;; activists.
;; «.ee-time-from-bol» (to "ee-time-from-bol")
;; «.ee-time-to-seconds» (to "ee-time-to-seconds")
;; «.mm:ss» (to "mm:ss")
;; «.youtube-time» (to "youtube-time")
;; «.ee-time-shift» (to "ee-time-shift")
;; «.eev-avadj-mode» (to "eev-avadj-mode")
;; «.find-mplayer» (to "find-mplayer")
;; «.find-termplayer» (to "find-termplayer")
;; «.find-mpv-video» (to "find-mpv-video")
;; «.find-mpv-audio» (to "find-mpv-audio")
;; «.code-brxxxs» (to "code-brxxxs")
;; «.aliases» (to "aliases")
;; «.video-tutorials» (to "video-tutorials")
(require 'eev-code)
(require 'eev-brxxx)
;; (find-efunction 'ee-stuff-around-point)
;; (find-elnode "Regexp Search")
;; (find-elnode "Regexp Backslash" "shy group")
;;
(defun ee-time-around-point ()
(let ((time (ee-no-properties (ee-stuff-around-point "0-9:"))))
(if (not (equal time ""))
time)))
;;; _ _ __ _ _
;;; | |_(_)_ __ ___ ___ / _|_ __ ___ _ __ ___ | |__ ___ | |
;;; | __| | '_ ` _ \ / _ \_____| |_| '__/ _ \| '_ ` _ \ _____| '_ \ / _ \| |
;;; | |_| | | | | | | __/_____| _| | | (_) | | | | | |_____| |_) | (_) | |
;;; \__|_|_| |_| |_|\___| |_| |_| \___/|_| |_| |_| |_.__/ \___/|_|
;;;
;; «ee-time-from-bol» (to ".ee-time-from-bol")
;; Old version:
;; (defvar ee-time-regexp "[0-9]?[0-9]:[0-9][0-9]\\(:[0-9][0-9]\\)?")
(defvar ee-time-regexp
"\\(?:\\([0-9]?[0-9]\\):\\)?\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)")
(defun ee-re-search-from (pos regexp &optional limit repeat)
(save-excursion
(if pos (goto-char pos))
(if (re-search-forward regexp limit t repeat)
(match-string-no-properties 0))))
;; Test: 98:76:54 3:21 (ee-time-from-bol)
;;
(defun ee-time-from-bol ()
"Try this: 98:76:54 3:21 (ee-time-from-bol)"
(ee-re-search-from (ee-bol) ee-time-regexp (ee-eol)))
;; Test: 98:76:54 3:21 (ee-time-from-bol-flash)
;;
(defun ee-time-from-bol-flash () (interactive)
"Try this: 98:76:54 3:21 (ee-time-from-bol-flash)"
(if (ee-time-from-bol)
(eeflash+ (match-beginning 0) (match-end 0) ee-highlight-spec))
(ee-time-from-bol))
;;; _ _ _ _
;;; | |_(_)_ __ ___ ___ | |_ ___ ___ ___ ___ ___ _ __ __| |___
;;; | __| | '_ ` _ \ / _ \_____| __/ _ \ _____/ __|/ _ \/ __/ _ \| '_ \ / _` / __|
;;; | |_| | | | | | | __/_____| || (_) |_____\__ \ __/ (_| (_) | | | | (_| \__ \
;;; \__|_|_| |_| |_|\___| \__\___/ |___/\___|\___\___/|_| |_|\__,_|___/
;;;
;; «ee-time-to-seconds» (to ".ee-time-to-seconds")
;; Tests:
;; (ee-seconds-to-time 5)
;; (ee-seconds-to-time 300)
;; (ee-time+ -20 "0:05")
;; Old notes:
;; (find-elnode "Time Parsing")
;; (find-elnode "Time Parsing" "Function: format-seconds")
;; (seconds-to-time 4000)
;; (date-to-time "2:30")
;; (float-time '(0 4000 0))
;; (format-seconds "%h:%m:%s" 4000)
;; (format-seconds "%h:%02m:%02s" 4000)
;; (ee-seconds-to-time 260)
;; (ee-seconds-to-time 4000)
;; (ee-time-to-seconds "4:20")
;; (ee-time-to-seconds "1:00:00")
;; (string-to-number "")
(defun ee-time-to-seconds (time)
(save-match-data
(if (string-match ee-time-regexp time)
(+ (* 3600 (string-to-number (or (match-string 1 time) "0")))
(* 60 (string-to-number (match-string 2 time)))
(string-to-number (match-string 3 time))))))
(defun ee-seconds-to-time (seconds)
(if (> 3600 seconds)
(format-seconds "%m:%02s" seconds)
(format-seconds "%h:%02m:%02s" seconds)))
;;;
;;; _ __ ___ _ __ ___ _ ___ ___
;;; | '_ ` _ \| '_ ` _ \(_) __/ __|
;;; | | | | | | | | | | |_\__ \__ \
;;; |_| |_| |_|_| |_| |_(_)___/___/
;;;
;; «mm:ss» (to ".mm:ss")
;; Convert between a number of seconds (a number)
;; and a "minutes:seconds" thing (a string).
;; TODO: convert all calls to `ee-secs-to-mm:ss' to `ee-seconds-to-time' and
;; all calls to `ee-mm:ss-to-secs' to `ee-time-to-seconds',
;; and declare this obsolete.
;;
(defun ee-secs-to-mm:ss (n)
"Force N - a number of seconds or an \"mm:ss\" string - to the mm:ss format"
(if (stringp n) n
(let* ((s (mod n 60))
(m (/ (- n s) 60)))
(format "%d:%02d" m s))))
(defun ee-mm:ss-to-secs (mm:ss)
"Force MM:SS - a string or a number of seconds - to a number of seconds"
(if (numberp mm:ss) mm:ss
(let* ((ms (mapcar 'string-to-number (split-string mm:ss ":"))))
(+ (* 60 (car ms)) (cadr ms)))))
;; «youtube-time» (to ".youtube-time")
;; Tests: (ee-time-to-youtube-time "")
;; (ee-time-to-youtube-time "!")
;; (ee-time-to-youtube-time "2")
;; (ee-time-to-youtube-time "23")
;; (ee-time-to-youtube-time "123")
;; (ee-time-to-youtube-time "1:23")
;; (ee-time-to-youtube-time "1:23:43")
;;
(defun ee-time-to-youtube-time (str)
"Convert strings like \"1:23\" to strings like \"#t=1m23s\".
Supports the input formats \"ss\", \"mm:ss\", and \"hh:mm:ss\".
If the input does not match any of these formats, return nil."
(save-match-data
(cond ((string-match "^\\([0-9]+\\)$" str)
(format "#t=%ss" (match-string 1 str)))
((string-match "^\\([0-9]+\\):\\([0-9][0-9]\\)$" str)
(format "#t=%sm%ss" (match-string 1 str) (match-string 2 str)))
((string-match "^\\([0-9]+\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" str)
(format "#t=%sh%sm%ss" (match-string 1 str) (match-string 2 str)
(match-string 2 str))))))
;;; _ _ _ _ __ _
;;; | |_(_)_ __ ___ ___ ___| |__ (_)/ _| |_
;;; | __| | '_ ` _ \ / _ \_____/ __| '_ \| | |_| __|
;;; | |_| | | | | | | __/_____\__ \ | | | | _| |_
;;; \__|_|_| |_| |_|\___| |___/_| |_|_|_| \__|
;;;
;; «ee-time-shift» (to ".ee-time-shift")
;; See: (find-audiovideo-intro "2. `eev-avadj-mode'")
;; Tests: (ee-time+ 40 "4:20")
;; (ee-time+ -1000 "4:20")
(defun ee-time+ (seconds time)
(save-match-data
(ee-seconds-to-time
(max 0 (+ seconds (ee-time-to-seconds time))))))
(defun ee-time-from-bol-shift (seconds)
(interactive "P")
(save-excursion
(let ((time (ee-time-from-bol)))
(if time
(replace-match (ee-time+ (or seconds 1) time) t t)
(error "No time (mm:ss or hh:mm:ss) in the current line")))))
(defun ee-time-from-bol-shift- (seconds)
(interactive "P")
(ee-time-from-bol-shift (- (or seconds 1))))
;;; _ _ _ _ __ _ _
;;; | | __ _ ___| |_ __ _ _ _ __| (_) ___ / /_ _(_) __| | ___ ___
;;; | |/ _` / __| __| / _` | | | |/ _` | |/ _ \ / /\ \ / / |/ _` |/ _ \/ _ \
;;; | | (_| \__ \ |_ | (_| | |_| | (_| | | (_) / / \ V /| | (_| | __/ (_) |
;;; |_|\__,_|___/\__| \__,_|\__,_|\__,_|_|\___/_/ \_/ |_|\__,_|\___|\___/
;;;
;; See: (find-audiovideo-intro "4.4. The default audio/video file")
;; (find-audiovideo-intro "2. `eev-avadj-mode'" "play the default")
(defvar ee-audiovideo-last nil
"See: (find-audiovideo-intro \"The current audio or video\")")
(defun ee-audiovideo-sexp (time)
(list ee-audiovideo-last time))
(defun ee-time-from-bol-rerun (&optional arg)
"Play the current audio or video starting at '(ee-time-from-bol)'.
With a prefix of 0 just display what would be done. See:
(find-audiovideo-intro \"time-from-bol\")
(find-audiovideo-intro \"ee-audiovideo-last\")"
(interactive "P")
(cond ((eq arg 0)
(message "-> %S" (ee-audiovideo-sexp (ee-time-from-bol-flash))))
(t (let ((sexp (ee-audiovideo-sexp (ee-time-from-bol))))
(eval sexp)
(message "%S" sexp)))))
;;; _ _ _
;;; __ ___ ____ _ __| |(_) _ __ ___ ___ __| | ___
;;; / _` \ \ / / _` |/ _` || |_____| '_ ` _ \ / _ \ / _` |/ _ \
;;; | (_| |\ V / (_| | (_| || |_____| | | | | | (_) | (_| | __/
;;; \__,_| \_/ \__,_|\__,_|/ | |_| |_| |_|\___/ \__,_|\___|
;;; |__/
;;
;; «eev-avadj-mode» (to ".eev-avadj-mode")
;; See: (find-audiovideo-intro "2. `eev-avadj-mode'")
;;
(setq eev-avadj-mode-map (make-sparse-keymap))
(define-key eev-avadj-mode-map "\M--" 'ee-time-from-bol-shift-)
(define-key eev-avadj-mode-map "\M-=" 'ee-time-from-bol-shift)
(define-key eev-avadj-mode-map "\M-+" 'ee-time-from-bol-shift)
(define-key eev-avadj-mode-map "\M-p" 'ee-time-from-bol-rerun)
(define-minor-mode eev-avadj-mode
"eev audio/video adjust mode: a mode for adjusting audio/video link lines.
See: (find-audiovideo-intro \"`eev-avadj-mode'\")"
:init-value nil
:global nil
:lighter " eev-avadj")
;; (eev-avadj-mode 0)
;; (eev-avadj-mode 1)
;; 1:15 foo
;;; _
;;; _ __ ___ _ __ | | __ _ _ _ ___ _ __
;;; | '_ ` _ \| '_ \| |/ _` | | | |/ _ \ '__|
;;; | | | | | | |_) | | (_| | |_| | __/ |
;;; |_| |_| |_| .__/|_|\__,_|\__, |\___|_|
;;; |_| |___/
;;
;; «find-mplayer» (to ".find-mplayer")
;; Play video files with mplayer.
;; Note that:
;; 1. mplayer is obsolete - see https://en.wikipedia.org/wiki/Mpv_(media_player)
;; 2. this should be called `find-mplayer-video' to follow the conventions on
;; hyphens in: (find-eevfile "eev-pdflike.el")
;; 3. this is very old code.
;;
(defun find-mplayer (fname &optional pos &rest rest)
"Open FNAME with mplayer, with a GUI (in fullscreen mode, for video files)."
(interactive "sFile name: ")
(find-bgprocess (ee-find-mplayer fname pos)))
(defvar ee-mplayer-options '("-fs" "-osdlevel" "2" "-zoom"))
(defun ee-mplayer-video-options () ee-mplayer-options)
(defun ee-find-mplayer (fname &optional pos &rest rest)
`("mplayer"
,fname
,@(if pos `("-ss" ,(ee-secs-to-mm:ss pos)))
,@(ee-mplayer-video-options)
))
(defun code-mplayer (c fname)
(eval (ee-read (ee-code-mplayer c fname))))
(defun find-code-mplayer (c fname)
(find-estring-elisp (ee-code-mplayer c fname)))
(defun ee-code-mplayer (c fname)
(ee-template0 "\
;; {(ee-S `(find-code-mplayer ,c ,fname))}
;;
(defun find-{c} (&optional time &rest rest)
(interactive (list (ee-time-around-point)))
(setq ee-audiovideo-last 'find-{c})
(if (eq time t)
\"Just setting the default video\"
(find-mplayer {(ee-S fname)} time)))
"))
;;; _ _
;;; | |_ ___ _ __ _ __ ___ _ __ | | __ _ _ _ ___ _ __
;;; | __/ _ \ '__| '_ ` _ \| '_ \| |/ _` | | | |/ _ \ '__|
;;; | || __/ | | | | | | | |_) | | (_| | |_| | __/ |
;;; \__\___|_| |_| |_| |_| .__/|_|\__,_|\__, |\___|_|
;;; |_| |___/
;;
;; «find-termplayer» (to ".find-termplayer")
;; Play audio files with mplayer (in an xterm).
;; Note that:
;; 1. mplayer is obsolete - see https://en.wikipedia.org/wiki/Mpv_(media_player)
;; 2. this should be called `find-mplayer-audio' to follow the conventions on
;; hyphens in: (find-eevfile "eev-pdflike.el")
;; 3. this is very old code.
;;
(defvar ee-termplayer-term-options '("xterm" "-geometry" "+200+100" "-e"))
(defvar ee-termplayer-options ())
(defun ee-mplayer-audio-options () ee-termplayer-options)
(defun ee-find-termplayer (fname &optional pos &rest rest)
`(,@ee-termplayer-term-options
"mplayer"
,fname
,@(if pos `("-ss" ,(ee-secs-to-mm:ss pos)))
,@(ee-mplayer-audio-options)
))
(defun find-termplayer (fname &optional pos &rest rest)
"Open FNAME with mplayer, without a GUI (in a terminal - for audio files)."
(interactive "sFile name: ")
(find-bgprocess (ee-find-termplayer fname pos)))
(defun code-termplayer (c fname)
(eval (ee-read (ee-code-termplayer c fname))))
(defun find-code-termplayer (c fname)
(find-estring-elisp (ee-code-termplayer c fname)))
(defun ee-code-termplayer (c fname)
(ee-template0 "\
;; {(ee-S `(find-code-termplayer ,c ,fname))}
;;
(defun find-{c} (&optional time &rest rest)
(interactive (list (ee-time-around-point)))
(setq ee-audiovideo-last 'find-{c})
(if (eq time t)
\"Just setting the default audio\"
(find-termplayer {(ee-S fname)} time)))
"))
;;; _ _
;;; _ __ ___ _ ____ __ __ _(_) __| | ___ ___
;;; | '_ ` _ \| '_ \ \ / /___\ \ / / |/ _` |/ _ \/ _ \
;;; | | | | | | |_) \ V /_____\ V /| | (_| | __/ (_) |
;;; |_| |_| |_| .__/ \_/ \_/ |_|\__,_|\___|\___/
;;; |_|
;;
;; «find-mpv-video» (to ".find-mpv-video")
;;
(defun find-mpv-video (fname &optional pos &rest rest)
"Open FNAME with mpv, with a GUI (in fullscreen mode, for video files)."
(interactive "sFile name: ")
(find-bgprocess (ee-find-mpv-video fname pos)))
(defvar ee-mpv-video-options '("--fs" "--osd-level=2"))
(defun ee-find-mpv-video (fname &optional pos &rest rest)
`("mpv"
,fname
,@(if pos (list (format "--start=%s" (ee-secs-to-mm:ss pos))))
,@ee-mpv-video-options
))
(defun code-mpv-video (c fname)
(eval (ee-read (ee-code-mpv-video c fname))))
(defun find-code-mpv-video (c fname)
(find-estring-elisp (ee-code-mpv-video c fname)))
(defun ee-code-mpv-video (c fname)
(ee-template0 "\
;; {(ee-S `(find-code-mpv-video ,c ,fname))}
;;
(defun find-{c} (&optional time &rest rest)
(interactive (list (ee-time-around-point)))
(setq ee-audiovideo-last 'find-{c})
(if (eq time t)
\"Just setting the default video\"
(find-mpv-video {(ee-S fname)} time)))
"))
;;; _ _
;;; _ __ ___ _ ____ __ __ _ _ _ __| (_) ___
;;; | '_ ` _ \| '_ \ \ / /____ / _` | | | |/ _` | |/ _ \
;;; | | | | | | |_) \ V /_____| (_| | |_| | (_| | | (_) |
;;; |_| |_| |_| .__/ \_/ \__,_|\__,_|\__,_|_|\___/
;;; |_|
;;
;; «find-mpv-audio» (to ".find-mpv-audio")
;; Play audio with mpv (running in an xterm).
;; This is immature code. My notes are here:
;; (find-es "mplayer" "mpv-audio")
;;
(defvar ee-mpv-term-options '("xterm" "-geometry" "+200+100" "-e"))
(defvar ee-mpv-audio-options '("--vid=no"))
(defun ee-find-mpv-audio (fname &optional pos &rest rest)
`(,@ee-mpv-term-options
"mpv"
,fname
;; ,@(if pos `("--start" ,(ee-secs-to-mm:ss pos)))
,@(if pos (list (format "--start=%s" (ee-secs-to-mm:ss pos))))
,@ee-mpv-audio-options
))
(defun find-mpv-audio (fname &optional pos &rest rest)
"Open FNAME with mpv, without a GUI (in a terminal - for audio files)."
(interactive "sFile name: ")
(find-bgprocess (ee-find-mpv-audio fname pos)))
(defun code-mpv-audio (c fname)
(eval (ee-read (ee-code-mpv-audio c fname))))
(defun find-code-mpv-audio (c fname)
(find-estring-elisp (ee-code-mpv-audio c fname)))
(defun ee-code-mpv-audio (c fname)
(ee-template0 "\
;; {(ee-S `(find-code-mpv-audio ,c ,fname))}
;;
(defun find-{c} (&optional time &rest rest)
(interactive (list (ee-time-around-point)))
(setq ee-audioaudio-last 'find-{c})
(if (eq time t)
\"Just setting the default audio\"
(find-mpv-audio {(ee-S fname)} time)))
"))
;;; _ _
;;; ___ ___ __| | ___ | |__ _ ____ ____ ____ _____
;;; / __/ _ \ / _` |/ _ \_____| '_ \| '__\ \/ /\ \/ /\ \/ / __|
;;; | (_| (_) | (_| | __/_____| |_) | | > < > < > <\__ \
;;; \___\___/ \__,_|\___| |_.__/|_| /_/\_\/_/\_\/_/\_\___/
;;;
;; «code-brxxxs» (to ".code-brxxxs")
;; See: (find-brxxx-intro "6. `code-brfile'")
;; (find-code-brfile 'find-audio :local 'braudiol :dired 'braudiod)
(code-brfile 'find-audio :local 'braudiol :dired 'braudiod)
;; (find-code-brfile 'find-video :local 'brvideol :dired 'brvideod)
(code-brfile 'find-video :local 'brvideol :dired 'brvideod)
;;; _ _
;;; __ _| (_) __ _ ___ ___ ___
;;; / _` | | |/ _` / __|/ _ \/ __|
;;; | (_| | | | (_| \__ \ __/\__ \
;;; \__,_|_|_|\__,_|___/\___||___/
;;;
;; «aliases» (to ".aliases")
(defalias 'find-video 'find-mpv-video)
(defalias 'code-video 'code-mpv-video)
(defalias 'find-code-video 'find-code-mpv-video)
(defalias 'find-audio 'find-mpv-audio)
(defalias 'code-audio 'code-mpv-audio)
(defalias 'find-code-audio 'find-code-mpv-audio)
;;; __ ___ _ _ _ _ _
;;; \ \ / (_) __| | ___ ___ | |_ _ _| |_ ___ _ __(_) __ _| |___
;;; \ \ / /| |/ _` |/ _ \/ _ \ | __| | | | __/ _ \| '__| |/ _` | / __|
;;; \ V / | | (_| | __/ (_) | | |_| |_| | || (_) | | | | (_| | \__ \
;;; \_/ |_|\__,_|\___|\___/ \__|\__,_|\__\___/|_| |_|\__,_|_|___/
;;;
;; «video-tutorials» (to ".video-tutorials")
;; See: (find-videos-intro "2. Short links to eev video tutorials")
;; Skel: (find-eevshortvideo-links "eev2019" "emacsconf2019" "86yiRG8YJD0")
;; Test: (find-eev2019video "0:00")
(defun find-eev2019video (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/emacsconf2019.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(interactive)
(find-eevvideo-links "eev2019" "emacsconf2019" "86yiRG8YJD0" time))
;; Skel: (find-eevshortvideo-links "eev2020" "emacsconf2020" "hOAqBc42Gg8")
;; Test: (find-eev2020video "0:00")
(defun find-eev2020video (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/emacsconf2020.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(interactive)
(find-eevvideo-links "eev2020" "emacsconf2020" "hOAqBc42Gg8" time))
;; Skel: (find-eevshortvideo-links "eevnav" "2020-list-packages-eev-nav" "kxBjiUo88_U")
;; Test: (find-eevnavvideo "0:00")
(defun find-eevnavvideo (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/2020-list-packages-eev-nav.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(interactive)
(find-eevvideo-links "eevnav" "2020-list-packages-eev-nav" "kxBjiUo88_U" time))
;; Skel: (find-eevshortvideo-links "eevtempl" "2020-some-template-based" "91-9YfRPsuk")
;; Test: (find-eevtemplvideo "0:00")
(defun find-eevtemplvideo (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/2020-some-template-based.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(interactive)
(find-eevvideo-links "eevtempl" "2020-some-template-based" "91-9YfRPsuk" time))
;; Skel: (find-eevshortvideo-links "eevfherel" "2020-find-here-links" "8jtiBlaDor4")
;; Test: (find-eevfherelvideo "0:00")
(defun find-eevfherelvideo (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/2020-find-here-links.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(find-eevvideo-links "eevfherel" "2020-find-here-links" "8jtiBlaDor4" time))
;; Skel: (find-eevshortvideo-links "eevtestbls" "2021-test-blocks" "fpsF_M55W4o")
;; Test: (find-eevtestblsvideo "0:00")
(defun find-eevtestblsvideo (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/2021-test-blocks.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(interactive)
(find-eevvideo-links "eevtestbls" "2021-test-blocks" "fpsF_M55W4o" time))
;; Skel: (find-eevshortvideo-links "eevvlinks" "2021-video-links")
;; Test: (find-eevvlinksvideo "0:00")
(defun find-eevvlinksvideo (&optional time &rest rest)
"Play one of the video tutorials of eev starting at TIME.
See: http://angg.twu.net/2021-video-links.html
for more info on this particular video,
and: (find-videos-intro \"2. Short links to eev video tutorials\")
or: http://angg.twu.net/eev-intros/find-videos-intro.html#2
for more info on these video tutorials."
(interactive)
(find-eevvideo-links "eevvlinks" "2021-video-links" "xQqWufQgzVY" time))
(provide 'eev-audiovideo)
;; Local Variables:
;; coding: utf-8-unix
;; ee-anchor-format: "«%s»"
;; no-byte-compile: t
;; End: