-#! /usr/bin/python
+#! /usr/bin/python2
"""
=head1 NAME
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:
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:
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('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:
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
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,
tags_file('candidate-tags-0', trackcount, False)
- include = musicbrainz2.webservice.ReleaseIncludes(artist=True, tracks=True)
-
i = 0
for release in releases:
i += 1
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)
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)
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:
--- /dev/null
+#!/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
--- /dev/null
+#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);
+}