From: Eric Gillespie Date: Sun, 4 Nov 2018 02:20:58 +0000 (-0700) Subject: Commit a bunch of state sitting around in the old bzr checkout! X-Git-Url: https://diplodocus.org/git/flac-archive/commitdiff_plain/bc10ac6298048de2f6c67c9d4d413a54352ccda9?hp=29d7234bd6c1853dc02c4e3c6c47c099bb1241a7 Commit a bunch of state sitting around in the old bzr checkout! 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 --- diff --git a/fa-flacd b/fa-flacd index 8166b94..5716223 100755 --- a/fa-flacd +++ b/fa-flacd @@ -1,4 +1,4 @@ -#! /usr/bin/python +#! /usr/bin/python2 """ =head1 NAME @@ -85,19 +85,12 @@ from errno import EEXIST, ENOENT 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: @@ -165,7 +158,12 @@ def flac(dir, tracknum, tags): 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: @@ -290,8 +288,11 @@ def flacloop(maxjobs): 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))) @@ -301,6 +302,12 @@ def flacloop(maxjobs): 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: diff --git a/fa-rip b/fa-rip index be1d5ca..6b72980 100755 --- a/fa-rip +++ b/fa-rip @@ -86,26 +86,31 @@ import os, re, sys, tempfile, time, traceback 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 +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 -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: - trackcount = disc.lastTrackNum + trackcount = len(disc.tracks) 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 @@ -115,14 +120,12 @@ def mkcue(disc, trackcount=None): 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)) - c(fp.close) - 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) - include = musicbrainz2.webservice.ReleaseIncludes(artist=True, tracks=True) - 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): - 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) @@ -261,6 +265,7 @@ def main(argv): 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) @@ -297,12 +302,17 @@ def main(argv): 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: - releases = releases_by_disc(disc.getId()) + releases = releases_by_disc(disc.id) 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 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 <> candidate-tags diff --git a/flac.c b/flac.c new file mode 100644 index 0000000..ed507ac --- /dev/null +++ b/flac.c @@ -0,0 +1,159 @@ +#include + +#include + +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); +}