]> diplodocus.org Git - flac-archive/commitdiff
Commit a bunch of state sitting around in the old bzr checkout!
authorEric Gillespie <epg@pretzelnet.org>
Sun, 4 Nov 2018 02:20:58 +0000 (19:20 -0700)
committerEric Gillespie <epg@pretzelnet.org>
Sun, 4 Nov 2018 02:20:58 +0000 (19:20 -0700)
I sent some of what's in here to a old-bzr branch.  I think this was an
older copy of what evolved on my laptop, and then I started hacking
on top of this again on another computer running FreeBSD, what a mess...

Because of that, some of this may be going backwards (e.g. dependent on
my horrible old utility library I hacked out at some point (see old-bzr)).

-rwxr-xr-x  1 epg  epg    395 Jul 16  2016 fa-rip.sh
-rwxr-xr-x  1 epg  epg  12025 May 19  2016 fa-flacd
-rwxr-xr-x  1 epg  epg   9962 May 18  2016 fa-rip

fa-flacd
fa-rip
fa-rip.sh [new file with mode: 0755]
flac.c [new file with mode: 0644]

index 8166b94..5716223 100755 (executable)
--- a/fa-flacd
+++ b/fa-flacd
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/python2
 
 """
 =head1 NAME
 
 """
 =head1 NAME
@@ -85,19 +85,12 @@ from errno import EEXIST, ENOENT
 from glob import glob
 from optparse import OptionParser
 
 from glob import glob
 from optparse import OptionParser
 
-from flac_archive.tags import Tags
+import org.diplodocus.jobs
+from org.diplodocus.structures import ListDictDict
+from org.diplodocus.util import die, flatten, nothing
+from org.diplodocus.util import catch_EnvironmentError as c
 
 
-def c(f, *args):
-    try:
-        return f(*args)
-    except EnvironmentError, error:
-        error.msg = '%s.%s(%s): ' % (f.__module__, f.__name__,
-                                     ', '.join(map(str, args)))
-        raise
-
-def die(e, *args):
-    sys.stderr.write(''.join(args))
-    sys.exit(e)
+from flac_archive.tags import Tags
 
 def spew(*args):
     if verbose:
 
 def spew(*args):
     if verbose:
@@ -165,7 +158,12 @@ def flac(dir, tracknum, tags):
         run_flac('wav', 'cue', '/'.join(['..', artist, outfile]), tags.all())
         files = ['%s/%s.flac' % (artist, outfile)]
 
         run_flac('wav', 'cue', '/'.join(['..', artist, outfile]), tags.all())
         files = ['%s/%s.flac' % (artist, outfile)]
 
-        c(os.unlink, 'cue')
+        try:
+            c(os.unlink, 'cue')
+        except EnvironmentError, error:
+            if error.errno != ENOENT:
+                raise error
+
         outlog = '/'.join(['..', artist, outfile + '.log'])
         c(os.rename, 'log', outlog)
     else:
         outlog = '/'.join(['..', artist, outfile + '.log'])
         c(os.rename, 'log', outlog)
     else:
@@ -290,8 +288,11 @@ def flacloop(maxjobs):
                     return 1
             return lamb
 
                     return 1
             return lamb
 
-    while True:
-        status = getjob(lambda *a,**k: None)()
+    def notify_start(pid, jobs):
+        # make this print '2 jobs; start 378 for Artist/01 Title.flac'
+        spew('%d jobs; start %d for %s\n' % (len(jobs), pid, dir[0]))
+
+    def notify_finish(pid, status, jobs):
         spew('%d jobs; %d finished (' % (len(jobs), pid))
         if os.WIFEXITED(status):
             spew('exited with status ', str(os.WEXITSTATUS(status)))
         spew('%d jobs; %d finished (' % (len(jobs), pid))
         if os.WIFEXITED(status):
             spew('exited with status ', str(os.WEXITSTATUS(status)))
@@ -301,6 +302,12 @@ def flacloop(maxjobs):
             spew('stopped with signal ', str(os.WSTOPSIG(status)))
         spew(')\n')
 
             spew('stopped with signal ', str(os.WSTOPSIG(status)))
         spew(')\n')
 
