New patches:
[Support for Last.fm
address@hidden
This patch adds a new file which enables EMMS to send the songs you listened to
to last.fm.
I volunteer to maintain and enhance the file. Please tell me what I have to do
therefore. (Sign papers, etc.)
Tassilo Horn
] {
addfile ./emms-lastfm.el
hunk ./emms-lastfm.el 1
+;;; emms-lastfm.el --- add your listened songs to your profile at last.fm
+
+;; Copyright (C) 2006 Tassilo Horn
+
+;; Author: Tassilo Horn
+;; Keywords: emms, mp3, mpeg, multimedia
+
+;; 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 2, 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.
+
+;; You should have received a copy of the GNU General Public License
+;; along with EMMS; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This code sends information about what music you are playing to
+;; last.fm. See and
+;; .
+
+;; It requires http-get.el and http-post.el which can be get from
+;; http://emacswiki.org/cgi-bin/wiki.pl?SimpleWikiEditMode. (You have to get it
+;; straight from savannah CVS.)
+
+;; Then tell emacs where those files are:
+;; (add-to-list 'load-path "~/elisp/http-emacs")
+
+;;; Sample configuration:
+
+;; (setq emms-lastfm-username "my-user-name"
+;; emms-lastfm-password "very-secret!")
+
+;;; Usage:
+
+;; To activate the last.fm emms plugin, run:
+;; M-x emms-lastfm-activate
+
+;; To deactivate the last.fm emms plugin, run:
+;; C-u -1 M-x emms-lastfm-activate
+
+;; -----------------------------------------------------------------------
+
+;; TODO: Have a look at `emms-playing-time'. Stopping the timer may not be
+;; needed.
+;; TODO: Implement a better error handling and give better infos to the user.
+
+(require 'http-get)
+(require 'http-post)
+
+(defvar emms-lastfm-username ""
+ "Your last.fm username")
+(defvar emms-lastfm-password ""
+ "Your last.fm password")
+
+(defconst emms-lastfm-server "http://post.audioscrobbler.com/"
+ "The last.fm server responsible for the handshaking procedure.")
+;; TODO: get an id for emms (There should be no release without a valid
+;; id. Email to address@hidden was sent, waiting for reply with our id.
+(defconst emms-lastfm-client-id "tst")
+(defconst emms-lastfm-client-version 1.0)
+
+;; used internally
+(defvar emms-lastfm-process nil)
+(defvar emms-lastfm-md5-challenge nil)
+(defvar emms-lastfm-submit-url nil)
+(defvar emms-lastfm-current-track nil)
+(defvar emms-lastfm-timer nil)
+
+(defun emms-lastfm-new-track-function ()
+ (setq emms-lastfm-current-track
+ (emms-playlist-current-selected-track))
+ ;; Tracks should be submitted, if they played 240 secs or half of their
+ ;; length, whichever comes first.
+ (let ((secs
+ (/ (cdr (assoc 'info-playing-time
+ emms-lastfm-current-track))
+ 2)))
+ (when (> secs 240)
+ (setq secs 240))
+ (unless (< secs 15) ;; Skip titles shorter than 30 seconds
+ (setq emms-lastfm-timer
+ (run-with-timer secs nil 'emms-lastfm-submit-track)))))
+
+(defun emms-lastfm-cancel-timer ()
+ (when emms-lastfm-timer
+ (cancel-timer emms-lastfm-timer)
+ (setq emms-lastfm-timer nil)))
+
+(defun emms-lastfm-activate (&optional ARG)
+ "Submit the tracks you listened to to http://www.last.fm, if
+ARG is positive. If ARG is negative or zero submission of the
+tracks will be stopped. This applies to the current track, too."
+ (interactive "p")
+ (if (> ARG 0)
+ (progn
+ (add-hook 'emms-player-started-hook
+ 'emms-lastfm-handshake-if-needed)
+ (add-hook 'emms-player-started-hook
+ 'emms-lastfm-new-track-function)
+ (add-hook 'emms-player-stopped-hook
+ 'emms-lastfm-cancel-timer)
+ (add-hook 'emms-player-paused-hook
+ 'emms-lastfm-cancel-timer)
+ (message "EMMS Last.fm plugin activated."))
+ (remove-hook 'emms-player-started-hook
+ 'emms-lastfm-handshake-if-needed)
+ (remove-hook 'emms-player-started-hook
+ 'emms-lastfm-new-track-function)
+ (remove-hook 'emms-player-stopped-hook
+ 'emms-lastfm-cancel-timer)
+ (remove-hook 'emms-player-paused-hook
+ 'emms-lastfm-cancel-timer)
+ (cancel-timer emms-lastfm-timer)
+ (setq emms-lastfm-md5-challenge nil
+ emms-lastfm-submit-url nil
+ emms-lastfm-process nil
+ emms-lastfm-current-track nil)
+ (message "EMMS Last.fm plugin deactivated.")))
+
+
+(defun read-line ()
+ (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position)))
+
+(defun emms-lastfm-handshake-if-needed ()
+ (when (not (and emms-lastfm-md5-challenge
+ emms-lastfm-submit-url))
+ (emms-lastfm-handshake)))
+
+(defun emms-lastfm-handshake ()
+ "Handshakes with the last.fm server."
+ (interactive)
+ (accept-process-output
+ (setq emms-lastfm-process
+ (http-get (concat emms-lastfm-server "?hs=true&p=1.1"
+ "&c=" emms-lastfm-client-id
+ "&v=" (number-to-string
+ emms-lastfm-client-version)
+ "&u=" emms-lastfm-username)
+ '(("Connection" . "close"))
+ 'emms-lastfm-handshake-sentinel
+ 1.0))))
+
+(defun emms-lastfm-handshake-sentinel (proc msg)
+ "Parses the server reponse and act accordingly."
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (goto-char (point-min))
+ (if (not (string-match "\\(UPTODATE\\|UPDATE\\)" (read-line)))
+ (progn
+ (cond ((string-match "FAILED" (read-line))
+ (error "Handshake failed"))
+ ((string-match "BADUSER" (read-line))
+ (error "Wrong username"))))
+ (goto-line 2)
+ (setq emms-lastfm-md5-challenge (read-line))
+ (next-line)
+ (setq emms-lastfm-submit-url (read-line)))
+ (erase-buffer)))
+
+(defun emms-lastfm-submit-track ()
+ "Submits the current track (`emms-lastfm-current-track') to
+last.fm."
+ (let* ((artist (emms-track-get emms-lastfm-current-track 'info-artist))
+ (title (emms-track-get emms-lastfm-current-track 'info-title))
+ (album (emms-track-get emms-lastfm-current-track 'info-album))
+ (musicbrainz-id "")
+ (track-length (number-to-string
+ (emms-track-get emms-lastfm-current-track
+ 'info-playing-time)))
+ (date (format-time-string "%Y-%m-%d %H:%M:%S" (current-time) t)))
+ (accept-process-output
+ (setq emms-lastfm-process
+ (http-post emms-lastfm-submit-url
+ `(("u" . ,emms-lastfm-username)
+ ("s" . ,(md5 (concat (md5 emms-lastfm-password)
+ emms-lastfm-md5-challenge)))
+ ("a[0]" . ,artist)
+ ("t[0]" . ,title)
+ ("b[0]" . ,album)
+ ("m[0]" . ,musicbrainz-id)
+ ("l[0]" . ,track-length)
+ ("i[0]" . ,date))
+ 'utf-8
+ '(("Connection" . "close"))
+ 'emms-lastfm-submission-sentinel
+ 1.0)))))
+
+(defun emms-lastfm-submission-sentinel (proc msg)
+ "Is called after a track submission to last.fm was made."
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (goto-char (point-min))
+ (if (string= "OK" (read-line))
+ (message "\"%s\" submitted..."
+ (emms-track-description emms-lastfm-current-track))
+ ;; TODO: Inform the user what went wrong.
+ (error "Song couldn't be submitted"))
+ (erase-buffer)))
+
+
+(provide 'emms-lastfm)
+;;; emms-lastfm.el ends here
+
}
[Inclusion of emms-lastfm in emms-devel setup script. Some changes to
address@hidden
emms-lastfm.el
Adds emms-lastfm to the `emms-devel' setup script in emms-setup.el. It's
only required, not activated.
`emms-lastfm-activate' tells the user to set his username and password, if
it's not already set.
replaced `error's with `message's at noncritical warnings.
] {
hunk ./emms-lastfm.el 104
- (if (> ARG 0)
- (progn
- (add-hook 'emms-player-started-hook
- 'emms-lastfm-handshake-if-needed)
- (add-hook 'emms-player-started-hook
- 'emms-lastfm-new-track-function)
- (add-hook 'emms-player-stopped-hook
- 'emms-lastfm-cancel-timer)
- (add-hook 'emms-player-paused-hook
- 'emms-lastfm-cancel-timer)
- (message "EMMS Last.fm plugin activated."))
- (remove-hook 'emms-player-started-hook
- 'emms-lastfm-handshake-if-needed)
- (remove-hook 'emms-player-started-hook
- 'emms-lastfm-new-track-function)
- (remove-hook 'emms-player-stopped-hook
- 'emms-lastfm-cancel-timer)
- (remove-hook 'emms-player-paused-hook
- 'emms-lastfm-cancel-timer)
- (cancel-timer emms-lastfm-timer)
- (setq emms-lastfm-md5-challenge nil
- emms-lastfm-submit-url nil
- emms-lastfm-process nil
- emms-lastfm-current-track nil)
- (message "EMMS Last.fm plugin deactivated.")))
+ (if (not (and emms-lastfm-username emms-lastfm-password))
+ (message "%s" (concat "In order to activate the last.fm plugin you first "
+ "have to set both `emms-lastfm-username' and "
+ "`emms-lastfm-password'."))
+ (if (> ARG 0)
+ (progn
+ (add-hook 'emms-player-started-hook
+ 'emms-lastfm-handshake-if-needed)
+ (add-hook 'emms-player-started-hook
+ 'emms-lastfm-new-track-function)
+ (add-hook 'emms-player-stopped-hook
+ 'emms-lastfm-cancel-timer)
+ (add-hook 'emms-player-paused-hook
+ 'emms-lastfm-cancel-timer)
+ (message "EMMS Last.fm plugin activated."))
+ (remove-hook 'emms-player-started-hook
+ 'emms-lastfm-handshake-if-needed)
+ (remove-hook 'emms-player-started-hook
+ 'emms-lastfm-new-track-function)
+ (remove-hook 'emms-player-stopped-hook
+ 'emms-lastfm-cancel-timer)
+ (remove-hook 'emms-player-paused-hook
+ 'emms-lastfm-cancel-timer)
+ (cancel-timer emms-lastfm-timer)
+ (setq emms-lastfm-md5-challenge nil
+ emms-lastfm-submit-url nil
+ emms-lastfm-process nil
+ emms-lastfm-current-track nil)
+ (message "EMMS Last.fm plugin deactivated."))))
hunk ./emms-lastfm.el 146
- (interactive)
hunk ./emms-lastfm.el 165
- (error "Handshake failed"))
+ (message "Handshake failed"))
hunk ./emms-lastfm.el 167
- (error "Wrong username"))))
+ (message "Wrong username"))))
hunk ./emms-lastfm.el 211
- (error "Song couldn't be submitted"))
+ (message "Song couldn't be submitted"))
hunk ./emms-setup.el 127
+ (require 'emms-lastfm)
}
Context:
[fix faulty emms-playlist-mode keybinding, fix due to William and Damien.
address@hidden
[Added seeking to the playlist keymap, and updated the manual.
address@hidden
[emms-player-mpd: Only display error if we are certain that url.el is not up-to-date
Michael Olson **20061004032213]
[seek-for-alsaplayer
address@hidden
Add relative seek support for alsaplayer
]
[midi-files-via-timidity
address@hidden
A simple-player definition for timidity
]
[emms-playing-time.el: Minor cleanups.
address@hidden
[emms-lyrics.el: Minor Cleanups.
address@hidden
[pause-for-alsaplayer
address@hidden
Get pause/resume working for alsaplayer
]
[mms-for-mplayer
address@hidden
mplayer also supports mms:// URLs
]
[DoTheRightThing with player pausing and emms-bookmarks.el
address@hidden
[Added emms-bookmarks.el
address@hidden
[Added `emms-pause' to emms-playlist-mode.el bound to to ``P''.
address@hidden
[browser: add deletion started/finished message
Damien Elmes **20060923051128]
[Added a link to the online version of the manual.
address@hidden
[emms-playing-time.el now works with `seek-to'.
address@hidden
[Added `seek-to' to emms.el and emms-player-mplayer.el.
address@hidden
[browser/cache: support deleting files, make emms-cache-dirty a defsubst
Damien Elmes **20060922090553]
[TAG 2.1
address@hidden
Patch bundle hash:
58334ae665ba914740e5f5ad83cffc389a0a8551