1890_在WSL中使用emacs org-pomodoro的声音提示

全部学习汇总: editors_skills: emacs,vim还有VS Code等编辑器技巧 (gitee.com)

在WSL中使用emacs org-pomodoro的声音提示

Grey

尝试使用WSL播放wav文件

其实WSL我也用了很多年了,但是主要的功能还是拿来跑跑脚本。很多交互式的环境启动的速度以及响应速度在这个平台上都会好很多。从我使用org-mode做笔记开始,我用到了org-download的功能,当时尝试抄来了一个调用PowerShell来使用剪切板的方式。这让我想到了,或许很多其他的功能也可以由这个渠道打通。

WSL的短板

有些版本的Windows上已经可以运行原生的GUI了,有的也可以运行多媒体。但是对我来说,简单的编辑为主的操作基本上用不到GUI。不过,声音的播放可能是我很期待的一个功能。因为我使用org-pomodoro,而这个提示的方式会是声音。即使我之前通过远程桌面的形式能够使用,也解决不了声音提示问题。到头来,还存在在不同的界面中切换信息的困扰。

PowerShell的测试

1890_在WSL中使用emacs org-pomodoro的声音提示_第1张图片

在PowerShell的环境中做了一个测试,出现了一些错误的提示,但是的确是听到了声音的播放。

cmd的环境中再次测试,成功且没有什么异常的提示。之所以做这样的测试,我想到的可能是这个PowerShell解析器的显式调用问题。或许,在PowerShell的shell交互中,解析器其实是默认已经启动了的。我对这个环境了解不多,暂且还是邯郸学步,先测试到这里基本可以继续下一步了。

WSL中调用测试

/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -c "(New-Object Media.SoundPlayer \"D:\zhangguolei_home\.emacs.d\elpa\org-pomodoro-20190530.1445\resources\bell.wav\").PlaySync()"

测试一下,上面的命令是可以成功通过PowerShell来播放音频的。接下来,可以尝试看看是不是可以把这个功能整合到WSL的emacs中。看起来似乎是很简单的,只是临门一脚的事情了。

emacs配置整合

以上是emacs的插件org-pomodoro的一个配置方式,关于这个看起来还是得进一步做一个命令的封装。感觉,如果把上面的测试的功能封装成一个可以传递文件名称的接口,似乎实现的可能性就有了。

最初的尝试还是按照直接做org-pomodoro的配置来实现,但是我自己尝试的时候发现很困难。因为这里面内置的方法其实是成熟的播放工具。而我自己探索出来的方式最多还是一个命令封装。

在emacs中,我做了进一步的测试,确认了如下的调用方式是可以工作的。

(shell-command "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -c \"(New-Object Media.SoundPlayer \\\"D:/bell.wav\\\").PlaySync()\"")

有了这么一个前提,接下来的处理就有了进一步希望了。由于我自己lisp掌握十分有限,因此尝试理解这个封装配置处理起来还是有些困难。我做的尝试倒是看上去难点,实则是简单不少。我看了下这个插件,其实播放的就是几个wav文件,那么我找到这几个文件的播放位置其实就很容易做代码上的修改。

最初的测试,遇到了好几次找不到播放器因而卡死的状态。为此,我做了一个暴力修改。有一个原始的借口设计如下:

(defcustom org-pomodoro-audio-player (or (executable-find "aplay")
                                         (executable-find "afplay"))
  "Music player used to play sounds."
  :group 'org-pomodoro
  :type 'string)

从这个接口看,其实这个播放器找不到的报错就在于这里。我现在既然不依赖于编译器,那么直接让这个接口返回True就好了。因此,修改如下:

(defcustom org-pomodoro-audio-player t
  "Music player used to play sounds."
  :group 'org-pomodoro
  :type 'string)

继续分析,找到了原始设计中的wav文件播放的一个处理设计:

(defun org-pomodoro-play-sound (type)
  "Play an audio file specified by TYPE (:pomodoro, :short-break, :long-break)."
  (let ((sound (org-pomodoro-sound type))
        (args (org-pomodoro-sound-args type)))
    (cond ((and (fboundp 'sound-wav-play)
        org-pomodoro-play-sounds
        sound)
       (sound-wav-play sound))
      ((and org-pomodoro-audio-player
        org-pomodoro-play-sounds
        sound)
       (start-process-shell-command
        "org-pomodoro-audio-player" nil
        (mapconcat 'identity
               `(,org-pomodoro-audio-player
             ,@(delq nil (list args (shell-quote-argument (expand-file-name sound)))))
               " "))))))

看到这里,解决的方案就有了。我直接设计一个函数,在这里接管对wav文件的处理即可。为此,我先设计了我自己的文件播放接口。

(defun powershell-wav-player(wav-file)
  "to simplify the logic, use c:/Users/Public as temporary directoy, and move it into current directoy"
  (interactive)
  (let* ((powershell "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe")
         (command-option " -c ")
         (command-begin "\"(New-Object Media.SoundPlayer ")
         (wav-file-windows (replace-regexp-in-string "/home/grey" "D:/zhangguolei_home" wav-file))
         (command-end ")")
         (command-method ".PlaySync()\""))
    (message (concat powershell command-option command-begin "\"" wav-file-windows "\"" command-end command-method))
    (shell-command (concat powershell command-option command-begin "\"" wav-file-windows "\"" command-end command-method))))

之后,wav的接管其实很容易。我直接简化掉这一段程序的处理,上来就调用播放接口播放文件即可。

(defun org-pomodoro-play-sound (type)
  "Play an audio file specified by TYPE (:pomodoro, :short-break, :long-break)."
  (let ((sound (org-pomodoro-sound type))
        (args (org-pomodoro-sound-args type)))
    (powershell-wav-player sound)))

经过上面的修改,测试了一下在WSL的命令终端环境下org-pomodoro的声音功能已经实现。这样,在Windows环境下的更顺手工具算是已经打造出来了。过程有点粗糙,但是终究也是适合自己的一次打磨。

你可能感兴趣的:(emacs,编辑器)