New patches: [emms-lastfm.dpatch Tassilo Horn **20061206112823 This patch adds emms-lastfm.el, its setup to emms-setup.el and myself to AUTHORS. ] { hunk ./AUTHORS 16 +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 Free Software Foundation, Inc. + +;; 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 +;; . + +;;; 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. + +(require 'url) + +(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. Only for internal use.") +(defconst emms-lastfm-client-id "ems" + "The client ID of EMMS. Don't change it!") +(defconst emms-lastfm-client-version 0.1 + "The version regitered at last.fm. Don't change it!") + +;; used internally +(defvar emms-lastfm-buffer nil "-- only used internally --") +(defvar emms-lastfm-md5-challenge nil "-- only used internally --") +(defvar emms-lastfm-submit-url nil "-- only used internally --") +(defvar emms-lastfm-current-track nil "-- only used internally --") +(defvar emms-lastfm-timer nil "-- only used internally --") + +(defun emms-lastfm-new-track-function () + "This function runs whenever a new track starts and sets the +track submission timer." + (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 (/ (emms-track-get emms-lastfm-current-track 'info-playing-time) + 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) + "Start submitting 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 (not (and emms-lastfm-username emms-lastfm-password)) + (message "%s" + (concat "EMMS: 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.")))) + + +(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." + (let ((url-request-method "GET")) + (setq emms-lastfm-buffer + (url-retrieve (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) + 'emms-lastfm-handshake-sentinel)))) + +(defun emms-lastfm-handshake-sentinel (&rest args) + "Parses the server reponse and inform the user if all worked +well or if an error occured." + (save-excursion + (set-buffer emms-lastfm-buffer) + (goto-char (point-min)) + (re-search-forward (rx (or "UPTODATE" "UPDATE" "FAILED" "BADUSER")) + nil t) + (let ((response (read-line))) + (if (not (string-match (rx (or "UPTODATE""UPDATE")) response)) + (progn + (cond ((string-match "FAILED" response) + (message "EMMS: Handshake failed: %s.") response) + ((string-match "BADUSER" response) + (message "EMMS: Wrong username.")))) + (when (string-match "UPDATE" response) + (message "EMMS: There's a new last.fm plugin version.")) + (next-line) + (setq emms-lastfm-md5-challenge (read-line)) + (next-line) + (setq emms-lastfm-submit-url (read-line)) + (message "EMMS: Handshaking with server done."))))) + +(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)) + (url-http-attempt-keepalives nil) + (url-request-method "POST") + (url-request-extra-headers + '(("Content-type" . + "application/x-www-form-urlencoded; charset=utf-8"))) + (url-request-data (encode-coding-string + (concat "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))) + (setq emms-lastfm-buffer + (url-retrieve emms-lastfm-submit-url + 'emms-lastfm-submission-sentinel)))) + +(defun emms-lastfm-submission-sentinel (&rest args) + "Parses the server reponse and inform the user if all worked +well or if an error occured." + (save-excursion + (set-buffer emms-lastfm-buffer) + (goto-char (point-min)) + (if (re-search-forward "^OK$" nil t) + (progn + (message "EMMS: \"%s\" submitted to last.fm." + (emms-track-description emms-lastfm-current-track)) + (kill-buffer emms-lastfm-buffer)) + (message "EMMS: Song couldn't be submitted to last.fm.")))) + + +(provide 'emms-lastfm) +;;; emms-lastfm.el ends here + hunk ./emms-setup.el 105 - (require 'emms-browser)) + (require 'emms-browser) + (require 'emms-lastfm)) } Context: [AUTHORS: Added Ye Wenbin address@hidden [Fix lyrics minibuffer display. Amixer display playback and more useful commands Wenbin Ye **20061127154113] [Edit all track, set tag to file for mp3 Wenbin Ye **20061205112209] [Add emms-mp3tag and emms-i18n Wenbin Ye **20061205065407] [Add emms-mark and emms-history address@hidden [emms-info-mp3info.el: Replace `emms-iconv' with decode-coding-string and address@hidden encode-coding-string. ] [emms.el: Fix bug introduced by recent changes to emms-playlist-set-playlist-buffer Michael Olson **20061119204738] [Default to current buffer when setting the current EMMS playlist buffer. Michael Olson **20061119053410] [manual: Add documentation for new emms-playlist-mode keybindings Michael Olson **20061119052935] [emms-playlist-mode: Bind "b" key to emms-playlist-set-playlist-buffer. Michael Olson **20061119052907] [emms-playlist-mode: Implement adding the thing at point to the current playlist. If it is a playlist, add its contents instead. Map this to the "a" key. Michael Olson **20061119052254] [emms.el: In emms-playlist-set-playlist-buffer, prompt user from available EMMS playlist buffers rather than all buffers, and display feedback upon setting the current buffer, since this is not an easy change to see Michael Olson **20061119052023] [emms.el: Fix compiler warning Michael Olson **20061119051946] [Don't add subdirectories for directory and playlist-directory source insert methods Michael Olson **20061119041900] [emms-playing-time.el: New variable `emms-playing-time-style', it address@hidden supports two styles at present, `time' and `bar'. ] [bind SPC to `scroll-up' in emms-playlist-mode and update manual. address@hidden [emms-player-mpd: Deal with change in output when getting supported file types Michael Olson **20061028042119] [emms.el: Move macros to the top of the file. address@hidden [NEWS: Add entry for recent emms-player-mpd change Michael Olson **20061023125738] [emms-player-mpd: Handle errors that occur when we begin playback Michael Olson **20061022215310] [NEWS: Version 2 is version 2.0 address@hidden [emms-playlist-mode: Handle case where selection has not been set but user wants to delete a region Michael Olson **20061022201724] [emms-playlist-mode: Fix typo in hook name Michael Olson **20061022022812] [emms-player-mpd: Update version recommendation Michael Olson **20061022012223] [emms-player-mpd: Work properly with tracks inserted by emms-browser Michael Olson **20061022011050] [Add NEWS items since version 2.1 Michael Olson **20061017222117] [emms-player-mplayer.el: Mplayer also supports .vob files. address@hidden [emms-player-mpd: When using the emms-volume interface, allow the user to specify the amount of change in the volume Michael Olson **20061017220404] [Documentation cleanups in emms-player-mpd and emms-source-playlist Michael Olson **20061017215345] [Since emms-player-seeked-to-functions and emms-player-time-set-functions hooks do the same thing, replace the former with the latter Michael Olson **20061017210238] [emms-browser: Fix compiler warning Michael Olson **20061017205310] [emms-player-mpd: Implement seek-to support Michael Olson **20061017205106] [FluidSynth midi file player address@hidden [Added delYsid address@hidden [jackd-support-for-emacs address@hidden jackd is a pro-audio server which can be used as a backend for alsaplayer, mplayer, and lots of other linux audio apps. This module allows to start jackd from within emacs, and connect/disconnect jack client ports. ] [browser: ensure the RNG is seeded before use Damien Elmes **20061011151535] [browser: require sort (fixes bug with sort-fold-case being void) Damien Elmes **20061010125718] [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: 3aa9457f60659f9296b802506db9948cbe70753c