]> git.vanrenterghem.biz Git - musicbrainz.git/commitdiff
Then they left without a sound
authornik gaffney <nik@fo.am>
Tue, 30 May 2023 07:41:39 +0000 (09:41 +0200)
committernik gaffney <nik@fo.am>
Tue, 30 May 2023 07:41:39 +0000 (09:41 +0200)
README.org
listenbrainz.el
musicbrainz.el

index d63d2463a377ad33b113b3e126b6b323d34cdff6..8da83cc9195efc24466021940017923573ab35f0 100644 (file)
@@ -3,11 +3,12 @@
 #+author:
 #+title:  MusicBrainz & ListenBrainz & others
 
 #+author:
 #+title:  MusicBrainz & ListenBrainz & others
 
-
+* Thus                                                             :TOC_2_gh:
 - [[#musicbrainz][MusicBrainz]]
     - [[#musicbrainz-api][MusicBrainz API]]
     - [[#searching--browsing][searching & browsing]]
     - [[#some-examples][some examples]]
 - [[#musicbrainz][MusicBrainz]]
     - [[#musicbrainz-api][MusicBrainz API]]
     - [[#searching--browsing][searching & browsing]]
     - [[#some-examples][some examples]]
+    - [[#cover-art][cover art]]
     - [[#mbid][MBID]]
     - [[#ambiguity][ambiguity]]
     - [[#incompleteness][incompleteness]]
     - [[#mbid][MBID]]
     - [[#ambiguity][ambiguity]]
     - [[#incompleteness][incompleteness]]
@@ -104,6 +105,25 @@ The MBID can be used for specific lookups (and checked if needed using =musicbra
 |  91 | Universal Music | plain logo: “Universal Music” (ongoing)                                                               | [[https://musicbrainz.org/label/13a464dc-b9fd-4d16-a4f4-d4316f6a46c7][13a464dc-b9fd-4d16-a4f4-d4316f6a46c7]] |
 |  90 | ZYX Music       | (1992 ongoing)                                                                                        | [[https://musicbrainz.org/label/6844efda-a451-431e-8cc1-48ab111b4711][6844efda-a451-431e-8cc1-48ab111b4711]] |
 
 |  91 | Universal Music | plain logo: “Universal Music” (ongoing)                                                               | [[https://musicbrainz.org/label/13a464dc-b9fd-4d16-a4f4-d4316f6a46c7][13a464dc-b9fd-4d16-a4f4-d4316f6a46c7]] |
 |  90 | ZYX Music       | (1992 ongoing)                                                                                        | [[https://musicbrainz.org/label/6844efda-a451-431e-8cc1-48ab111b4711][6844efda-a451-431e-8cc1-48ab111b4711]] |
 
+** cover art
+
+Cover art for a release may be available from the [[http://coverartarchive.org/][Cover Art Archive]] and can be accessed via the [[https://musicbrainz.org/doc/Cover_Art_Archive/API][API]]
+
+#+BEGIN_SRC emacs-lisp
+(musicbrainz-coverart "a929130a-535c-4827-8663-f048e1a7ca0d")
+#+END_SRC
+
+
+#+BEGIN_SRC emacs-lisp
+(musicbrainz-coverart-front "a929130a-535c-4827-8663-f048e1a7ca0d")
+#+END_SRC
+
+
+#+BEGIN_SRC emacs-lisp
+(musicbrainz-lookup-release "a929130a-535c-4827-8663-f048e1a7ca0d")
+#+END_SRC
+
+ | Head Cleaning Cassette | Cassette Case | [[https://musicbrainz.org/release/a929130a-535c-4827-8663-f048e1a7ca0d][a929130a-535c-4827-8663-f048e1a7ca0d]] |
 
 ** MBID
 
 
 ** MBID
 
@@ -119,6 +139,7 @@ returns =410c9baf-5469-44f6-9852-826524b80c61=
 (musicbrainz-mbid-p "410c9baf-5469-44f6-9852-826524b80c61")
 #+END_SRC
 
 (musicbrainz-mbid-p "410c9baf-5469-44f6-9852-826524b80c61")
 #+END_SRC
 
+
 ** ambiguity
 
 From the docs…
 ** ambiguity
 
 From the docs…
index fc32c666c931b8804085364ca8e28330a3efeaa2..43084f7773ea41bcb06eea5c6e87ba220cb9d0e3 100644 (file)
@@ -262,7 +262,8 @@ macroexpands to something like ->
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "Listens for user: %s" username)))))))
+                         (message "Listens for user: %s\n%s" username
+                                  (if data data ""))))))))
     (princ (listenbrainz--format-listens response))))
 
 
     (princ (listenbrainz--format-listens response))))
 
 
@@ -279,7 +280,8 @@ macroexpands to something like ->
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "User playing now: %s" username)))))))
+                         (message "User playing now: %s\n%s" username
+                                  (if data data ""))))))))
     (princ (listenbrainz--format-playing response))))
 
 
     (princ (listenbrainz--format-playing response))))
 
 
@@ -358,7 +360,8 @@ possible values are week, month, year, all_time, defaults to all_time."
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "Top recordings for user: %s" username)))))))
+                         (message "Top recordings for user: %s\n%s" username
+                                  (if data data ""))))))))
     (princ (listenbrainz--format-stats-2 response))))
 
 
     (princ (listenbrainz--format-stats-2 response))))
 
 
