aboutsummaryrefslogtreecommitdiff
path: root/emms-score.el
diff options
context:
space:
mode:
Diffstat (limited to 'emms-score.el')
-rw-r--r--emms-score.el272
1 files changed, 272 insertions, 0 deletions
diff --git a/emms-score.el b/emms-score.el
new file mode 100644
index 0000000..8c783c5
--- /dev/null
+++ b/emms-score.el
@@ -0,0 +1,272 @@
+;;; emms-score.el --- Scoring system for mp3player
+
+;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008,
+;; 2009, 2018 Free Software Foundation, Inc.
+
+;; Authors: Jean-Philippe Theberge <jphiltheberge@videotron.ca>,
+;; Yoni Rabkin <yrk@gnu.org>
+;;
+;; 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:
+
+;; NOTE: This is experimental stuff - comments welcome! There
+;; shouldn't worky anything in that file... scores aren't saved, they
+;; even don't have any consequence on playing order and there's just
+;; one mood in the moment. But it's a beginning and you can score down
+;; or up tracks... :)
+;;
+;; * How to use scoring in emms
+;;
+;; When you load emms, you are set to a default mood
+;; 'emms-default-mood' A mood is a one word string describing how
+;; you feel (like "funny", "tired", "aggresive"...) Each mood have is
+;; own set of scoring rules.
+;;
+;; You can change your mood with M-x emms-score-change-mood.
+;;
+;; Every music file start with a default score of 0 the command
+;; emms-score-up-playing and emms-score-down-playing modify the
+;; score of the file you are curently listening by 1 In addition,
+;; skipping a file (with emms-skip) automaticaly score the file
+;; down.
+;;
+;; With scoring on (this mean the variable emms-use-scoring is t),
+;; emms will compare the score of the file with your tolerance to
+;; decide if it is played or not.
+;;
+;; The default tolerance level is 0 (or the variable
+;; emms-score-min-score). This mean files with a score of 0 or more will
+;; be played and files with a score of -1 or less will be skipped.
+;;
+;; You can change the tolerance (by 1) with M-x
+;; emms-score-lower-tolerance and M-x
+;; emms-score-be-more-tolerant
+
+;;; Code:
+
+(require 'emms)
+
+(defvar emms-scores-list nil)
+(defvar emms-score-current-mood 'default)
+(defvar emms-score-min-score 0)
+(defvar emms-score-default-score 0)
+(defvar emms-score-hash (make-hash-table :test 'equal))
+(defvar emms-score-enabled-p nil
+ "If non-nil, emms score is active.")
+
+(defcustom emms-score-file (concat (file-name-as-directory emms-directory) "scores")
+ "*Directory to store the score file."
+ :type 'directory
+ :group 'emms)
+
+
+;;; User Interfaces
+
+(defun emms-score (arg)
+ "Turn on emms-score if prefix argument ARG is a positive integer,
+off otherwise."
+ (interactive "p")
+ (if (and arg (> arg 0))
+ (progn
+ (setq emms-score-enabled-p t)
+ (emms-score-load-hash)
+ (setq emms-ok-track-function 'emms-score-ok-track-function)
+ (unless noninteractive
+ (add-hook 'kill-emacs-hook 'emms-score-save-hash)))
+ (setq emms-score-enabled-p nil)
+ (emms-score-save-hash)
+ (setq emms-ok-track-function 'emms-default-ok-track-function)
+ (remove-hook 'kill-emacs-hook 'emms-score-save-hash)))
+
+;;;###autoload
+(defun emms-score-enable ()
+ "Turn on emms-score."
+ (interactive)
+ (emms-score 1)
+ (message "emms score enabled"))
+
+;;;###autoload
+(defun emms-score-disable ()
+ "Turn off emms-score."
+ (interactive)
+ (emms-score -1)
+ (message "emms score disabled"))
+
+;;;###autoload
+(defun emms-score-toggle ()
+ "Toggle emms-score."
+ (interactive)
+ (if emms-score-enabled-p
+ (emms-score-disable)
+ (emms-score-enable)))
+
+(defun emms-score-change-mood (mood)
+ "Change the current MOOD.
+The score hash is automatically saved."
+ (interactive "sMood: ")
+ (emms-score-save-hash)
+ (setq emms-score-current-mood (intern (downcase mood))))
+
+(defun emms-score-up-playing ()
+ (interactive)
+ (if emms-player-playing-p
+ (emms-score-change-score 1 (emms-score-current-selected-track-filename))
+ (error "No track currently playing")))
+
+(defun emms-score-down-playing ()
+ (interactive)
+ (if emms-player-playing-p
+ (emms-score-change-score -1 (emms-score-current-selected-track-filename))
+ (error "No track currently playing")))
+
+(defun emms-score-up-file-on-line ()
+ (interactive)
+ (emms-score-change-score 1 (emms-score-track-at-filename)))
+
+(defun emms-score-down-file-on-line ()
+ (interactive)
+ (emms-score-change-score -1 (emms-score-track-at-filename)))
+
+(defun emms-score-less-tolerant ()
+ "Only play mp3 with a higher score"
+ (interactive)
+ (setq emms-score-min-score (+ emms-score-min-score 1))
+ (message "Will play songs with a score >= %d" emms-score-min-score))
+
+(defun emms-score-more-tolerant ()
+ "Allow playing of mp3 with a lower score."
+ (interactive)
+ (setq emms-score-min-score (- emms-score-min-score 1))
+ (message "Will play songs with a score >= %d" emms-score-min-score))
+
+(defun emms-score-set-playing (score)
+ "Set score for current playing track."
+ (interactive "nSet score for playing track: ")
+ (let ((filename (emms-score-current-selected-track-filename)))
+ (if emms-player-playing-p
+ (emms-score-change-score
+ (- score (emms-score-get-score filename))
+ filename)
+ (error "No track currently playing"))))
+
+(defun emms-score-set-file-on-line (score)
+ "Set score for track at point in emms-playlist buffer."
+ (interactive "nSet score for track at point: ")
+ (let ((filename (emms-score-track-at-filename)))
+ (if emms-player-playing-p
+ (emms-score-change-score
+ (- score (emms-score-get-score filename))
+ filename))))
+
+(defun emms-score-set-tolerance (tolerance)
+ "Allow playing tracks with a score >= tolerance."
+ (interactive "nSet tolerance: ")
+ (setq emms-score-min-score tolerance)
+ (message "Will play songs with a score >= %d" emms-score-min-score))
+
+(defun emms-score-show-playing ()
+ "Show score for current playing track in minibuf."
+ (interactive)
+ (message "track/tolerance score: %d/%d"
+ (emms-score-get-score
+ (emms-score-current-selected-track-filename))
+ emms-score-min-score))
+
+(defun emms-score-show-file-on-line ()
+ "Show score for track at point in emms-playlist buffer."
+ (interactive)
+ (message "track/tolerance score: %d/%d"
+ (emms-score-get-score
+ (emms-score-track-at-filename))
+ emms-score-min-score))
+
+
+;;; Internal Functions
+
+(defun emms-score-current-selected-track-filename ()
+ "Return filename of current selected track."
+ (emms-track-get (emms-playlist-current-selected-track) 'name))
+
+(defun emms-score-track-at-filename ()
+ "Return file of track at point in emms-playlist buffer."
+ (emms-track-get (emms-playlist-track-at) 'name))
+
+(defun emms-score-ok-track-function (track)
+ "Decide if to skip or play TRACK."
+ (emms-score-check-score (emms-track-get track 'name)))
+
+(defun emms-score-save-hash ()
+ "Save score hash in `emms-score-file'."
+ (interactive)
+ (unless (file-directory-p (file-name-directory emms-score-file))
+ (make-directory (file-name-directory emms-score-file)))
+ (with-temp-file emms-score-file
+ (let ((standard-output (current-buffer)))
+ (insert "(")
+ (maphash (lambda (key value)
+ (prin1 (cons key value)))
+ emms-score-hash)
+ (insert ")"))))
+
+(defun emms-score-load-hash ()
+ "Load score hash from `emms-score-file'."
+ (interactive)
+ (if (file-exists-p emms-score-file)
+ (let ((score-string (with-temp-buffer
+ (emms-insert-file-contents emms-score-file)
+ (buffer-string))))
+ (if (> (length score-string) 0)
+ (mapc (lambda (elt)
+ (puthash (car elt) (cdr elt) emms-score-hash))
+ (read score-string)))
+ ;; when file not exists, make empty but valid score file
+ (emms-score-save-hash))))
+
+(defun emms-score-get-plist (filename)
+ (gethash filename emms-score-hash))
+
+(defun emms-score-change-score (score filename)
+ (let ((sp (emms-score-get-plist filename) )
+ (sc (emms-score-get-score filename)))
+ (puthash filename
+ (plist-put sp emms-score-current-mood (+ sc score))
+ emms-score-hash)
+ (message "New score is %s" (+ score sc))))
+
+(defun emms-score-create-entry (filename)
+ (puthash filename
+ `(,emms-score-current-mood ,emms-score-default-score)
+ emms-score-hash))
+
+(defun emms-score-get-score (filename)
+ "Return score of TRACK."
+ (let ((plist (emms-score-get-plist filename)))
+ (if (member emms-score-current-mood plist)
+ (plist-get plist emms-score-current-mood)
+ (emms-score-create-entry filename)
+ (emms-score-get-score filename))))
+
+(defun emms-score-check-score (filename)
+ (>= (emms-score-get-score filename) emms-score-min-score))
+
+(provide 'emms-score)
+
+;;; emms-scores.el ends here