diff options
-rw-r--r-- | lisp/emms-streams.el | 704 |
1 files changed, 109 insertions, 595 deletions
diff --git a/lisp/emms-streams.el b/lisp/emms-streams.el index 3ebdcc3..f2c424d 100644 --- a/lisp/emms-streams.el +++ b/lisp/emms-streams.el @@ -1,24 +1,20 @@ -;; emms-streams.el -- interface to add and play streams +;; emms-streams.el -- A collection of online streaming audio -;; Copyright (C) 2004, 2005, 2006, 2007, 2008, -;; 2009 Free Software Foundation, Inc. +;; Copyright (C) 2019 Free Software Foundation, Inc. -;; Authors: Lucas Bonnet <lucas@rincevent.net> -;; Jose A Ortega Ruiz <jao@gnu.org> -;; Yoni Rabkin <yrk@gnu.org> -;; Michael Olson <mwolson@gnu.org> +;; Authors: Yoni Rabkin <yrk@gnu.org> ;; This file is part of EMMS. -;; EMMS 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. +;; EMMS 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. -;; EMMS 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. +;; EMMS 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 EMMS; if not, write to the Free Software Foundation, @@ -26,597 +22,115 @@ ;;; Commentary: -;; It is part of the EMMS package +;; 2019-11-05 - This is a complete re-write of the emms-streams.el, +;; using a different approach. -;; Heavily based on bmk-mgr.el by Jose A Ortega Ruiz <jao@gnu.org> -;; thanks to you ! +;; This includes the built-in list of streams which come with Emms by +;; default. Emms has no affiliation of any kind with the streaming +;; audio stations listed below, nor is this an endorsement of these +;; stations. Instead, this is a collection of stations submitted to +;; the project over the years by people who enjoy Emms. We hope you +;; will enjoy them too. ;;; Code: (require 'emms) -(require 'later-do) -(defgroup emms-stream nil - "*Add and play streams with EMMS." - :group 'emms) -(defcustom emms-stream-bookmarks-file (concat (file-name-as-directory emms-directory) "streams") - "*The file where you store your favorite emms streams." - :type 'file - :group 'emms-stream) - -(defcustom emms-stream-default-action "add" - "*The default action when you press RET in the EMMS Stream interface. -Can be either \"add\" or \"play\". The default is \"add\"." - :type 'string - :group 'emms-stream) - -(defface emms-stream-name-face '((t (:bold t :weight bold))) - "Face for stream names." - :group 'emms-stream) - -(defface emms-stream-url-face - '((((class color) (background dark)) - (:foreground "LightSteelBlue")) - (((class color) (background light)) - (:foreground "Blue"))) - "Face for stream URLs." - :group 'emms-stream) - -(defvar emms-stream-list nil - "The list that contains your current stream bookmarks.") - -(defvar emms-stream-buffer-name "*EMMS Streams*" - "The name of the buffer used by emms-stream interface.") - -(defvar emms-stream-play-hook nil - "*A hook run when you add or play an EMMS stream via the popup.") - -(defvar emms-stream-hook nil -"*A hook run when you call emms-streams or emms-stream-popup.") - -(defvar emms-stream-current-stream nil - "The stream currently being played. -Needed by the info method, as the track doesn't contain all the -needed info.") - -(defvar emms-stream-popup-old-conf nil - "Old window configuration.") - -(defvar emms-stream-last-stream nil - "The last stream added/played by EMMS.") - -(defvar emms-stream-playlist-buffer nil - "The EMMS playlist buffer associated with emms-streams.") - -(defcustom emms-stream-repeat-p nil - "*If non-nil, try to repeat a streamlist if it gets disconnected." - :set (function - (lambda (sym val) - (when (buffer-live-p emms-stream-playlist-buffer) - (with-current-buffer emms-stream-playlist-buffer - (setq emms-repeat-playlist val))) - (set sym val))) - :type 'boolean - :group 'emms-stream) - -;; Format: (("descriptive name" url feed-number type)) -;; -;; type could be either url, playlist, or lastfm. If url, then it -;; represents a direct IP, if streamlist it's a stream playlist, if -;; lastfm it's a lastfm station -(defvar emms-stream-default-list - '(("SomaFM: Beatblender" - "http://www.somafm.com/beatblender.pls" 1 streamlist) - ("SomaFM: Secret Agent" - "http://www.somafm.com/secretagent.pls" 1 streamlist) - ("SomaFM: Groove Salad" - "http://www.somafm.com/groovesalad.pls" 1 streamlist) - ("SomaFM: Drone Zone" - "http://www.somafm.com/dronezone.pls" 1 streamlist) - ("SomaFM: Tag's Trance" - "http://www.somafm.com/tagstrance.pls" 1 streamlist) - ("SomaFM: Indie Pop Rocks" - "http://www.somafm.com/indiepop.pls" 1 streamlist) - ("SomaFM: Doomed" - "http://www.somafm.com/doomed.pls" 1 streamlist) - ("P H I L O S O M A T I K A - Progressive Psytrance" - "http://listen.radionomy.com:80/-PHILOSOMATIKAPROGRESSIVE-" 1 url) - ("P H I L O S O M A T I K A - Psytrance" - "http://listen.radionomy.com:80/-PHILOSOMATIKA-" 1 url) - ("Drum and Bass Radio, BassDrive" - "http://www.bassdrive.com/BassDrive.m3u" 1 streamlist) - ("WCPE, Classical Music" - "http://www.ibiblio.org/wcpe/wcpe.pls" 1 streamlist) - ("Kohina - Old school game and demo music" - "http://stream.nute.net/kohina/stream.ogg.m3u" 1 streamlist) - ("Nectarine, Demoscene Radio, DE Continuum's relay 192 mp3" - "http://privat.is-by.us:8000/necta192.mp3.m3u" 1 streamlist) - ("Nectarine, Demoscene Radio, DE stream (High Bitrate)" - "http://nectarine.from-de.com/necta192.m3u" 1 streamlist) - ("Nectarine, Demoscene Radio, FR stream (High Bitrate)" - "http://necta-relay.mnus.de:8000/necta192.mp3.m3u" 1 streamlist) - ("Nectarine, Demoscene Radio, Norwegian stream" - "http://pmaster.no:9000/necta.m3u" 1 streamlist) - ("Nectarine, Demoscene Radio, UK stream (High Bitrate)" - "http://necta.jansenit.com:8000/necta192.mp3.m3u" 1 streamlist) - ("idobi Radio" - "http://www.idobi.com/radio/iradio.pls" 1 streamlist) - ("radio.wazee - Modern Alternative Rock" - "http://www.wazee.org/128.pls" 1 streamlist) - ("WFMU, Freeform radio" - "http://www.wfmu.org/wfmu.pls" 1 streamlist) - ("WBCR-LP - Berkshire Community Radio" - "http://nyc01.egihosting.com:6232/listen.pls" 1 streamlist) - ("Rinse FM - London and Worldwide" - "http://streamer.dgen.net:8000/rinseradio" 1 streamlist))) - -(defvar emms-stream-mode-map - (let ((map (make-keymap))) - (suppress-keymap map) - (define-key map (kbd "C-a") 'beginning-of-line) - (define-key map (kbd "C-e") 'end-of-line) - (define-key map (kbd "C-k") 'emms-stream-kill-bookmark) - (define-key map (kbd "C-y") 'emms-stream-yank-bookmark) - (define-key map (kbd "C-n") 'emms-stream-next-line) - (define-key map (kbd "C-p") 'emms-stream-previous-line) - (define-key map (kbd "Q") 'emms-stream-quit) - (define-key map (kbd "a") 'emms-stream-add-bookmark) - (define-key map (kbd "d") 'emms-stream-delete-bookmark) - (define-key map (kbd "e") 'emms-stream-edit-bookmark) - (define-key map (kbd "h") 'describe-mode) - (define-key map (kbd "n") 'emms-stream-next-line) - (define-key map (kbd "p") 'emms-stream-previous-line) - (define-key map (kbd "q") 'emms-stream-quit) - (define-key map (kbd "s") 'emms-stream-save-bookmarks-file) - (define-key map (kbd "t") 'emms-stream-toggle-default-action) -;; (define-key map (kbd "u") 'emms-stream-move-bookmark-up) - (define-key map (kbd "i") 'emms-stream-info-bookmark) - (define-key map (kbd "<up>") 'emms-stream-previous-line) - (define-key map (kbd "<down>") 'emms-stream-next-line) - (define-key map (kbd "<left>") 'beginning-of-line) - (define-key map (kbd "<right>") 'end-of-line) - (define-key map (kbd "RET") 'emms-stream-play) - map) - "Keymap for `emms-stream-menu'.") - -;;;###autoload -(defun emms-streams () - "Opens the EMMS Streams interface." - (interactive) - (kill-buffer (get-buffer-create emms-stream-buffer-name)) - (set-buffer (get-buffer-create emms-stream-buffer-name)) - (erase-buffer) - (when (string= emms-stream-default-action "play") - (emms-stream-create-playlist)) - (emms-stream-mode) - (switch-to-buffer emms-stream-buffer-name)) - -(defun emms-stream-mode () - "Major mode for the EMMS Streams interface. - -\\{emms-stream-mode-map}" - (kill-all-local-variables) - (buffer-disable-undo) - (setq major-mode 'emms-stream-mode) - (setq mode-name "EMMS Streams") - (use-local-map emms-stream-mode-map) - (emms-stream-init) - (set (make-local-variable 'truncate-lines) t) - (set (make-local-variable 'auto-hscroll-mode) t) - (set (make-local-variable 'kill-whole-line) t) - (set (make-local-variable 'next-line-add-newlines) nil) - (goto-char 1) - (emms-stream-display) - (read-only-mode 1) - (run-hooks 'emms-stream-hook) - (set-buffer-modified-p nil) - (message "EMMS Stream Menu")) - -(defun emms-stream-create-playlist () - "Create a new EMMS playlist and associate it with emms-streams. -This is used when `emms-stream-default-action' is \"play\"." - (save-excursion - (setq emms-stream-playlist-buffer - (emms-playlist-set-playlist-buffer (emms-playlist-new))) - (with-current-buffer emms-stream-playlist-buffer - ;; if emms-stream-repeat-p is non-nil, make sure that we - ;; continue to play the station, even if briefly disconnected - (set (make-local-variable 'emms-repeat-playlist) - emms-stream-repeat-p)))) - -(defun emms-stream-kill-playlist () - "Delete the EMMS playlist associated with emms-streams, if one exists." - (when (buffer-live-p emms-stream-playlist-buffer) - (save-excursion - (if (eq emms-stream-playlist-buffer emms-playlist-buffer) - (emms-playlist-current-kill) - (kill-buffer emms-stream-playlist-buffer))) - (setq emms-stream-playlist-buffer nil))) - -(defun emms-stream-popup-revert () - "Revert to the window-configuration from before if there is one, -otherwise just remove the special bindings from the stream menu." - (interactive) - (remove-hook 'emms-pbi-manually-change-song-hook 'emms-pbi-popup-revert) - (let ((streambuffer (get-buffer emms-stream-buffer-name))) - (when streambuffer - (with-current-buffer streambuffer - (local-unset-key (kbd "TAB"))))) - (when emms-stream-popup-old-conf - (set-window-configuration emms-stream-popup-old-conf)) - (remove-hook 'emms-stream-play-hook 'emms-stream-popup-revert) - (remove-hook 'emms-stream-quit-hook 'emms-stream-popup-revert)) - -(defun emms-stream-popup (&optional popup-height) - "Pops up the stream Menu, for the new stream selection. - -POPUP-HEIGHT is the height of the new frame, defaulting to -`emms-popup-default-height'." - (interactive) - (setq popup-height (or popup-height (/ (window-height) 2))) - ;; Split the current screen, and make the stream menu popup - (let ((new-window-height (- (window-height) popup-height))) - (if (not (> new-window-height 0)) - (error "Current window too small to popup menu!")) - ;; Save the current window-configuration - (setq emms-stream-popup-old-conf (current-window-configuration)) - ;; Split and select the menu - (let ((buffer-down - (split-window-vertically new-window-height))) - (select-window buffer-down)) - - (kill-buffer (get-buffer-create emms-stream-buffer-name)) - (switch-to-buffer (get-buffer-create emms-stream-buffer-name)) - (erase-buffer) - (emms-stream-mode) - - (add-hook 'emms-stream-play-hook 'emms-stream-popup-revert) - (add-hook 'emms-stream-quit-hook 'emms-stream-popup-revert) - (local-set-key (kbd "TAB") 'emms-stream-popup-revert) - (local-set-key (kbd "RET") 'emms-stream-play) - ;; (local-set-key (kbd "q") 'delete-window) - ;; Also, forget about the whole thing if the user does something - ;; to the window-configuration - ;; (add-hook 'window-configuration-change-hook 'emms-stream-popup-forget-conf))) - )) - -(defun emms-stream-init () - (setq emms-stream-list (emms-stream-read-file emms-stream-bookmarks-file))) - -(defun emms-stream-read-file (file) - "Returns a sexp." - (let ((file (expand-file-name file))) - (if (file-readable-p file) - (with-temp-buffer - (emms-insert-file-contents file) - (goto-char (point-min)) - (read (current-buffer))) - emms-stream-default-list))) - -(defun emms-stream-save-bookmarks-file () - (interactive) - (save-excursion - (let ((buffer (find-file-noselect emms-stream-bookmarks-file))) - (set-buffer buffer) - (erase-buffer) - (insert "(") - (let ((firstp t)) - (dolist (stream emms-stream-list) - (if (not firstp) - (insert "\n ") - (setq firstp nil)) - ;; make sure type identifier is a symbol, not a string - (when (stringp (nth 3 stream)) - (setq stream (copy-alist stream)) - (setcar (nthcdr 3 stream) (intern (nth 3 stream)))) - (prin1 stream buffer))) - (insert ")\n") - (save-buffer) - (kill-buffer buffer))) - (set-buffer-modified-p nil)) - -(defun emms-stream-display-line (line) - (insert (emms-stream-name line)) - (add-text-properties (point-at-bol) (point-at-eol) - '(face emms-stream-name-face)) - (add-text-properties (point-at-bol) (point-at-eol) `(emms-stream ,line)) - (insert "\n ") - (insert (emms-stream-url line)) - (add-text-properties (point-at-bol) (point-at-eol) - '(face emms-stream-url-face)) - (insert "\n")) - -(defun emms-stream-display () - "Displays the bookmark list in the current buffer, in a human - readable way." - (mapc 'emms-stream-display-line emms-stream-list) - (goto-char (point-min))) - -;; Helper functions -(defun emms-stream-take (n list) - "Takes N elements from LIST." - (let ((idx 0) - (res '())) - (while (< idx n) - (setq res (append res (list (nth idx list)))) - (setq idx (+ idx 1))) - res)) - -(defun emms-stream-insert-at (n elt list) - "Inserts the element ELT in LIST, *before* position N. -Positions are counted starting with 0." - (let* ((n-1 (- n 1)) - (before (emms-stream-take n-1 list)) - (after (last list (- (length list) n-1)))) - (append before (list elt) after))) - -(defun emms-stream-insert-several-at (n new-list list) - "Inserts the list NEW-LIST in LIST, *before* position N. -Positions are counted starting with 0." - (let* ((n-1 (- n 1)) - (before (emms-stream-take n-1 list)) - (after (last list (- (length list) n-1)))) - (append before new-list after))) - -(defun emms-stream-look-behind () - "Return non-nil if the position behind the point is an emms-stream." - (and (not (bobp)) - (get-text-property (1- (point)) 'emms-stream))) - -(defun emms-stream-back-to-stream () - "If we are not on a stream, move backwards to the nearest one." - (unless (get-text-property (point) 'emms-stream) - (unless (emms-stream-look-behind) - (goto-char (or (previous-single-property-change (point) 'emms-stream) - (point-min)))) - (goto-char (or (previous-single-property-change (point) 'emms-stream) - (point-min))))) - -(defun emms-stream-get-bookmark-at-point () - "Returns the bookmark under point." - (emms-stream-back-to-stream) - (get-text-property (point) 'emms-stream)) - -(defun emms-stream-redisplay () - (let ((inhibit-read-only t)) - (erase-buffer) - (goto-char (point-min)) - (emms-stream-display))) - -(defun emms-stream-determine-fd (name) - "Return a feed descriptor, given NAME. -This is the count of the times NAME appears in the bookmark list, -plus one." - (let ((count 1)) - (dolist (feed emms-stream-list) - (when (string= (emms-stream-name feed) name) - (setq count (1+ count)))) - count)) - -(defun emms-stream-add-bookmark (name url fd type) - "Creates a new bookmark, and inserts it at point position. - -Don't forget to run `emms-stream-save-bookmarks-file' after !" - (interactive - (list - (read-string "Name of the bookmark: ") - (read-string "URL: ") - nil - (emms-completing-read - "Type (url, streamlist, or lastfm): " - (mapcar #'list '("url" "streamlist" "lastfm"))))) - (unless fd (setq fd (emms-stream-determine-fd name))) - (when (stringp type) (setq type (intern type))) - (let* ((line (emms-line-number-at-pos (point))) - (index (+ (/ line 2) 1))) - (setq emms-stream-list (emms-stream-insert-at index (list name url fd type) - emms-stream-list)) - (emms-stream-redisplay) - (goto-char (point-min)) - (forward-line (1- line)))) - -(defun emms-stream-delete-bookmark () - "Deletes the bookmark under the point. - -Don't forget to save your modifications !" - (interactive) - (let ((line (emms-line-number-at-pos (point)))) - (setq emms-stream-list - (delete (emms-stream-get-bookmark-at-point) emms-stream-list)) - (emms-stream-redisplay) - (goto-char (point-min)) - (forward-line (1- line)))) - -(defun emms-stream-edit-bookmark () - "Change the information of current bookmark." - (interactive) - (let* ((bookmark (emms-stream-get-bookmark-at-point)) - (name (read-from-minibuffer "Description: " - (emms-stream-name bookmark))) - (url (read-from-minibuffer "URL: " - (emms-stream-url bookmark))) - (fd (read-from-minibuffer "Feed Descriptor: " - (int-to-string (emms-stream-fd bookmark)))) - (type (read-from-minibuffer "Type (url, streamlist, or lastfm): " - (format "%s" (emms-stream-type bookmark))))) - (emms-stream-delete-bookmark) - (emms-stream-add-bookmark name url (string-to-number fd) type))) - -(defun emms-stream-name (el) - (car el)) -(defun emms-stream-url (el) - (cadr el)) -(defun emms-stream-fd (el) - (car (cddr el))) -(defun emms-stream-type (el) - (cadr (cddr el))) - -(defun emms-stream-play () - (interactive) - (let* ((line (or (get-text-property (point) 'emms-stream) - (progn - (goto-char (or (previous-single-property-change - (point) 'emms-stream) - (point-min))) - (goto-char (or (previous-single-property-change - (point) 'emms-stream) - (point-min))) - (get-text-property (point) 'emms-stream)) - (error "No stream found at point"))) - (name (emms-stream-name line)) - (url (emms-stream-url line)) - (fd (emms-stream-fd line)) - (type (emms-stream-type line)) - (player (read (concat "emms-" emms-stream-default-action "-" - (format "%s" type))))) - (setq emms-stream-last-stream line) -;; (funcall emms-stream-default-action url) - (funcall player url) - (if (string= emms-stream-default-action "add") - (message "URL added to playlist"))) - (later-do 'emms-mode-line-alter) - (run-hooks 'emms-stream-play-hook)) - -(defun emms-stream-info-bookmark () - "Return the station and track information for the streaming audio station under point." - (interactive) - (if (fboundp 'emms-stream-info-message) - (let* ((line (get-text-property (point) 'emms-stream)) - (url (emms-stream-url line))) - (emms-stream-info-message url)) - (message "Streaming media info not available."))) - -;; Killing and yanking -(defvar emms-stream-killed-streams () - "Bookmarks that have been killed.") - -(defun emms-stream-kill-bookmark () - "Kill the current bookmark." - (interactive) - (let ((stream (emms-stream-get-bookmark-at-point))) - (setq emms-stream-list (delete stream emms-stream-list) - emms-stream-killed-streams (cons stream emms-stream-killed-streams))) - (let ((inhibit-read-only t)) - (kill-line 2))) - -(defun emms-stream-yank-bookmark () - "Yank bookmark into the streams buffer." - (interactive) - (emms-stream-back-to-stream) - (let ((inhibit-read-only t) - (streams nil)) - ;; get all valid streams - (save-restriction - (narrow-to-region (point) (point)) - (yank) - (goto-char (point-min)) - (while (and (< (point) (point-max)) - (car emms-stream-killed-streams) - (looking-at "^\\(.+\\)\n \\(.+\\)\n")) - (setq streams (cons (car emms-stream-killed-streams) streams) - emms-stream-killed-streams (cdr emms-stream-killed-streams)) - (goto-char (match-end 0))) - (delete-region (point-min) (point-max))) - ;; insert streams into list - (if streams - (let* ((line (emms-line-number-at-pos (point))) - (index (+ (/ line 2) 1))) - (setq emms-stream-list (emms-stream-insert-several-at - index streams emms-stream-list)) - (setq line (+ line (* (length streams) 2))) - (emms-stream-redisplay) - (goto-char (point-min)) - (forward-line (1- line))) - (message "Not yanking anything")))) - -;; Navigation -(defun emms-stream-next-line () - (interactive) - (when (get-text-property (point) 'emms-stream) - (goto-char (or (next-single-property-change (point) 'emms-stream) - (point-max)))) - (goto-char (or (next-single-property-change (point) 'emms-stream) - (point-max))) - (forward-line 0)) - -(defun emms-stream-previous-line () - (interactive) - (emms-stream-back-to-stream) - (goto-char (or (previous-single-property-change (point) 'emms-stream) - (point-min))) - (goto-char (or (previous-single-property-change (point) 'emms-stream) - (point-min))) - (forward-line 0)) - -(defun emms-stream-quit () +;;; ------------------------------------------------------------------ +;;; definitions +;;; ------------------------------------------------------------------ + +(defvar emms-streams-buffer-name "Emms Streams" + "Name for creating a streams buffer.") + +(defvar emms-streams-built-in-disclaimer + ";; This includes the built-in list of streams which come with Emms by +;; default. Emms has no affiliation of any kind with the streaming +;; audio stations listed below, nor is this an endorsement of these +;; stations. Instead, this is a collection of stations submitted to +;; the project over the years by people who enjoy Emms. We hope you +;; will enjoy them too." + "Explaining the relationship between Emms and these streams.") + +(defvar emms-streams-built-in-list + '((*track* (type . streamlist) (name . "http://www.somafm.com/beatblender.pls") (metadata "SomaFM: Beatblender" "http://www.somafm.com/beatblender.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.somafm.com/secretagent.pls") (metadata "SomaFM: Secret Agent" "http://www.somafm.com/secretagent.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.somafm.com/groovesalad.pls") (metadata "SomaFM: Groove Salad" "http://www.somafm.com/groovesalad.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.somafm.com/dronezone.pls") (metadata "SomaFM: Drone Zone" "http://www.somafm.com/dronezone.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.somafm.com/tagstrance.pls") (metadata "SomaFM: Tag's Trance" "http://www.somafm.com/tagstrance.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.somafm.com/indiepop.pls") (metadata "SomaFM: Indie Pop Rocks" "http://www.somafm.com/indiepop.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.somafm.com/doomed.pls") (metadata "SomaFM: Doomed" "http://www.somafm.com/doomed.pls" 1 streamlist)) + (*track* (type . url) (name . "http://listen.radionomy.com:80/-PHILOSOMATIKAPROGRESSIVE-") (metadata "P H I L O S O M A T I K A - Progressive Psytrance" "http://listen.radionomy.com:80/-PHILOSOMATIKAPROGRESSIVE-" 1 url)) + (*track* (type . streamlist) (name . "http://www.bassdrive.com/BassDrive.m3u") (metadata "Drum and Bass Radio, BassDrive" "http://www.bassdrive.com/BassDrive.m3u" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.ibiblio.org/wcpe/wcpe.pls") (metadata "WCPE, Classical Music" "http://www.ibiblio.org/wcpe/wcpe.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://stream.nute.net/kohina/stream.ogg.m3u") (metadata "Kohina - Old school game and demo music" "http://stream.nute.net/kohina/stream.ogg.m3u" 1 streamlist)) + (*track* (type . streamlist) (name . "http://privat.is-by.us:8000/necta192.mp3.m3u") (metadata "Nectarine, Demoscene Radio, DE Continuum's relay 192 mp3" "http://privat.is-by.us:8000/necta192.mp3.m3u" 1 streamlist)) + (*track* (type . streamlist) (name . "http://nectarine.from-de.com/necta192.m3u") (metadata "Nectarine, Demoscene Radio, DE stream (High Bitrate)" "http://nectarine.from-de.com/necta192.m3u" 1 streamlist)) + (*track* (type . streamlist) (name . "http://www.wfmu.org/wfmu.pls") (metadata "WFMU, Freeform radio" "http://www.wfmu.org/wfmu.pls" 1 streamlist)) + (*track* (type . streamlist) (name . "http://nyc01.egihosting.com:6232/listen.pls") (metadata "WBCR-LP - Berkshire Community Radio" "http://nyc01.egihosting.com:6232/listen.pls" 1 streamlist)))) + +(defcustom emms-streams-file (concat (file-name-as-directory emms-directory) + "streams.emms") + "A file used to store the built-in streams." + :group 'emms + :type 'file) + + +;;; ------------------------------------------------------------------ +;;; private functions +;;; ------------------------------------------------------------------ + +(defun emms-streams-install-file (file) + "Install FILE, containing streams." + (when (not (file-directory-p (file-name-directory emms-streams-file))) + (make-directory (file-name-directory emms-streams-file))) + (if (or (not (file-exists-p file)) + (and (file-exists-p file) + (y-or-n-p (format "overwrite existing %s?" file)))) + (progn + (message "writing %s" file) + (with-temp-buffer + (insert emms-source-playlist-native-header-line) + (insert (format "\n%s\n\n" emms-streams-built-in-disclaimer)) + (insert + (concat "(" + (mapconcat + #'(lambda (e) + (format "%S" e)) + emms-streams-built-in-list "\n") + ")")) + (write-region (point-min) (point-max) file)) + (message "writing %s... done" file)) + (message "aborting"))) + + +;;; ------------------------------------------------------------------ +;;; interface +;;; ------------------------------------------------------------------ + +(defun emms-streams-install () (interactive) - (emms-stream-kill-playlist) - (kill-this-buffer) - (run-hooks 'emms-stream-quit-hook)) + "Install the built-in streams file." + (emms-streams-install-file emms-streams-file)) -(defun emms-stream-toggle-default-action () -"Toggle between adding to the current active playlist or play -right now (and thus erase the current active playlist)." +(defun emms-streams () (interactive) - (if (string= emms-stream-default-action "play") - (progn - (emms-stream-kill-playlist) - (setq emms-stream-default-action "add") - (message "Default action is now add")) - (emms-stream-create-playlist) - (setq emms-stream-default-action "play") - (message "Default action is now play"))) + "Create or switch to the built-in streaming audio playlist." + (when (and (not (file-exists-p emms-streams-file)) + (y-or-n-p "Emms' built-in streams file hasn't been installed yet. Install it now?")) + (emms-streams-install)) + (let ((buf (get-buffer emms-streams-buffer-name))) + (when (not buf) + (with-current-buffer (get-buffer-create emms-streams-buffer-name) + (setq buf (current-buffer)) + (emms-playlist-mode) + (setq emms-playlist-buffer-p t) + (emms-playlist-set-playlist-buffer (current-buffer)) + (emms-add-native-playlist emms-streams-file))) + (switch-to-buffer buf))) -;; info part -; (define-emms-info-method emms-info-url -; :providep 'emms-info-url-providep -; :get 'emms-info-url-get) -;; :set 'emms-info-url-set) - -;; A way to get the last element. it is either the only one, or the -;; last one added by emms-add-url. so in both cases, that's what we -;; want. -;; FIXME : not working with the new design. Yrk ? -; (defun emms-stream-last-element () -; (elt emms-playlist (- (length emms-playlist) 1))) - -(defun emms-info-url-providep (track) - (if (eq (emms-track-type track) 'url) - t - nil)) - -; (defun emms-info-url-get (track) -; (make-emms-info -; :title (emms-stream-url (emms-track-get track 'metadata)) -; :artist (emms-stream-name (emms-track-get track 'metadata)) -; :album " " -; :note " " -; :year " " -; :genre " " -; :file (emms-stream-url (emms-track-get track 'metadata)))) - -;; Then you register it with emms-info, by adding it to -;; `emms-info-methods-list'. - -; (add-to-list 'emms-info-methods-list 'emms-info-url) - -(defun emms-stream-add-data-to-track (track) - (emms-track-set track 'metadata emms-stream-last-stream)) - -(add-to-list 'emms-track-initialize-functions - 'emms-stream-add-data-to-track) - -; (when (featurep 'emms-info) -; (eval-when-compile (require 'emms-info)) ; appease byte-compiler -; (add-to-list 'emms-info-methods-list 'emms-info-streamlist) -; (defun emms-info-streamlist-providep (track) -; (if (eq (emms-track-type track) 'streamlist) -; t -; nil)) -; (define-emms-info-method emms-info-streamlist ;; FIXME-PLS ? -; :providep 'emms-info-streamlist-providep ;; FIXME-PLS ? -; :get 'emms-info-url-get)) (provide 'emms-streams) + ;;; emms-streams.el ends here |