emms-help
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[emms-help] Last.fm plugin for EMMS


From: Tassilo Horn
Subject: [emms-help] Last.fm plugin for EMMS
Date: Mon, 09 Oct 2006 14:11:32 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/22.0.50 (gnu/linux)

Hi all,

I've written a plugin for last.fm. Unlike my last version (see
<address@hidden>) this version works. But there's a
bug in http-get.el and http-post.el which needs to be fixed first. I've
sent a patch to its maintainer David Hansen and report back when he
applied it.

I would be happy if emms-lastfm.el could be part of EMMS. Of course I'll
maintain it. What do I have to do?

--8<---------------cut here---------------start------------->8---
;;; emms-lastfm.el --- add your listened songs to your profile at last.fm

;; Copyright (C) 2006  Tassilo Horn <address@hidden>

;; Author: Tassilo Horn <address@hidden>
;; Keywords: emms, mp3, mpeg, multimedia

;; This file 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.

;; This file 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 GNU Emacs; 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 <URL:http://www.last.fm> and
;; <URL:http://www.audioscrobbler.net/wiki/Protocol1.1>.

;; 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")

;; To activate the last.fm emms plugin, run:
;; (emms-lastfm-initialize)

;; -----------------------------------------------------------------------

;; 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")

(defvar emms-lastfm-server "http://post.audioscrobbler.com/";)
;; TODO: get an id for emms
(defvar emms-lastfm-client-id "tst")
(defvar emms-lastfm-client-version 1.0)

;; internally used
(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)))

(defun emms-lastfm-initialize ()
  "Adds handshaking and submission to the relevant hooks."
  (interactive)
  (add-hook 'emms-player-started-hook
            (lambda ()
              (when (not (and emms-lastfm-md5-challenge
                              emms-lastfm-submit-url))
                (emms-lastfm-handshake))))
  (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))


(defun read-line ()
  (buffer-substring-no-properties (line-beginning-position)
                                  (line-end-position)))

(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)))))

(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
--8<---------------cut here---------------end--------------->8---

Bye and thanks,
Tassilo
-- 
My opinions may have changed, but not the fact that I am right.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]