branch: externals/emms commit 06e44f28541ceb050252fa29ad1889c64f97a67f Author: Yoni Rabkin <y...@gnu.org> Commit: Yoni Rabkin <y...@gnu.org>
Add info support for SNES SPC files. Code by Warren Wilkinson. --- AUTHORS | 1 + emms-info-native.el | 10 +++++- emms-info-spc.el | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ emms.el | 2 +- 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 282a1a5677..e7ba653f49 100644 --- a/AUTHORS +++ b/AUTHORS @@ -34,6 +34,7 @@ Tassilo Horn <tass...@member.fsf.org> Thierry Volpiatto Trent Buck <trentb...@gmail.com> Ulrik Jensen <ter...@daimi.au.dk> +Warren Wilkinson <warrenwilkin...@gmail.com> William Xu <william....@gmail.com> Ye Wenbin <wenbi...@gmail.com> Yoni (Johnathan) Rabkin <y...@gnu.org> diff --git a/emms-info-native.el b/emms-info-native.el index 3e3e2d48f7..e17df9126a 100644 --- a/emms-info-native.el +++ b/emms-info-native.el @@ -1,6 +1,6 @@ ;;; emms-info-native.el --- Native Emacs Lisp info method for EMMS -*- lexical-binding: t; -*- -;; Copyright (C) 2020-2021 Free Software Foundation, Inc. +;; Copyright (C) 2020-2023 Free Software Foundation, Inc. ;; Author: Petteri Hintsanen <pette...@iki.fi> @@ -51,6 +51,10 @@ ;; encryption are not supported. Based on id3v2 Informal Standards, ;; see URL `https://id3.org'. ;; +;; - SPC files with extension `.spc' and id666 tags. This is an audio +;; file based on a memory dump from an SPC700, a special audio chip +;; found within Super Nintendos. +;; ;; Format detection is based solely on filename extension, which is ;; matched case-insensitively. @@ -59,6 +63,7 @@ (require 'bindat) (require 'cl-lib) (require 'emms-info) +(require 'emms-info-spc) (require 'seq) (require 'subr-x) @@ -954,6 +959,8 @@ strings." (emms-info-native--decode-flac-comments filename)) ((eq stream-type 'mp3) (emms-info-native--decode-id3v2 filename)) + ((eq stream-type 'spc) + (emms-info-spc--decode-id666 filename)) (t nil)))) (defun emms-info-native--find-stream-type (filename) @@ -967,6 +974,7 @@ Return one of symbols `vorbis', `opus', `flac', or `mp3'." ((string-match ".opus$" filename) 'opus) ((string-match ".flac$" filename) 'flac) ((string-match ".mp3$" filename) 'mp3) + ((string-match ".spc$" filename) 'spc) (t nil)))) (provide 'emms-info-native) diff --git a/emms-info-spc.el b/emms-info-spc.el new file mode 100644 index 0000000000..fd092a52d0 --- /dev/null +++ b/emms-info-spc.el @@ -0,0 +1,95 @@ +;;; emms-info-spc.el --- Native Emacs Lisp info method for EMMS -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Free Software Foundation, Inc. + +;; Author: Warren Wilkinson <warrenwilkin...@gmail.com> + +;; 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 file provides a native emms-info-method for SPC files. (well, +;; actually the id666 tag embedded inside them). "Native" means a pure +;; Emacs Lisp implementation instead of one relying on external tools +;; or libraries. + +;;; Code: + +(require 'bindat) + +(defconst emms-info-spc--id666-magic-array + [#x53 #x4e #x45 #x53 #x2d #x53 #x50#x43 #x37 #x30 #x30 #x20 #x53 #x6f #x75 #x6e #x64 #x20 #x46 #x69 #x6c #x65 #x20 #x44 #x61 #x74 #x61 #x20 #x76 #x30 #x2e #x33 #x30] + "id666 header magic pattern `SNES-SPC700 Sound File Data v0.30'") + +(defconst emms-info-spc--id666-header-bindat-spec + '((file-identifier vec 33) + (eval (unless (equal last emms-info-spc--id666-magic-array) + (error "id666 framing mismatch: expected `%s', got `%s'" + emms-info-spc--id666-magic-array + last))) + (unused u16) + (has-id666 u8) + (revision u8) + (pc-reg u16) + (a-reg u8) + (x-reg u8) + (y-reg u8) + (psw-reg u8) + (sp-reg u8) + (res-reg u16) + (song-title strz 32) + (game-title strz 32) + (dumper strz 16) + (comment strz 32) + (date strz 11) + (fadeout vec 3) + (fadeout-length vec 5) + (artist strz 32)) + "id666 header specification. + +Sources: + +- URL `https://ocremix.org/info/SPC_Format_Specification' +- URL `https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html'") + +(defun emms-info-spc--decode-id666-header (filename) + "Read and decode id666 header from FILENAME." + (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally filename nil 0 210) + (bindat-unpack emms-info-spc--id666-header-bindat-spec + (buffer-string)))) + +(defun emms-info-spc--decode-id666 (filename) + "Read and decode id666 metadata from FILENAME. +Return metadata in a list of (FIELD . VALUE) cons cells, or nil +in case of errors or if there were no known fields in FILENAME." + (condition-case nil + (let ((header (emms-info-spc--decode-id666-header filename))) + (when (= 26 (bindat-get-field header 'has-id666)) + (list + (cons 'info-title (bindat-get-field header 'song-title)) + (cons 'info-album (bindat-get-field header 'game-title)) + (cons 'info-artist (bindat-get-field header 'artist)) + (cons 'info-composer (bindat-get-field header 'artist)) + (cons 'info-note (bindat-get-field header 'comment))))) + (error nil))) + +(provide 'emms-info-spc) + +;;; emms-info-spc.el ends here diff --git a/emms.el b/emms.el index 8ed548072d..4c592a4df4 100644 --- a/emms.el +++ b/emms.el @@ -376,7 +376,7 @@ Point will not be restored afterward." '("ogg" "mp3" "wav" "mpg" "mpeg" "wmv" "wma" "mov" "avi" "divx" "ogm" "ogv" "asf" "mkv" "rm" "rmvb" "mp4" "flac" "vob" "m4a" "ape" - "flv" "webm" "aif" "opus") + "flv" "webm" "aif" "opus" "spc") "A list of common formats which player definitions can use.")