@@ -381,7 +384,8 @@ possible values are week, month, year, all_time, defaults to all_time."
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "Top releases for user: %s" username)))))))
+                         (message "Top releases for user: %s\n%s" username
+                                  (if data data ""))))))))
     (princ (listenbrainz--format-stats-0 response))))
 
 
     (princ (listenbrainz--format-stats-0 response))))
 
 
@@ -404,7 +408,8 @@ possible values are week, month, year, all_time, defaults to all_time."
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "Top artists for user: %s" username)))))))
+                         (message "Top artists for user: %s\n%s" username
+                                  (if data data ""))))))))
     (princ (listenbrainz--format-stats-1 response))))
 
 
     (princ (listenbrainz--format-stats-1 response))))
 
 
@@ -430,10 +435,11 @@ OUTPUT format can be either `list' (default) or `graph'."
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "Followers for %s" username)))))))
+                         (message "Followers for %s\n%s" username
+                                  (if data data ""))))))))
     (if (string= "graph" output)
     (if (string= "graph" output)
-         (princ (listenbrainz--format-followers-graph response))
-         (princ (listenbrainz--format-followers-list response)))))
+        (princ (listenbrainz--format-followers-graph response))
+        (princ (listenbrainz--format-followers-list response)))))
 
 ;;;###autoload
 (defun listenbrainz-following (username)
 
 ;;;###autoload
 (defun listenbrainz-following (username)
@@ -448,7 +454,8 @@ OUTPUT format can be either `list' (default) or `graph'."
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
              :sync t
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
-                         (message "Users %s is following" username)))))))
+                         (message "Users %s is following\n%s" username
+                                  (if data data ""))))))))
     (princ (listenbrainz--format-following response))))
 
 
     (princ (listenbrainz--format-following response))))
 
 