+    # Never returns (see getjob comment).
+    org.diplodocus.jobs.run(maxjobs=maxjobs, debug=debug,
+                            get_job=getjob,
+                            notify_start=notify_start,
+                            notify_finish=notify_finish)
+
 def main(argv):
     # Control the exit code for any uncaught exceptions.
     try:
 def main(argv):
     # Control the exit code for any uncaught exceptions.
     try:
diff --git a/fa-rip b/fa-rip
index be1d5ca..6b72980 100755 (executable)
--- a/fa-rip
+++ b/fa-rip
@@ -86,26 +86,31 @@ import os, re, sys, tempfile, time, traceback
 from optparse import OptionParser
 import urllib
 
 from optparse import OptionParser
 import urllib
 
-import musicbrainz2.disc
-import musicbrainz2.webservice
+import discid.disc
+import musicbrainzngs.musicbrainz
 
 from org.diplodocus.util import catch_EnvironmentError as c
 
 
 from org.diplodocus.util import catch_EnvironmentError as c
 
+musicbrainzngs.musicbrainz.set_useragent(
+    'flac-archive', '0.1', 'https://diplodocus.org/git/flac-archive')
+
+#import logging
+#logging.basicConfig(level=logging.DEBUG)
+
 # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=439790
 MSF_OFFSET = 150
 
 # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=439790
 MSF_OFFSET = 150
 
-def mkcue(disc, trackcount=None):
-    fp = c(file, 'cue', 'w')
+def mkcue(fp, disc, trackcount=None):
     c(fp.write, 'FILE "dummy.wav" WAVE\n')
 
     if trackcount == None:
     c(fp.write, 'FILE "dummy.wav" WAVE\n')
 
     if trackcount == None:
-        trackcount = disc.lastTrackNum
+        trackcount = len(disc.tracks)
     else:
     else:
-        trackcount = min(trackcount, disc.lastTrackNum)
+        trackcount = min(trackcount, len(disc.tracks))
 
 
-    for i in xrange(disc.firstTrackNum, trackcount+1):
-        offset = disc.tracks[i-1][0]
-        offset -= MSF_OFFSET
+    for i in xrange(1, trackcount+1):
+        track = disc.tracks[i-1]
+        offset = track.offset - MSF_OFFSET
 
         minutes = seconds = 0
         sectors = offset % 75
 
         minutes = seconds = 0
         sectors = offset % 75
@@ -115,14 +120,12 @@ def mkcue(disc, trackcount=None):
                 minutes = seconds / 60
                 seconds = seconds % 60
 
                 minutes = seconds / 60
                 seconds = seconds % 60
 
-        c(fp.write, '  TRACK %02d AUDIO\n' % (i,))
+        c(fp.write, '  TRACK %02d AUDIO\n' % (track.number,))
         if i == 1 and offset > 0:
             c(fp.write, '    INDEX 00 00:00:00\n')
         c(fp.write,
           '    INDEX 01 %02d:%02d:%02d\n' % (minutes, seconds, sectors))
 
         if i == 1 and offset > 0:
             c(fp.write, '    INDEX 00 00:00:00\n')
         c(fp.write,
           '    INDEX 01 %02d:%02d:%02d\n' % (minutes, seconds, sectors))
 
