diff options
author | Sacha Chua <sacha@sachachua.com> | 2022-10-20 21:49:32 -0400 |
---|---|---|
committer | Sacha Chua <sacha@sachachua.com> | 2022-10-20 21:49:32 -0400 |
commit | 59de795fdcdd117e671b1513474f158a7e38c313 (patch) | |
tree | c3a9ae1a1e9233ed519e32b893cbef51fcf6b97a | |
parent | a8102ca8b13607b4e4eae95635e0d4ac578cf195 (diff) | |
download | emacsconf-el-59de795fdcdd117e671b1513474f158a7e38c313.tar.xz emacsconf-el-59de795fdcdd117e671b1513474f158a7e38c313.zip |
Work on watch pages on live.emacsconf.org
-rw-r--r-- | emacsconf-publish.el | 319 | ||||
-rw-r--r-- | emacsconf-schedule.el | 8 | ||||
-rw-r--r-- | emacsconf.el | 12 |
3 files changed, 221 insertions, 118 deletions
diff --git a/emacsconf-publish.el b/emacsconf-publish.el index 8d85b76..296c946 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -696,43 +696,43 @@ Entries are sorted chronologically, with different tracks interleaved." (defun emacsconf-publish-sched-directive (o) (format "[[!template id=sched%s%s]]" - (let ((result "") - (attrs (append - (list - :title (plist-get o :title) - :url (concat "/" (plist-get o :url)) - :speakers (plist-get o :speakers) - :q-and-a (plist-get o :q-and-a)) - (unless (eq emacsconf-publishing-phase 'program) - (list - :track (plist-get o :track) - :slug (plist-get o :slug) - :status (pcase (plist-get o :status) - ("CAPTIONED" "captioned") - ("PREREC_RECEIVED" "received") - ("DONE" "done") - ("STARTED" "now playing") - (_ nil)) - :time (plist-get o :time) - :startutc (format-time-string "%FT%T%z" (plist-get o :start-time) t) - :endutc (format-time-string "%FT%T%z" (plist-get o :end-time) t) - :start (format-time-string "%-l:%M" (plist-get o :start-time) emacsconf-timezone) - :end (format-time-string "%-l:%M" (plist-get o :end-time) emacsconf-timezone)))))) - (while attrs - (let ((field (pop attrs)) - (val (pop attrs))) - (when val - (setq result (concat result " " (substring (symbol-name field) 1) "=\"" val "\""))))) - result) - (if (eq emacsconf-publishing-phase 'resources) - (format" resources=\"\"\"\n%s\n\"\"\"" - (mapconcat (lambda (s) (concat "<li>" s "</li>")) - (emacsconf-link-file-formats-as-list - (append o - (list :base-url (format "%s%s/" emacsconf-media-base-url emacsconf-year))) - (append emacsconf-main-extensions '("--main.webm"))) - "")) - ""))) + (let ((result "") + (attrs (append + (list + :title (plist-get o :title) + :url (concat "/" (plist-get o :url)) + :speakers (plist-get o :speakers) + :q-and-a (plist-get o :q-and-a)) + (unless (eq emacsconf-publishing-phase 'program) + (list + :track (plist-get o :track) + :slug (plist-get o :slug) + :status (pcase (plist-get o :status) + ("CAPTIONED" "captioned") + ("PREREC_RECEIVED" "received") + ("DONE" "done") + ("STARTED" "now playing") + (_ nil)) + :time (plist-get o :time) + :startutc (format-time-string "%FT%T%z" (plist-get o :start-time) t) + :endutc (format-time-string "%FT%T%z" (plist-get o :end-time) t) + :start (format-time-string "%-l:%M" (plist-get o :start-time) emacsconf-timezone) + :end (format-time-string "%-l:%M" (plist-get o :end-time) emacsconf-timezone)))))) + (while attrs + (let ((field (pop attrs)) + (val (pop attrs))) + (when val + (setq result (concat result " " (substring (symbol-name field) 1) "=\"" val "\""))))) + result) + (if (eq emacsconf-publishing-phase 'resources) + (format" resources=\"\"\"\n%s\n\"\"\"" + (mapconcat (lambda (s) (concat "<li>" s "</li>")) + (emacsconf-link-file-formats-as-list + (append o + (list :base-url (format "%s%s/" emacsconf-media-base-url emacsconf-year))) + (append emacsconf-main-extensions '("--main.webm"))) + "")) + ""))) (defun emacsconf-format-main-schedule (info) (let* ((cancelled (seq-filter (lambda (o) (string= (plist-get o :status) "CANCELLED")) info))) @@ -1244,88 +1244,181 @@ Entries are sorted chronologically, with different tracks interleaved." (insert "</div>")))) by-day)))) +(defvar emacsconf-publish-watch-directory "/ssh:front:/var/www/live.emacsconf.org/") + +(defun emacsconf-publish-format-watch-index (info) + (concat + "<!-- Automatically generated by emacsconf-publish-watch-pages -->\n +<h1>Tracks</h1>" + "<table width=\"100%\"><tr><th>Watch page</th><th>IRC channel (libera.chat)</th><th>Alternative for streaming player</th><th>Low res</th></tr>\n" + (mapconcat (lambda (track) + (emacsconf-replace-plist-in-string + track + "<tr><td><a href=\"/${year}/watch/${id}\">${name}</a></td><td><a href=\"${webchat}\">${channel}</a></td><td><a href=\"${stream}\">${stream}</a></td><td><a href=\"${480p}\">${id}-480p.webm</a></tr>")) + emacsconf-tracks + "\n") + "</table>\n\n" + (with-temp-buffer + (svg-print (emacsconf-schedule-svg 800 300 info)) + (buffer-string)))) + +(defun emacsconf-publish-schedule-line (talk) + (setq talk (append talk (list + :startutc (format-time-string "%FT%T%z" (plist-get talk :start-time) t) + :endutc (format-time-string "%FT%T%z" (plist-get talk :end-time) t) + :start (format-time-string "%-l:%M" (plist-get talk :start-time) emacsconf-timezone) + :end (format-time-string "%-l:%M" (plist-get talk :end-time) emacsconf-timezone) + :base-url emacsconf-base-url))) + (emacsconf-replace-plist-in-string + (append talk (list + :start-info (emacsconf-surround "<span class=\"sched-start\">" (plist-get talk :start) "</span>" "") + :end-info(emacsconf-surround " - <span class=\"sched-end\">" (plist-get talk :end) "</span>" "") + :track-info (emacsconf-surround (format " <span class=\"sched-track %s\">" (or (plist-get talk :track) "")) (plist-get talk :track) "</span>" "") + :q-info (emacsconf-surround " <span class=\"sched-q-and-a\">Q&A: " (plist-get talk :q-and-a) "</span>; " "") + :slug-info (emacsconf-surround " <span class=\"sched-slug\">id:" (plist-get talk :slug) "</span>" "") + :speaker-info (emacsconf-surround " <div class=\"sched-speakers\">id:" (plist-get talk :speakers) "</div>" "") + :resources-info (emacsconf-surround "<ul class=\"resources\">id:" (plist-get talk :resources) "</ul>" ""))) + "<div data-start=\"${startutc}\" data-end=\"${endutc}\" class=\"sched-entry track-${track}\"> +<div class=\"sched-meta\"><span class=\"sched-time\">${start-info}${end-info}</span>${track-info}${q-info}${slug-info}</div> +<div class=\"sched-title\"><a href=\"${base-url}${url}\">${title}</a></div> +${speaker-info} +${resources-info} +</div> +")) + +(defun emacsconf-publish-schedule-short (info) + (mapconcat (lambda (o) + (emacsconf-replace-plist-in-string + (append o (list :base-url emacsconf-base-url)) + "<span><a href=\"${base-url}${url}\">${slug}</a> (<a class=\"pad-link\" href=\"${pad-url}\">pad</a>, ${qa-link})</span>")) + info " - ")) + +(defun emacsconf-publish-page-nav (nav &optional current sep) + (concat (if current (format "<a name=\"%s\"></a>" current) "") + (mapconcat (lambda (n) + (if (string= current (car n)) + (concat "<strong>" (cdr n) "</strong>") + (concat "<a href=\"#" (car n) "\">" (cdr n) "</a>"))) + nav (or sep " - ")))) + +(defun emacsconf-publish-format-watch-track (track info) + (let ((nav '(("watch" . "Watch") + ("links" . "Pad and Q&A links") + ("chat" . "Chat") + ("sched" . "Schedule"))) + (track-talks (seq-filter (lambda (o) (string= (plist-get o :track) + (plist-get track :name))) + info)) + ) + (emacsconf-replace-plist-in-string + (append + (list :links (concat + "<a href=\"#watch\">Watch</a> - <a href=\"#links\">Pad and Q&A links</a> - <a href=\"#chat\">Chat</a> - <a href=\"#sched\">View schedule</a> - \nStreams: " + ) + :sched (with-temp-buffer + (svg-print (emacsconf-schedule-svg 800 300 info)) + (buffer-string)) + :year emacsconf-year + :brief (emacsconf-publish-schedule-short + + track-talks) + :stream-nav (concat "Tracks: " (mapconcat (lambda (tr) + (if (string= (plist-get tr :name) (plist-get track :name)) + (format "<strong>%s</strong>" (plist-get track :name)) + (format "<a href=\"/%s/watch/%s/\">%s</a>" + emacsconf-year + (plist-get tr :id) + (plist-get tr :name)))) + emacsconf-tracks + " - ")) + :talks + (mapconcat (lambda (entry) (format "<h1>%s</h1>\n%s\n" (car entry) + (mapconcat #'emacsconf-publish-schedule-line (cdr entry) "\n"))) + (seq-group-by (lambda (o) + (format-time-string "%A, %b %-e, %Y" (plist-get o :start-time) emacsconf-timezone)) + track-talks))) + track) + (concat + "<!-- Automatically generated by emacsconf-publish-watch-pages --> +<!-- +[[!inline pages=\"internal(${year}/watch/announce)\" raw=\"yes\"]] +[[!meta title=\"${name} stream\"]] +[[!sidebar content=\"\"]] --> +<h1>EmacsConf ${year}: ${name} track</h1> +<hr size=\"1\"> +<div>" + (emacsconf-publish-page-nav nav "watch") + " | ${stream-nav}</div> + +<video controls><source src=\"${stream}\" type=\"video/webm\" /></video> +<div>Alternatively, load <a href=\"${stream}\">${stream}</a> or <a href=\"${480p}\"></a> (low-res) in a streaming media player such as MPV.</div> +<hr size=\"1\"><div>" (emacsconf-publish-page-nav nav "links") " | ${stream-nav}</div>" + "<div>${brief}</div> +<div class=\"pad-output\"></div> +<hr size=\"1\"><div>" (emacsconf-publish-page-nav nav "chat") " | ${stream-nav}</div>" +"<div>Chat: <a href=\"${webchat}\">${channel}</a> on libera.chat</div> + +<div class=\"chat-iframe\" data-track=\"${id}\"></div> +<iframe src=\"${webchat}\" height=\"600\" width=\"100%\"></iframe> +<hr size=\"1\"><div>" (emacsconf-publish-page-nav nav "sched") " | ${stream-nav}</div>" +" +<div>${sched}</div> +<div>${talks}</div> +")))) + (defun emacsconf-publish-watch-pages () "Update /year/watch pages." (interactive) - (emacsconf-publish-with-wiki-change - - (mapc (lambda (track) - (plist-put track :year emacsconf-year) - (plist-put track :stream (concat emacsconf-stream-base (plist-get track :id) ".webm")) - (plist-put track :480p (concat emacsconf-stream-base (plist-get track :id) "-480p.webm")) - (plist-put track :webchat-channels (concat "emacsconf,emacsconf-" (plist-get track :id))) - (plist-put track :webchat (concat emacsconf-chat-base "?join=" (plist-get track :webchat-channels))) - (plist-put track :channel (concat "#emacsconf-" (plist-get track :id)))) - emacsconf-tracks) - (let* ((info (sort (emacsconf-get-talk-info) #'emacsconf-sort-by-scheduled)) - (emacsconf-publishing-phase 'schedule) - (sched (format "[[!inline pages=\"internal(%s/schedule-image)\" raw=\"yes\"]]" emacsconf-year))) - (unless (file-directory-p (expand-file-name "watch" (expand-file-name emacsconf-year emacsconf-directory))) - (make-directory (expand-file-name "watch" (expand-file-name emacsconf-year emacsconf-directory)))) - (with-temp-file (expand-file-name "watch/info.md" (expand-file-name emacsconf-year emacsconf-directory)) - (insert - "<!-- Automatically generated by emacsconf-publish-watch-pages -->\n[[!sidebar content=\"\"]] -# Tracks\n\n" - "<table width=\"100%\"><tr><th>Watch page</th><th>IRC channel (libera.chat)</th><th>Alternative for streaming player</th><th>Low res</th></tr>\n" - (mapconcat (lambda (track) - (emacsconf-replace-plist-in-string - track - "<tr><td><a href=\"/${year}/watch/${id}\">${name}</a></td><td><a href=\"${webchat}\">${channel}</a></td><td><a href=\"${stream}\">${stream}</a></td><td><a href=\"${480p}\">${id}-480p.webm</a></tr>")) - emacsconf-tracks - "\n") - "</table>\n\n" sched)) - + (mapc (lambda (track) + (plist-put track :year emacsconf-year) + (plist-put track :stream (concat emacsconf-stream-base (plist-get track :id) ".webm")) + (plist-put track :480p (concat emacsconf-stream-base (plist-get track :id) "-480p.webm")) + (plist-put track :webchat-channels (concat "emacsconf,emacsconf-" (plist-get track :id))) + (plist-put track :webchat (concat emacsconf-chat-base "?join=" (plist-get track :webchat-channels))) + (plist-put track :channel (concat "#emacsconf-" (plist-get track :id)))) + emacsconf-tracks) + (let* ((info (sort (emacsconf-get-talk-info) #'emacsconf-sort-by-scheduled)) + (emacsconf-publishing-phase 'schedule) + (emacsconf-use-absolute-url t)) + ;; (when emacsconf-directory + ;; (emacsconf-publish-with-wiki-change + ;; (make-directory (expand-file-name "watch" (expand-file-name emacsconf-year emacsconf-directory)) t) + ;; (with-temp-file (expand-file-name "watch/info.md" (expand-file-name emacsconf-year emacsconf-directory)) + ;; (insert "[[!sidebar content=\"\"]]" (emacsconf-publish-format-watch-index info))) + ;; (mapc (lambda (track) + ;; (with-temp-file (expand-file-name (format "%s/watch/%s.md" emacsconf-year (plist-get track :id)) + ;; emacsconf-directory) + ;; (insert (emacsconf-publish-format-watch-track track info)))) + ;; emacsconf-tracks))) + ;; Update live.emacsconf.org + (when emacsconf-publish-watch-directory + (make-directory (expand-file-name "watch" (expand-file-name emacsconf-year emacsconf-publish-watch-directory)) t) + (with-temp-file (expand-file-name "watch/index.html" (expand-file-name emacsconf-year emacsconf-publish-watch-directory)) + (insert "<html><head><title>Watch EmacsConf</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"></link></head><body>" (emacsconf-publish-format-watch-index info) + +" <p> + Depending on which media player you use, you may enter the stream address + in a graphical user interface or provide it as an argument to the program + when launching it from the terminal. + </p> + <p> + Examples: + </p> +<pre>mpv https://live0.emacsconf.org:9001/emacsconf/gen.webm +vlc https://live0.emacsconf.org:9001/emacsconf/gen.webm +ffplay https://live0.emacsconf.org:9001/emacsconf/gen.webm +</pre>" + "</body></html>")) (mapc (lambda (track) - (with-temp-file (expand-file-name (format "%s/watch/%s.md" - emacsconf-year - (plist-get track :id)) - emacsconf-directory) + (make-directory (expand-file-name (format "%s/watch/%s" emacsconf-year (plist-get track :id)) emacsconf-publish-watch-directory) t) + (with-temp-file (expand-file-name (format "%s/watch/%s/index.html" emacsconf-year (plist-get track :id)) + emacsconf-publish-watch-directory) (insert (emacsconf-replace-plist-in-string - (append - (list :links (concat - "<a href=\"#watch\">Watch</a> - <a href=\"#chat\">Chat</a> - <a href=\"#sched\">View schedule</a> - \nStreams: " - (mapconcat (lambda (tr) - (if (string= (plist-get tr :name) (plist-get track :name)) - (format "**%s**" (plist-get track :name)) - (format "<a href=\"/%s/watch/%s/\">%s</a>" - emacsconf-year - (plist-get tr :id) - (plist-get tr :name)))) - emacsconf-tracks - " - ")) - :sched sched - :year emacsconf-year - :talks (mapconcat #'emacsconf-publish-sched-directive - (seq-filter (lambda (o) (string= (plist-get o :track) - (plist-get track :name))) - info) - "\n")) - track) - "<!-- Automatically generated by emacsconf-publish-watch-pages --> -[[!inline pages=\"internal(${year}/watch/announce)\" raw=\"yes\"]] -[[!meta title=\"${name} stream\"]] -[[!sidebar content=\"\"]] - -<a name=\"watch\"></a> -${links} -\n<video controls><source src=\"${stream}\" type=\"video/webm\" /></video> -Alternatively, load <${stream}> or <${480p}> (low-res) in a streaming media player such as MPV. - -<a name=\"chat\"></a> -${links} - -Chat: [${channel} on libera.chat](${webchat}) - -<div class=\"chat-iframe\" data-track=\"${id}\"></div> - -<a name=\"sched\"></a> -${links} - -${sched}\n - -${talks} -")))) + track + "<html><head><title>Watch EmacsConf ${name} track</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"></link></head><body>") + (emacsconf-publish-format-watch-track track info) + "</body></html>"))) emacsconf-tracks)))) (defvar emacsconf-publish-current-dir "/ssh:media:/var/www/media.emacsconf.org/2022/current" diff --git a/emacsconf-schedule.el b/emacsconf-schedule.el index 9b90faa..b8c3892 100644 --- a/emacsconf-schedule.el +++ b/emacsconf-schedule.el @@ -226,6 +226,7 @@ Each function should take the info and manipulate it as needed, returning the ne (emacsconf-filter-talks info))))) (defvar emacsconf-schedule-svg-modify-functions '(emacsconf-schedule-svg-color-by-track) "Functions to run to modify the display of each item.") +(defvar emacsconf-use-absolute-url nil "Non-nil means try to use absolute URLs.") (defun emacsconf-schedule-svg-track (svg base-x base-y width height start-time end-time info) (let ((scale (/ width (float-time (time-subtract end-time start-time))))) (mapc @@ -258,7 +259,12 @@ Each function should take the info and manipulate it as needed, returning the ne (parent (dom-node 'a (list - (cons 'href (concat "/" (plist-get o :url))) + (cons 'href + (concat + (if emacsconf-use-absolute-url + emacsconf-base-url + "/") + (plist-get o :url))) (cons 'title (plist-get o :title)) (cons 'data-slug (plist-get o :slug))) (dom-node 'title nil diff --git a/emacsconf.el b/emacsconf.el index 8183fc5..6d25045 100644 --- a/emacsconf.el +++ b/emacsconf.el @@ -75,7 +75,7 @@ :type 'file :group 'emacsconf) -(defvar emacsconf-stream-base "https://live0.emacsconf.org/") +(defvar emacsconf-stream-base "https://live0.emacsconf.org:9001/emacsconf/") (defvar emacsconf-chat-base "https://chat.emacsconf.org/") (defcustom emacsconf-download-directory "~/Downloads" @@ -422,14 +422,18 @@ (when track (plist-put o :watch-url (concat emacsconf-base-url emacsconf-year "/watch/" (plist-get track :id)))) (plist-put o :channel (plist-get track :channel)) + (plist-put o :webchat-url (concat emacsconf-chat-base "?join=emacsconf," (plist-get track :channel))) (cond ((string-match "live" (or (plist-get o :q-and-a) "")) (plist-put o :bbb-redirect (format "https://emacsconf.org/current/%s/room/" (plist-get o :slug))) - (plist-put o :qa-info (plist-get o :bbb-redirect))) + (plist-put o :qa-info (plist-get o :bbb-redirect)) + (plist-put o :qa-link (format "<a href=\"%s\">live</a>" (plist-get o :bbb-redirect)))) ((string-match "IRC" (or (plist-get o :q-and-a) "")) (plist-put o :qa-info (concat (emacsconf-surround "nick: " (plist-get o :irc) ", " "") - (plist-get o :channel)))) - (t (plist-put o :qa-info "none"))) + (plist-get o :channel))) + (plist-put o :qa-link (format "<a href=\"%s\">%s</a>" (plist-get o :webchat-url) (plist-get o :qa-info)))) + (t (plist-put o :qa-info "none") + (plist-put o :qa-link "none"))) (plist-put o :pad-url (format "https://pad.emacsconf.org/%s-%s" emacsconf-year (plist-get o :slug))) o)) |