index 506a23bf2b43692ac24a6f14038a5151714a11ff..50d5a1d6df030347298281d7ebf3748818fba183 100644 (file)
@@ -43,6 +43,7 @@
 
 (require 'request)
 (require 'json)
 
 (require 'request)
 (require 'json)
+(require 'pp)
 
 ;;; ;; ;; ;  ; ;   ;  ;      ;
 ;;
 
 ;;; ;; ;; ;  ; ;   ;  ;      ;
 ;;
 ;;; ; ;; ;;
 
 (defcustom musicbrainz-api-url "https://musicbrainz.org/ws/2"
 ;;; ; ;; ;;
 
 (defcustom musicbrainz-api-url "https://musicbrainz.org/ws/2"
-  "URL for musicbrainz API.
+  "URL for MusicBrainz API.
 Documentation available at https://musicbrainz.org/doc/MusicBrainz_API"
   :type 'string
   :group 'musicbrainz)
 
 Documentation available at https://musicbrainz.org/doc/MusicBrainz_API"
   :type 'string
   :group 'musicbrainz)
 
+(defcustom musicbrainz-coverart-api-url "http://coverartarchive.org"
+  "URL for MusicBrainz Cover Art Archive API.
+Documentation available at https://musicbrainz.org/doc/Cover_Art_Archive/API"
+  :type 'string
+  :group 'musicbrainz)
+
 (defcustom musicbrainz-api-token ""
   "An auth token is required for some functions."
   :type 'string
 (defcustom musicbrainz-api-token ""
   "An auth token is required for some functions."
   :type 'string
@@ -238,6 +245,7 @@ The QUERY field supports the full Lucene Search syntax, some details
 can be found near https://musicbrainz.org/doc/MusicBrainz_API/Search
 or in the Lucene docs."
 
 can be found near https://musicbrainz.org/doc/MusicBrainz_API/Search
 or in the Lucene docs."
 
+  (interactive "sMusicBrainz search type: \nsMusicBrainz search query: ")
   (message "MusicBrainz: searching %s=%s" type query)
   ;; queries may need to be escaped
   (let* ((max (if limit limit 1))
   (message "MusicBrainz: searching %s=%s" type query)
   ;; queries may need to be escaped
   (let* ((max (if limit limit 1))
@@ -252,10 +260,13 @@ or in the Lucene docs."
              :headers (list `("User-Agent" . ,musicbrainz-user-agent))
              :parser 'json-read
              :sync t
              :headers (list `("User-Agent" . ,musicbrainz-user-agent))
              :parser 'json-read
              :sync t
-             :success (cl-function
-                       (lambda (&key data &allow-other-keys)
-                         (message "ok")))))))
-    response))
+             :sucess (cl-function
+                      (lambda (&key data &allow-other-keys)
+                        (message "ok: %s" data)))
+             ))))
+    (if (called-interactively-p 'any)
+        (message "%s" (pp response))
+        response)))
 
 
 ;;;###autoload
 
 
 ;;;###autoload
@@ -269,14 +280,14 @@ Heuristics.
 - if QUERY is an MBID, check artist, recording, etc
 - if QUERY is text, search for artists or recordings, etc"
 
 - if QUERY is an MBID, check artist, recording, etc
 - if QUERY is text, search for artists or recordings, etc"
 
-  (message "MusicBrainz: query %s" query)
+  (message "MusicBrainz: query %s %s" query (if extras extras ""))
   (if (musicbrainz-mbid-p query)
       ;; search (lookup) for things that could have an mbid
       (let ((mbid query))
   (if (musicbrainz-mbid-p query)
       ;; search (lookup) for things that could have an mbid
       (let ((mbid query))
-        (message "searching mbid: %s" mbid))
-      ;; search (search/browse/query) for other things
-      (progn
-        (message "searching other: %s" mbid))))
+        (message "searching mbid: %s" mbid)
+        ;; search (search/browse/query) for other things
+        (progn
+          (message "searching other: %s" mbid)))))
 
 
 ;; generate search functions
 
 
 ;; generate search functions
@@ -291,14 +302,14 @@ Optionally return LIMIT number of results." name)))
     `(defun ,f (query &optional limit) ,doc
        (let* ((max (if limit limit 1))
               (response
     `(defun ,f (query &optional limit) ,doc
        (let* ((max (if limit limit 1))
               (response
-               (musicbrainz-search ,name query max)))
+                (musicbrainz-search ,name query max)))
          (let-alist response
                     (format ,format-string ,@format-args))))))
 
 
 (defmacro musicbrainz--defsearch-2 (name format-string format-args alist)
   "Generate lookup function to format multiple items.
          (let-alist response
                     (format ,format-string ,@format-args))))))
 
 
 (defmacro musicbrainz--defsearch-2 (name format-string format-args alist)
   "Generate lookup function to format multiple items.
-QUERY SUBQUERY FORMAT-STRING FORMAT-ARGS ALIST
+NAME FORMAT-STRING FORMAT-ARGS ALIST
 See listenbrainz--deformatter for details."
   (let ((f (intern (concat "musicbrainz-search-" name)))
         (doc (format "Search for %s using QUERY and show matches.
 See listenbrainz--deformatter for details."
   (let ((f (intern (concat "musicbrainz-search-" name)))
         (doc (format "Search for %s using QUERY and show matches.
@@ -480,6 +491,7 @@ Subqueries
  /ws/2/work
  /ws/2/url"
 
  /ws/2/work
  /ws/2/url"
 
+  (interactive "sMusicBrainz entity type: \nsMusicBrainz MBID for entity: ")
   (message "MusicBrainz: lookup: %s/%s" entity mbid)
   (if (and (musicbrainz-core-entity-p entity)
            (musicbrainz-mbid-p mbid))
   (message "MusicBrainz: lookup: %s/%s" entity mbid)
   (if (and (musicbrainz-core-entity-p entity)
            (musicbrainz-mbid-p mbid))
@@ -495,10 +507,13 @@ Subqueries
                  :sync t
                  :success (cl-function
                            (lambda (&key data &allow-other-keys)
                  :sync t
                  :success (cl-function
                            (lambda (&key data &allow-other-keys)
-                             (message "%s data: %s" entity mbid)))))))
-        response)
-      (error "MusicBrainz: search requires a valid MBID and entity (i.e. one of %s)"
-             musicbrainz-entities-core)))
+                             (when data
+                               (message "%s data: %s" entity mbid))))))))
+        (if (called-interactively-p 'any)
+            (message "%s" (pp response))
+            response))
+      (user-error "MusicBrainz: search requires a valid MBID and entity (i.e. one of %s)"
+                  musicbrainz-entities-core)))
 
 ;; relationship lookups
 
 
 ;; relationship lookups
 
