From ea7d3100b660201ff5e24d3c53cb403f23b09786 Mon Sep 17 00:00:00 2001 From: Yoni Rabkin Date: Thu, 24 Dec 2009 21:30:32 +0200 Subject: Replace lisp/emms-lastfm.el with lisp/emms-lastfm-client.el. The original emms-lastfm.el doesn't work at all with the current Last.fm API. --- lisp/emms-lastfm.el | 697 ---------------------------------------------------- 1 file changed, 697 deletions(-) delete mode 100644 lisp/emms-lastfm.el (limited to 'lisp/emms-lastfm.el') diff --git a/lisp/emms-lastfm.el b/lisp/emms-lastfm.el deleted file mode 100644 index a58e13a..0000000 --- a/lisp/emms-lastfm.el +++ /dev/null @@ -1,697 +0,0 @@ -;;; emms-lastfm.el --- add your listened songs to your profile at last.fm - -;; Copyright (C) 2006, 2007, 2008, 2009 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 3, 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-enable' - -;; Now all music you listen to will be submitted to Last.fm to enhance your -;; profile. - -;; To deactivate the last.fm emms plugin, run: -;; `M-x emms-lastfm-disable' - -;; Beside submitting the tracks you listen to, you can also listen to Last.fm -;; radio. Simply copy the lastfm:// URL and run & paste: -;; `M-x emms-lastfm-radio RET lastfm://artist/Britney Spears/fans' -;; (Of course you don't need to use _this_ URL. :-)) - -;; You can also insert Last.fm streams into playlists (or use -;; emms-streams.el to listen to them) by activating the player as -;; follows. -;; (add-to-list 'emms-player-list 'emms-player-lastfm-radio) -;; To insert a Last.fm stream into a playlist, do -;; (emms-insert-lastfm "lastfm://rest-of-url") - -;; There are some functions for conveniently playing the Similar -;; Artists, Fan Radio, and the Global Tag Radio. Here you only need to -;; enter the band's name (for the first two) or the tag. -;; `M-x emms-play-lastfm-similar-artists RET Britney Spears' -;; `M-x emms-play-lastfm-artist-fan RET Modest Mouse' -;; `M-x emms-play-lastfm-global-tag RET pop' - -;; When you're listening to a Last.fm radio station you have the possibility to -;; give feedback to them. If you like the current song, type -;; `M-x emms-lastfm-radio-love'. -;; If it's not that good, or it just happens to not fit to your actual mood, -;; type -;; `M-x emms-lastfm-radio-skip' -;; and this song will be skipped. -;; If you really hate that song and you never want to hear it again, ban it by -;; typing -;; `M-x emms-lastfm-radio-ban'. - -;;; TODO -;; -;; - Get the last.fm radio stuff right again. Currently the rating stuff seems -;; to be broken. There seems to be no official API, so one needs to look -;; into the sources of the official client which can be found at -;; http://www.audioscrobbler.net/development/client/. - -;; ----------------------------------------------------------------------- - -(require 'url) -(require 'emms) -(require 'emms-mode-line) -(require 'emms-playing-time) -(require 'emms-source-file) -(require 'emms-url) - -;;; Variables - -(defgroup emms-lastfm nil - "Interaction with the services offered by http://www.last.fm." - :prefix "emms-lastfm-" - :group 'emms) - -(defcustom emms-lastfm-username "" - "Your last.fm username" - :type 'string - :group 'emms-lastfm) - -(defcustom emms-lastfm-password "" - "Your last.fm password" - :type 'string - :group 'emms-lastfm) - -(defcustom emms-lastfm-submission-verbose-p nil - "If non-nil, display a message every time we submit a track to Last.fm." - :type 'boolean - :group 'emms-lastfm) - -(defcustom emms-lastfm-submit-track-types '(file) - "Specify what types of tracks to submit to Last.fm. -The default is to only submit files. - -To submit every track to Last.fm, set this to t. - -Note that it is not very meaningful to submit playlists, -streamlists, or Last.fm streams to Last.fm." - :type '(choice (const :tag "All" t) - (set :tag "Types" - (const :tag "Files" file) - (const :tag "URLs" url) - (const :tag "Playlists" playlist) - (const :tag "Streamlists" streamlist) - (const :tag "Last.fm streams" lastfm))) - :group 'emms-lastfm) - -(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.2 - "The version registered at last.fm. Don't change it!") -(defconst emms-lastfm-protocol-version 1.2 - "The version of the supported last.fm protocol. Don't change it.") - -;; used internally -(defvar emms-lastfm-process nil "-- only used internally --") -(defvar emms-lastfm-session-id nil "-- only used internally --") -(defvar emms-lastfm-now-playing-url 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 --") -(defvar emms-lastfm-current-track-starting-time-string nil "-- only used internally --") - -;;; Scrobbling - -(defun emms-lastfm-new-track-function () - "This function should run whenever a new track starts (or a -paused track resumes) and sets the track submission timer." - (setq emms-lastfm-current-track - (emms-playlist-current-selected-track)) - (setq emms-lastfm-current-track-starting-time-string - (emms-lastfm-current-unix-time-string)) - ;; 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)) - (type (emms-track-type emms-lastfm-current-track))) - (when (and secs - (or (eq emms-lastfm-submit-track-types t) - (and (listp emms-lastfm-submit-track-types) - (memq type emms-lastfm-submit-track-types)))) - (when (> secs 240) - (setq secs 240)) - (unless (< secs 30) ;; Skip titles shorter than 30 seconds - (setq secs (- (/ secs 2) emms-playing-time)) - (unless (< secs 0) - (setq emms-lastfm-timer - (run-with-timer secs nil 'emms-lastfm-submit-track)))))) - ;; Update the now playing info displayed on the user's last.fm page. This - ;; doesn't affect the user's profile, so it can be done even for tracks that - ;; should not be submitted. - (emms-lastfm-submit-now-playing)) - -(defun emms-lastfm-http-POST (url string sentinel &optional sentinel-args) - "Perform a HTTP POST request to URL using STRING as data. -STRING will be encoded to utf8 before the request. Call SENTINEL -with the result buffer." - (let ((url-http-attempt-keepalives nil) - (url-show-status emms-lastfm-submission-verbose-p) - (url-request-method "POST") - (url-request-extra-headers - '(("Content-type" - . "application/x-www-form-urlencoded; charset=utf-8"))) - (url-request-data (encode-coding-string string 'utf-8))) - (url-retrieve url sentinel sentinel-args))) - -(defun emms-lastfm-http-GET (url sentinel &optional sentinel-args) - "Perform a HTTP GET request to URL. -Call SENTINEL with SENTINEL-ARGS and the result buffer." - (let ((url-show-status emms-lastfm-submission-verbose-p) - (url-request-method "GET")) - (url-retrieve url sentinel sentinel-args))) - -(defun emms-lastfm-submit-now-playing () - "Submit now-playing infos to last.fm. -These will be displayed on the user's last.fm page." - (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)) - (track-number (emms-track-get emms-lastfm-current-track - 'info-tracknumber)) - (musicbrainz-id "") - (track-length (number-to-string - (or (emms-track-get emms-lastfm-current-track - 'info-playing-time) - 0)))) - ;; wait up to 5 seconds to submit np infos in order to finish handshaking. - (dotimes (i 5) - (when (not (and emms-lastfm-session-id - emms-lastfm-now-playing-url)) - (sit-for 1))) - (when (and emms-lastfm-session-id - emms-lastfm-now-playing-url) - (emms-lastfm-http-POST emms-lastfm-now-playing-url - (concat "&s=" emms-lastfm-session-id - "&a[0]=" (emms-url-quote artist) - "&t[0]=" (emms-url-quote title) - "&b[0]=" (emms-url-quote album) - "&l[0]=" track-length - "&n[0]=" track-number - "&m[0]=" musicbrainz-id) - 'emms-lastfm-submit-now-playing-sentinel)))) - -(defun emms-lastfm-submit-now-playing-sentinel (&rest args) - "Parses the server reponse and inform the user if all worked -well or if an error occured." - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (goto-char (point-min)) - ;; skip to the first empty line and go one line further. There the last.fm - ;; response starts. - (re-search-forward "^$" nil t) - (forward-line) - (if (re-search-forward "^OK$" nil t) - (progn - (when emms-lastfm-submission-verbose-p - (message "EMMS: Now playing infos submitted to last.fm")) - (kill-buffer buffer)) - (message "EMMS: Now playing infos couldn't be submitted to last.fm: %s" - (emms-read-line))))) - -(defun emms-lastfm-cancel-timer () - "Cancels `emms-lastfm-timer' if it is running." - (emms-cancel-timer emms-lastfm-timer) - (setq emms-lastfm-timer nil)) - -(defun emms-lastfm-pause () - "Handles things to be done when the player is paused or -resumed." - (if emms-player-paused-p - ;; the player paused - (emms-lastfm-cancel-timer) - ;; The player resumed - (emms-lastfm-new-track-function))) - -(defun emms-lastfm (&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") - (cond - ((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'"))) - ((not emms-playing-time-p) - (message "%s" - (concat "EMMS: The last.fm plugin needs the functionality " - "provided by `emms-playing-time'. It seems that you " - "disabled it explicitly in your init file using code " - "like this: `(emms-playing-time -1)'. Delete that " - "line and have a look at `emms-playing-time's doc " - "string"))) - (t - (if (and ARG (> ARG 0)) - (progn - ;; Append it. Else the playing time could be started a bit too late. - (add-hook 'emms-player-started-hook - 'emms-lastfm-handshake-if-needed t) - ;; Has to be appended, because it has to run after - ;; `emms-playing-time-start' - (add-hook 'emms-player-started-hook - 'emms-lastfm-new-track-function t) - (add-hook 'emms-player-stopped-hook - 'emms-lastfm-cancel-timer) - (add-hook 'emms-player-paused-hook - 'emms-lastfm-pause) - ;; Clean up after EMMS radio - (remove-hook 'emms-player-started-hook - 'emms-lastfm-cancel-timer-after-stop) - (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-pause) - (when emms-lastfm-timer (emms-cancel-timer emms-lastfm-timer)) - (setq emms-lastfm-session-id nil - emms-lastfm-submit-url nil - emms-lastfm-process nil - emms-lastfm-current-track nil) - (message "EMMS Last.fm plugin deactivated"))))) - -(defalias 'emms-lastfm-activate 'emms-lastfm) -(emms-make-obsolete 'emms-lastfm-activate 'emms-lastfm "EMMS 2.2") - -(defun emms-lastfm-enable () - "Enable the emms last.fm plugin." - (interactive) - (emms-lastfm 1)) - -(defun emms-lastfm-disable () - "Disable the emms last.fm plugin." - (interactive) - (emms-lastfm -1)) - -(defun emms-lastfm-restart () - "Disable and reenable the last.fm plugin. This will cause a new -handshake." - (emms-lastfm-disable) - (emms-lastfm-enable)) - -(defun emms-lastfm-handshake-if-needed () - (when (not (and emms-lastfm-session-id - emms-lastfm-submit-url - emms-lastfm-now-playing-url)) - (emms-lastfm-handshake))) - -(defun emms-lastfm-current-unix-time-string () - (replace-regexp-in-string "\\..*" "" (number-to-string (float-time)))) - -(defun emms-lastfm-handshake () - "Handshakes with the last.fm server." - (let ((timestamp (emms-lastfm-current-unix-time-string))) - (emms-lastfm-http-GET - (concat emms-lastfm-server - "?hs=true" - "&p=" (number-to-string emms-lastfm-protocol-version) - "&c=" emms-lastfm-client-id - "&v=" (number-to-string emms-lastfm-client-version) - "&u=" (emms-url-quote emms-lastfm-username) - "&t=" timestamp - "&a=" (md5 (concat (md5 emms-lastfm-password) timestamp))) - '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." - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (goto-char (point-min)) - ;; skip to the first empty line and go one line further. There the last.fm - ;; response starts. - (re-search-forward "^$" nil t) - (forward-line) - (let ((response (emms-read-line))) - (if (not (string-match (rx (or "OK")) response)) - (message "EMMS: Handshake failed: %s" response) - (forward-line) - (setq emms-lastfm-session-id (emms-read-line)) - (forward-line) - (setq emms-lastfm-now-playing-url (emms-read-line)) - (forward-line) - (setq emms-lastfm-submit-url (emms-read-line)) - (message "EMMS: Handshaking with server done") - (kill-buffer 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)) - (track-number (emms-track-get emms-lastfm-current-track 'info-tracknumber)) - (musicbrainz-id "") - (track-length (number-to-string - (emms-track-get emms-lastfm-current-track - 'info-playing-time)))) - (emms-lastfm-http-POST - emms-lastfm-submit-url - (concat "&s=" emms-lastfm-session-id - "&a[0]=" (emms-url-quote artist) - "&t[0]=" (emms-url-quote title) - "&i[0]=" emms-lastfm-current-track-starting-time-string - "&o[0]=P" ;; TODO: Maybe support others. See the API. - "&r[0]=" ;; The rating. Empty if not applicable (for P it's not) - "&l[0]=" track-length - "&b[0]=" (emms-url-quote album) - "&n[0]=" track-number - "&m[0]=" musicbrainz-id) - '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." - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (goto-char (point-min)) - ;; skip to the first empty line and go one line further. There the last.fm - ;; response starts. - (re-search-forward "^$" nil t) - (forward-line) - (if (re-search-forward "^OK$" nil t) - (progn - (when emms-lastfm-submission-verbose-p - (message "EMMS: \"%s\" submitted to last.fm" - (emms-track-description emms-lastfm-current-track))) - (kill-buffer buffer)) - (message "EMMS: Song couldn't be submitted to last.fm: %s" - (emms-read-line))))) - -;;; Playback of lastfm:// streams - -(defgroup emms-player-lastfm-radio nil - "EMMS player for Last.fm streams." - :group 'emms-player - :prefix "emms-player-lastfm-") - -(defcustom emms-player-lastfm-radio (emms-player 'emms-lastfm-radio-start - 'ignore ; no need to stop - 'emms-lastfm-radio-playable-p) - "*Parameters for the Last.fm radio player." - :type '(cons symbol alist) - :group 'emms-player-lastfm-radio) - -(defconst emms-lastfm-radio-base-url "http://ws.audioscrobbler.com/radio/" - "The base URL for playing lastfm:// stream. --- only used internally --") - -(defvar emms-lastfm-radio-session nil "-- only used internally --") -(defvar emms-lastfm-radio-stream-url nil "-- only used internally --") - -(defun emms-lastfm-radio-get-handshake-url () - (concat emms-lastfm-radio-base-url - "handshake.php?version=" (number-to-string - emms-lastfm-client-version) - "&platform=" emms-lastfm-client-id - "&username=" (emms-url-quote emms-lastfm-username) - "&passwordmd5=" (md5 emms-lastfm-password) - "&debug=" (number-to-string 9))) - -(defun emms-lastfm-radio-handshake (fn radio-url) - "Handshakes with the last.fm server. -Calls FN when done with RADIO-URL as its only argument." - (emms-lastfm-http-GET (emms-lastfm-radio-get-handshake-url) - 'emms-lastfm-radio-handshake-sentinel - (list fn radio-url))) - -(defun emms-lastfm-radio-handshake-sentinel (status fn radio-url) - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (setq emms-lastfm-radio-session (emms-key-value "session")) - (setq emms-lastfm-radio-stream-url (emms-key-value "stream_url")) - (kill-buffer buffer) - (if (and emms-lastfm-radio-session emms-lastfm-radio-stream-url) - (progn - (message "EMMS: Handshaking for Last.fm playback successful") - (funcall fn radio-url)) - (message "EMMS: Failed handshaking for Last.fm playback")))) - -(defun emms-lastfm-radio-1 (lastfm-url) - "Internal function used by `emms-lastfm-radio'." - (if (and emms-lastfm-radio-session - emms-lastfm-radio-stream-url) - (progn - (emms-lastfm-http-GET - (concat emms-lastfm-radio-base-url - "adjust.php?" - "session=" emms-lastfm-radio-session - "&url=" (emms-url-quote lastfm-url) - "&debug=" (number-to-string 0)) - 'emms-lastfm-radio-sentinel)) - (message "EMMS: Cannot play Last.fm stream"))) - -(defun emms-lastfm-radio (lastfm-url) - "Plays the stream associated with the given Last.fm URL. (A -Last.fm URL has the form lastfm://foo/bar/baz, e.g. - - lastfm://artist/Manowar/similarartists - -or - - lastfm://globaltags/metal." - (interactive "sLast.fm URL: ") - ;; Streamed songs must not be added to the lastfm profile - (emms-lastfm-disable) - (if (not (and emms-lastfm-radio-session - emms-lastfm-radio-stream-url)) - (emms-lastfm-radio-handshake #'emms-lastfm-radio-1 lastfm-url) - (emms-lastfm-radio-1 lastfm-url))) - -(defun emms-lastfm-radio-playable-p (track) - "Determine whether the Last.fm player can play this track." - (let ((name (emms-track-get track 'name)) - (type (emms-track-get track 'type))) - (and (eq type 'lastfm) - (string-match "^lastfm://" name)))) - -(defun emms-lastfm-radio-start (track) - "Start playing TRACK." - (when (emms-lastfm-radio-playable-p track) - (let ((name (emms-track-get track 'name))) - (emms-lastfm-radio name)))) - -(defcustom emms-lastfm-radio-metadata-period 15 - "When listening to Last.fm Radio every how many seconds should -emms-lastfm poll for metadata? If set to nil, there won't be any -polling at all. - -The default is 15: That means that the mode line will display the -wrong (last) track's data for a maximum of 15 seconds. If your -network connection has a big latency this value may be too -high. (But then streaming a 128KHz mp3 won't be fun anyway.)" - :type '(choice integer - (const :tag "Disable" nil)) - :group 'emms-lastfm) - -(defun emms-lastfm-cancel-timer-after-stop () - (add-hook 'emms-player-stopped-hook - 'emms-lastfm-cancel-timer)) - -(defun emms-lastfm-radio-sentinel (&rest args) - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (if (string= (emms-key-value "response" buffer) "OK") - (progn - (kill-buffer buffer) - (add-hook 'emms-player-started-hook - 'emms-lastfm-cancel-timer-after-stop) - (emms-play-url emms-lastfm-radio-stream-url) - (when emms-lastfm-radio-metadata-period - (when emms-lastfm-timer - (emms-lastfm-cancel-timer)) - (setq emms-lastfm-timer - (run-with-timer 0 emms-lastfm-radio-metadata-period - 'emms-lastfm-radio-request-metadata))) - (message "EMMS: Playing Last.fm stream")) - (kill-buffer buffer) - (message "EMMS: Bad response from Last.fm")))) - -(defun emms-lastfm-np (&optional insertp callback) - "Show the currently-playing lastfm radio tune. - -If INSERTP is non-nil, insert the description into the current -buffer instead. - -If CALLBACK is a function, call it with the current buffer and -description as arguments instead of displaying the description or -inserting it." - (interactive "P") - (emms-lastfm-radio-request-metadata - (lambda (status insertp buffer callback) - (let ((response-buf (current-buffer)) - artist title) - (emms-http-decode-buffer response-buf) - (setq artist (emms-key-value "artist" response-buf) - title (emms-key-value "track" response-buf)) - (kill-buffer response-buf) - (let ((msg (if (and title artist) - (format emms-show-format - (format "%s - %s" artist title)) - "Nothing playing right now"))) - (cond ((functionp callback) - (when (and title artist) - (funcall callback buffer msg))) - ((and insertp title artist) - (with-current-buffer buffer - (insert msg))) - (t (message msg)))))) - (list insertp (current-buffer) callback))) - -(defun emms-lastfm-read-artist () - "Read an artist name from the user." - (let ((artists nil)) - (when (boundp 'emms-cache-db) - (maphash - #'(lambda (file track) - (let ((artist (emms-track-get track 'info-artist))) - (when artist - (add-to-list 'artists artist)))) - emms-cache-db)) - (if artists - (emms-completing-read "Artist: " artists) - (read-string "Artist: ")))) - -(defun emms-play-lastfm-similar-artists (artist) - "Plays the similar artist radio of ARTIST." - (interactive (list (emms-lastfm-read-artist))) - (emms-lastfm-radio (concat "lastfm://artist/" - artist - "/similarartists"))) - -(defun emms-play-lastfm-global-tag (tag) - "Plays the global tag radio of TAG." - (interactive "sGlobal Tag: ") - (emms-lastfm-radio (concat "lastfm://globaltags/" tag))) - -(defun emms-play-lastfm-artist-fan (artist) - "Plays the artist fan radio of ARTIST." - (interactive (list (emms-lastfm-read-artist))) - (emms-lastfm-radio (concat "lastfm://artist/" artist "/fans"))) - -(defun emms-lastfm-radio-love () - "Inform Last.fm that you love the currently playing song." - (interactive) - (emms-lastfm-radio-rating "love")) - -(defun emms-lastfm-radio-skip () - "Inform Last.fm that you want to skip the currently playing -song." - (interactive) - (emms-lastfm-radio-rating "skip")) - -(defun emms-lastfm-radio-ban () - "Inform Last.fm that you want to ban the currently playing -song." - (interactive) - (emms-lastfm-radio-rating "ban")) - -(defun emms-lastfm-radio-rating (command) - (emms-lastfm-http-GET - (concat emms-lastfm-radio-base-url - "control.php?" - "session=" emms-lastfm-radio-session - "&command=" command - "&debug=" (number-to-string 0)) - 'emms-lastfm-radio-rating-sentinel)) - -(defun emms-lastfm-radio-rating-sentinel (&rest args) - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (if (string= (emms-key-value "response" buffer) "OK") - (message "EMMS: Rated current track") - (message "EMMS: Rating failed")) - (kill-buffer buffer))) - -(defun emms-lastfm-radio-request-metadata (&optional fn data) - "Request the metadata of the current song and display it. - -If FN is given, call it instead of -`emms-lastfm-radio-request-metadata-sentinel', with DATA as its -first parameter. - -If DATA is given, it should be a list." - (interactive) - (emms-lastfm-http-GET - (concat emms-lastfm-radio-base-url - "np.php?" - "session=" emms-lastfm-radio-session - "&debug=" (number-to-string 0)) - (or fn 'emms-lastfm-radio-request-metadata-sentinel) - data)) - -(defun emms-lastfm-radio-request-metadata-sentinel (&rest args) - (let ((buffer (current-buffer))) - (emms-http-decode-buffer buffer) - (let ((artist (emms-key-value "artist" buffer)) - (title (emms-key-value "track" buffer)) - (track (emms-playlist-current-selected-track))) - (kill-buffer buffer) - (emms-track-set track 'info-artist artist) - (emms-track-set track 'info-title title) - (emms-track-updated track)))) - - -;;; Utility functions - -(defun emms-read-line () - (buffer-substring-no-properties (line-beginning-position) - (line-end-position))) - -(defun emms-key-value (key &optional buffer) - "Returns the value of KEY from BUFFER. -If BUFFER is nil, use the current buffer. - -BUFFER has to contain a key-value list like: - -foo=bar -x=17" - (unless (and buffer (not (buffer-live-p buffer))) - (with-current-buffer (or buffer (current-buffer)) - (goto-char (point-min)) - (when (re-search-forward (concat "^" key "=") nil t) - (buffer-substring-no-properties (point) (line-end-position)))))) - -(provide 'emms-lastfm) -;;; emms-lastfm.el ends here -- cgit v1.2.3