My personal dotfiles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

spotify-controller.el 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. ;; spotify-controller.el --- Generic player controller interface for Spotify.el
  2. ;; Copyright (C) 2014-2016 Daniel Fernandes Martins
  3. ;; Code:
  4. (defmacro if-gnu-linux (then else)
  5. "Evaluates `then' form if Emacs is running in GNU/Linux, otherwise evaluates
  6. `else' form."
  7. `(if (eq system-type 'gnu/linux) ,then ,else))
  8. (defmacro when-gnu-linux (then)
  9. "Evaluates `then' form if Emacs is running in GNU/Linux."
  10. `(if-gnu-linux ,then nil))
  11. (defmacro if-darwin (then else)
  12. "Evaluates `then' form if Emacs is running in OS X, otherwise evaluates
  13. `else' form."
  14. `(if (eq system-type 'darwin) ,then ,else))
  15. (defmacro when-darwin (then)
  16. "Evaluates `then' form if Emacs is running in OS X."
  17. `(if-darwin ,then nil))
  18. (defcustom spotify-transport (if-gnu-linux 'dbus 'apple)
  19. "How the commands should be sent to Spotify process. Defaults for `dbus' for
  20. GNU/Linux, `apple' otherwise."
  21. :type '(choice (symbol :tag "AppleScript" apple)
  22. (symbol :tag "D-Bus" dbus)))
  23. ;; TODO: No modeline support for linux just yet
  24. (defcustom spotify-mode-line-refresh-interval (if-gnu-linux 0 1)
  25. "The interval, in seconds, that the mode line must be updated. Set to 0 to
  26. disable this feature."
  27. :type 'integer)
  28. (defcustom spotify-mode-line-truncate-length 15
  29. "The maximum number of characters to truncated fields in
  30. `spotify-mode-line-format'.")
  31. (defcustom spotify-mode-line-format "%at - %t [%l]"
  32. "Format used to display the current Spotify client player status. The
  33. following placeholders are supported:
  34. * %u - Track URI (i.e. spotify:track:<ID>)
  35. * %a - Artist name
  36. * %at - Artist name (truncated)
  37. * %t - Track name
  38. * %tt - Track name (truncated)
  39. * %n - Track #
  40. * %d - Track disc #
  41. * %s - Player state (i.e. playing, paused, stopped)
  42. * %l - Track duration, in minutes (i.e. 01:35)
  43. * %p - Player position in current track, in minutes (i.e. 01:35)
  44. ")
  45. (defvar spotify-timer nil)
  46. ;; simple facility to emulate multimethods
  47. (defun spotify-apply (suffix &rest args)
  48. (let ((func-name (format "spotify-%s-%s" spotify-transport suffix)))
  49. (apply (intern func-name) args)))
  50. (defun spotify-replace-mode-line-flags (metadata)
  51. ""
  52. (let ((mode-line spotify-mode-line-format)
  53. (fields (split-string metadata "\n"))
  54. (duration-format "%m:%02s"))
  55. (if (or (< (length fields) 8)
  56. (string= "stopped" (seventh fields)))
  57. (setq mode-line "")
  58. (progn
  59. (setq mode-line (replace-regexp-in-string "%u" (first fields) mode-line))
  60. (setq mode-line (replace-regexp-in-string "%at" (truncate-string-to-width (second fields) spotify-mode-line-truncate-length 0 nil "...") mode-line))
  61. (setq mode-line (replace-regexp-in-string "%a" (second fields) mode-line))
  62. (setq mode-line (replace-regexp-in-string "%tt" (truncate-string-to-width (third fields) spotify-mode-line-truncate-length 0 nil "...") mode-line))
  63. (setq mode-line (replace-regexp-in-string "%t" (third fields) mode-line))
  64. (setq mode-line (replace-regexp-in-string "%n" (fourth fields) mode-line))
  65. (setq mode-line (replace-regexp-in-string "%d" (fifth fields) mode-line))
  66. (setq mode-line (replace-regexp-in-string "%s" (seventh fields) mode-line))
  67. (setq mode-line (replace-regexp-in-string "%l" (format-seconds duration-format (/ (string-to-number (sixth fields)) 1000)) mode-line))
  68. (setq mode-line (replace-regexp-in-string "%p" (format-seconds duration-format (string-to-number (eighth fields))) mode-line))))
  69. (spotify-update-mode-line mode-line)))
  70. (defun start-mode-line-timer ()
  71. "Starts the timer that updates the mode line according to the Spotify
  72. player status."
  73. (stop-mode-line-timer)
  74. (when (> spotify-mode-line-refresh-interval 0)
  75. (let ((first-run (format "%d sec" spotify-mode-line-refresh-interval))
  76. (interval spotify-mode-line-refresh-interval))
  77. (setq spotify-timer
  78. (run-at-time first-run interval 'spotify-refresh-mode-line)))))
  79. (defun stop-mode-line-timer ()
  80. "Stops the timer that updates the mode line."
  81. (when (and (boundp 'spotify-timer) (timerp spotify-timer))
  82. (cancel-timer spotify-timer)
  83. (spotify-player-status)))
  84. (defun spotify-player-status ()
  85. "Updates the mode line to display the current Spotify player status."
  86. (interactive)
  87. (spotify-apply "player-status"))
  88. (defun spotify-refresh-mode-line (&rest args)
  89. "Starts the player status process in order to update the mode line."
  90. (spotify-apply "player-status"))
  91. (defun spotify-play-uri (uri)
  92. "Sends a `play' command to Spotify process passing the given URI."
  93. (interactive "SSpotify URI: ")
  94. (spotify-apply "player-play-track" uri nil))
  95. (defun spotify-play-track (track &optional context)
  96. "Sends a `play' command to Spotify process passing a context id."
  97. (interactive)
  98. (spotify-apply "player-play-track"
  99. (when track (spotify-get-item-uri track))
  100. (when context (spotify-get-item-uri context))))
  101. (defun spotify-toggle-play ()
  102. "Sends a `playpause' command to Spotify process."
  103. (interactive)
  104. (spotify-apply "player-toggle-play"))
  105. (defun spotify-play ()
  106. "Sends a `play' command to Spotify process."
  107. (interactive)
  108. (spotify-apply "player-play"))
  109. (defun spotify-next-track ()
  110. "Sends a `next track' command to Spotify process."
  111. (interactive)
  112. (spotify-apply "player-next-track"))
  113. (defun spotify-previous-track ()
  114. "Sends a `previous track' command to Spotify process."
  115. (interactive)
  116. (spotify-apply "player-previous-track"))
  117. (defun spotify-pause ()
  118. "Sends a `pause' command to Spotify process."
  119. (interactive)
  120. (spotify-apply "player-pause"))
  121. (defun spotify-toggle-repeat ()
  122. "Sends a command to Spotify process to toggle the repeating flag."
  123. (interactive)
  124. (spotify-apply "toggle-repeat"))
  125. (defun spotify-toggle-shuffle ()
  126. "Sends a command to Spotify process to toggle the shuffling flag."
  127. (interactive)
  128. (spotify-apply "toggle-shuffle"))
  129. (provide 'spotify-controller)