@@ -515,8 +530,10 @@ Subqueries
 NAME FORMAT-STRING FORMAT-ARGS
 See listenbrainz--deformatter for details."
   (let ((f (intern (concat "musicbrainz-lookup-" name)))
 NAME FORMAT-STRING FORMAT-ARGS
 See listenbrainz--deformatter for details."
   (let ((f (intern (concat "musicbrainz-lookup-" name)))
-        (doc "MusicBrainz lookup."))
+        (doc "MusicBrainz lookup.")
+        (prompt (format "sMusicBrainz lookup %s by MBID: " name)))
     `(defun ,f (mbid) ,doc
     `(defun ,f (mbid) ,doc
+       (interactive ,prompt)
        (let ((response
                (musicbrainz-lookup ,name mbid)))
          (let-alist response
        (let ((response
                (musicbrainz-lookup ,name mbid)))
          (let-alist response
@@ -528,8 +545,10 @@ See listenbrainz--deformatter for details."
 QUERY SUBQUERY FORMAT-STRING FORMAT-ARGS ALIST
 See listenbrainz--deformatter for details."
   (let ((f (intern (format "musicbrainz-lookup-%s-%s" query subquery)))
 QUERY SUBQUERY FORMAT-STRING FORMAT-ARGS ALIST
 See listenbrainz--deformatter for details."
   (let ((f (intern (format "musicbrainz-lookup-%s-%s" query subquery)))
-        (doc "MusicBrainz lookup."))
+        (doc "MusicBrainz lookup.")
+        (prompt (format "sMusicBrainz lookup %s %s by MBID: " query subquery)))
     `(defun ,f (mbid) ,doc
     `(defun ,f (mbid) ,doc
+       (interactive ,prompt)
        (let ((response
                (musicbrainz-lookup ,query mbid ,subquery)))
          (let-alist response
        (let ((response
                (musicbrainz-lookup ,query mbid ,subquery)))
          (let-alist response
@@ -767,6 +786,77 @@ Optionally limit the search to TYPE results for ENTITY."
 
 
 
 
 
 
+;;;;;; ; ; ;; ;   ;     ;  ; ; ;;   ;
+;;
+;; Cover Art Archive API
+;;  https://musicbrainz.org/doc/Cover_Art_Archive/API
+;;
+;;;; ; ; ; ; ;
+
+;; /release/{mbid}/
+;; /release/{mbid}/front
+;; /release/{mbid}/back
+;; /release/{mbid}/{id}
+;; /release/{mbid}/({id}|front|back)-(250|500|1200)
+;;
+;; /release-group/{mbid}/
+;; /release-group/{mbid}/front[-(250|500|1200)]
+
+;;;###autoload
+(defun musicbrainz-coverart (mbid &optional release-group)
+  "Search MusicBrainz Cover Art Archive for release MBID.
+When RELEASE-GROUP is non-nil MBID is for a release group, rather than release."
+  (message "MusicBrainz: cover art for %s" mbid)
+  (message "url: %s/release/%s" musicbrainz-coverart-api-url mbid)
+  (let ((response
+          (request-response-data
+           (request
+            (url-encode-url
+             (format "%s/release/%s" musicbrainz-coverart-api-url mbid))
+            :type "GET"
+            :header (list `("User-Agent" . ,musicbrainz-user-agent))
+            :parser 'json-read
+            :sync t
+            :success (cl-function
+                      (lambda (&key data &allow-other-keys)
+                        (message "ok")))))))
+    response))
+
+(defun musicbrainz-coverart-file-front (mbid)
+  "Get the MusicBrainz Cover Art front cover file for MBID."
+  (message "MusicBrainz: cover art (front) for %s" mbid)
+  (message "url: %s/release/%s/front" musicbrainz-coverart-api-url mbid)
+  (let ((response
+          (request-response-data
+           (request
+            (url-encode-url
+             (format "%s/release/%s/front" musicbrainz-coverart-api-url mbid))
+            :type "GET"
+            :header (list `("User-Agent" . ,musicbrainz-user-agent))
+            :sync t
+            :success (cl-function
+                      (lambda (&key data &allow-other-keys)
+                        (message "ok")))))))
+    response))
+
+(defun musicbrainz-coverart-file-back (mbid)
+  "Get the MusicBrainz Cover Art back cover file for MBID."
+  (message "MusicBrainz: cover art (back) for %s" mbid)
+  (message "url: %s/release/%s/back" musicbrainz-coverart-api-url mbid)
+  (let ((response
+          (request-response-data
+           (request
+            (url-encode-url
+             (format "%s/release/%s/back" musicbrainz-coverart-api-url mbid))
+            :type "GET"
+            :header (list `("User-Agent" . ,musicbrainz-user-agent))
+            :sync t
+            :success (cl-function
+                      (lambda (&key data &allow-other-keys)
+                        (message "ok")))))))
+    response))
+
+
 (provide 'musicbrainz)
 
 ;;; musicbrainz.el ends here
 (provide 'musicbrainz)
 
 ;;; musicbrainz.el ends here