-    c(fp.close)
-
     return trackcount
 
 def tags_file(fn, trackcount, various, artist=None, album=None,
     return trackcount
 
 def tags_file(fn, trackcount, various, artist=None, album=None,
@@ -173,8 +176,6 @@ def tags(releases, trackcount):
 
     tags_file('candidate-tags-0', trackcount, False)
 
 
     tags_file('candidate-tags-0', trackcount, False)
 
-    include = musicbrainz2.webservice.ReleaseIncludes(artist=True, tracks=True)
-
     i = 0
     for release in releases:
         i += 1
     i = 0
     for release in releases:
         i += 1
@@ -240,8 +241,11 @@ def get_releases(filter_, tries=5):
             time.sleep(sleep)
 
 def releases_by_disc(disc_id):
             time.sleep(sleep)
 
 def releases_by_disc(disc_id):
-    filter_ = musicbrainz2.webservice.ReleaseFilter(discId=disc_id)
-    return (result.release for result in get_releases(filter_))
+    try:
+        musicbrainzngs.musicbrainz.get_releases_by_discid(disc_id)
+    except musicbrainzngs.musicbrainz.ResponseError:
+        return []
+    raise 'what now'
 
 def releases_by(q, title, artist=None):
     filter_ = musicbrainz2.webservice.ReleaseFilter(title=title)
 
 def releases_by(q, title, artist=None):
     filter_ = musicbrainz2.webservice.ReleaseFilter(title=title)
@@ -261,6 +265,7 @@ def main(argv):
         parser.add_option('--artist')
         parser.add_option('--discid')
         parser.add_option('--title')
         parser.add_option('--artist')
         parser.add_option('--discid')
         parser.add_option('--title')
+        parser.add_option('--print-discid', action='store_true', default=False)
         parser.add_option('-d', '--device')
         parser.add_option('-m', '--no-musicbrainz',
                           action='store_true', default=False)
         parser.add_option('-d', '--device')
         parser.add_option('-m', '--no-musicbrainz',
                           action='store_true', default=False)
@@ -297,12 +302,17 @@ def main(argv):
         elif options.discid != None:
             tags(releases_by_disc(options.discid), trackcount)
         else:
         elif options.discid != None:
             tags(releases_by_disc(options.discid), trackcount)
         else:
-            disc = musicbrainz2.disc.readDisc(device)
-            trackcount = mkcue(disc, trackcount)
+            disc = discid.disc.read(device)
+            if options.print_discid:
+                print disc.id
+                return 0
+            fp = c(file, 'cue', 'w')
+            trackcount = mkcue(fp, disc, trackcount)
+            c(fp.close)
             if options.no_musicbrainz:
                 releases = []
             else:
             if options.no_musicbrainz:
                 releases = []
             else:
-                releases = releases_by_disc(disc.getId())
+                releases = releases_by_disc(disc.id)
             tags(releases, trackcount)
             rip(device, trackcount, options.single_file)
     except Exception, error:
             tags(releases, trackcount)
             rip(device, trackcount, options.single_file)
     except Exception, error:
diff --git a/fa-rip.sh b/fa-rip.sh
new file mode 100755 (executable)
index 0000000..75c94d8
--- /dev/null
+++ b/fa-rip.sh
@@ -0,0 +1,25 @@
+#!/bin/ksh93
+
+set -e
+
+d=$(mktemp -d flac-archive.XXXXXX)
+st=$?
+if (( st != 0 )); then
+    print -u2 "mktemp -d exited $st"
+    exit $st
+fi
+if [[ -z $d ]]; then
+    print -u2 'mktemp -d did not give directory'
+    exit 2
+fi
+
+print -- $d
+cd $d
+cdparanoia -B
+cat > candidate-tags <<EOF
+ARTIST=
+ALBUM=
+DATE=
+EOF
+ls track*.cdda.wav | sed 's/track0*/TITLE[/; s/\.cdda\.wav/]=/' \
+   >> candidate-tags
diff --git a/flac.c b/flac.c
new file mode 100644 (file)
index 0000000..ed507ac
--- /dev/null
+++ b/flac.c
@@ -0,0 +1,159 @@
+#include <FLAC/metadata.h>
+
+#include <Python.h>
+
+static PyObject *flac_error;
+
+static PyObject *
+flac_pictures(char *fn)
+{
+    FLAC__Metadata_Chain *chain;
+    FLAC__Metadata_Iterator *iterator;
+    FLAC__StreamMetadata *block;
+    PyObject *description, *tuple, *list;
+
+    chain = FLAC__metadata_chain_new();
+    if (chain == NULL) {
+        return PyErr_NoMemory();
+    }
+
+    if(!FLAC__metadata_chain_read(chain, fn)) {
+        PyObject *s = PyString_FromFormat("metadata_chain_read (%d)",
+                                          FLAC__metadata_chain_status(chain));
+        if (s != NULL) {
+            PyErr_SetObject(flac_error, s);
+        }
+        return NULL;
+    }
+
+    iterator = FLAC__metadata_iterator_new();
+    if (iterator == NULL) {
+        return PyErr_NoMemory();
+    }
+
+    FLAC__metadata_iterator_init(iterator, chain);
+
+    list = PyList_New(0);
+    if (list == NULL) {
+        return NULL;
+    }
+
+    do {
+        /* This can fail, but the documentation doesn't say how, why,
+         * or how to react.  metaflac/operations.c just prints a
+         * useless error message and keeps going. */
+        block = FLAC__metadata_iterator_get_block(iterator);
+        if (block == NULL) {
+            PyErr_SetString(flac_error,
+                            "metadata_iterator_get_block returned NULL");
+            return NULL;
+        }
+
+        if (block->type != FLAC__METADATA_TYPE_PICTURE) {
+            continue;
+        }
+
+        description = PyUnicode_DecodeUTF8(
+            (const char *)block->data.picture.description,
+            strlen((const char *)block->data.picture.description),
+            "strict");
+        if (description == NULL) {
+            return NULL;
+        }
+
+        tuple = Py_BuildValue("(isOiiiis#)",
+                              block->data.picture.type,
+                              block->data.picture.mime_type,
+                              description,
+                              block->data.picture.width,
+                              block->data.picture.height,
+                              block->data.picture.depth,
+                              block->data.picture.colors,
+                              block->data.picture.data,
+                              block->data.picture.data_length);
+        if (tuple == NULL) {
+            return NULL;
+        }
+
+        if (PyList_Append(list, tuple) == -1) {
+            return NULL;
+        }
+    } while(FLAC__metadata_iterator_next(iterator));
+
+    FLAC__metadata_iterator_delete(iterator);
+    FLAC__metadata_chain_delete(chain);
+
+    return list;
+}
+
+static PyObject *
+get_pictures(PyObject *self, PyObject *args)
+{
+    char *fn;
+
+    if (!PyArg_ParseTuple(args, "s", &fn)) {
+        return NULL;
+    }
+
+    return flac_pictures(fn);
+}
+
+static
+PyMethodDef methods[] = {
+    {"get_pictures", get_pictures, METH_VARARGS,
+     "document me"},
+
+    {NULL, NULL, 0, NULL}
+};
+
+static void
+export_constants(PyObject *m)
+{
+    PyObject *n;
+
+#define foo(x) \
+    n = PyInt_FromLong(FLAC__STREAM_METADATA_ ## x); \
+    if (n == NULL || PyModule_AddObject(m, #x, n) == -1) return;
+
+    foo(PICTURE_TYPE_OTHER);
+    foo(PICTURE_TYPE_FILE_ICON_STANDARD);
+    foo(PICTURE_TYPE_FILE_ICON);
+    foo(PICTURE_TYPE_FRONT_COVER);
+    foo(PICTURE_TYPE_BACK_COVER);
+    foo(PICTURE_TYPE_LEAFLET_PAGE);
+    foo(PICTURE_TYPE_MEDIA);
+    foo(PICTURE_TYPE_LEAD_ARTIST);
+    foo(PICTURE_TYPE_ARTIST);
+    foo(PICTURE_TYPE_CONDUCTOR);
+    foo(PICTURE_TYPE_BAND);
+    foo(PICTURE_TYPE_COMPOSER);
+    foo(PICTURE_TYPE_LYRICIST);
+    foo(PICTURE_TYPE_RECORDING_LOCATION);
+    foo(PICTURE_TYPE_DURING_RECORDING);
+    foo(PICTURE_TYPE_DURING_PERFORMANCE);
+    foo(PICTURE_TYPE_VIDEO_SCREEN_CAPTURE);
+    foo(PICTURE_TYPE_FISH);
+    foo(PICTURE_TYPE_ILLUSTRATION);
+    foo(PICTURE_TYPE_BAND_LOGOTYPE);
+    foo(PICTURE_TYPE_PUBLISHER_LOGOTYPE);
+    foo(PICTURE_TYPE_UNDEFINED);
+
+#undef foo
+}
+
+PyMODINIT_FUNC
+initflac(void)
+{
+    PyObject *m = Py_InitModule("flac", methods);
+    if (m == NULL) {
+        return;
+    }
+
+    flac_error = PyErr_NewException("flac_archive.flac.error", NULL, NULL);
+    if (flac_error == NULL) {
+        return;
+    }
+    PyModule_AddObject(m, "error", flac_error);
+
+    export_constants(m);
+}