Mercurial > ~darius > hgwebdir.cgi > amakode
changeset 4:65a9f99302cd
Incorporate changes from Jens Zurheide <jens.zurheide@gmx.de> to read tags
from the source file and add them to the one being written.
Appears to work fine, however it should be optional. (ie work without tagpy
just not write tags)
author | darius@inchoate.localdomain |
---|---|
date | Mon, 12 Nov 2007 15:01:23 +1030 |
parents | de86a9e19151 |
children | f11c5ed0178e |
files | amakode.py |
diffstat | 1 files changed, 92 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/amakode.py Mon Nov 12 14:52:41 2007 +1030 +++ b/amakode.py Mon Nov 12 15:01:23 2007 +1030 @@ -2,13 +2,25 @@ ############################################################################ # Transcoder for Amarok -# (c) 2007 Daniel O'Connor <darius@dons.net.au> +# - Add support for tagging (jens.zurheide@gmx.de) +# - Fixed typo in lame encoder (tcuya from kde-apps.org) +# - Made setting maxjobs easier, although Amarok doesn't appear to issue +# multiple requests :( # # Depends on: Python 2.2 +# tagpy (optional) +# +# The only user servicable parts are the encode/decode (line 103) and the +# number of concurrent jobs to run (line 225) +# +# The optional module tagpy (http://news.tiker.net/software/tagpy) is used +# for tag information processing. This allows for writing tags into the +# transcoded files. # ############################################################################ # # Copyright (C) 2007 Daniel O'Connor. All rights reserved. +# Copyright (C) 2007 Jens Zurheide. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -33,6 +45,8 @@ # ############################################################################ +__version__ = "1.3" + import ConfigParser import os import sys @@ -46,8 +60,35 @@ import urllib import urlparse import re +import tagpy -class QueueMgr: +class tagpywrap(dict): + textfields = ['album', 'artist', 'title', 'comment', 'genre'] + numfields = ['year', 'track'] + allfields = textfields + numfields + + def __init__(self, url): + f = urllib.urlopen(url) + + self.tagInfo = tagpy.FileRef(f.fp.name).tag() + f.close() + + self['album'] = self.tagInfo.album.strip() + self['artist'] = self.tagInfo.artist.strip() + self['title'] = self.tagInfo.title.strip() + self['comment'] = self.tagInfo.comment.strip() + self['year'] = self.tagInfo.year + self['genre'] = self.tagInfo.genre.strip() + self['track'] = self.tagInfo.track + for i in self.textfields: + if (self[i] == ""): + del self[i] + + for i in self.numfields: + if (self[i] == 0): + del self[i] + +class QueueMgr(object): queuedjobs = [] activejobs = [] @@ -86,7 +127,7 @@ """ Returns true if both queues are empty """ return(len(self.queuedjobs) == 0 and len(self.activejobs) == 0) -class TranscodeJob: +class TranscodeJob(object): # Programs used to decode (to a wav stream) decode = {} decode["mp3"] = ["mpg123", "-w", "-", "-"] @@ -100,9 +141,20 @@ encode = {} encode["mp3"] = ["lame", "--abr", "128", "-", "-"] encode["ogg"] = ["oggenc", "-q", "2", "-"] - encode["mp4"] = ["faac", "-o", "/dev/stdout", "-"] + encode["mp4"] = ["faac", "-wo", "/dev/stdout", "-"] encode["m4a"] = encode["mp4"] - encode["flac"] = ["flac", "-c", "-"] + + # XXX: can't encode flac - it's wav parser chokes on mpg123's output, it does work + # OK if passed through sox but we can't do that. If you really want flac modify + # the code & send me a diff or write a wrapper shell script :) + #encode["flac"] = ["flac", "-c", "-"] + + # Options for output programs to store ID3 tag information + tagopt = {} + tagopt["mp3"] = { "album" : "--tl", "artist" : "--ta", "title" : "--tt", "track" : "--tn" } + tagopt["ogg"] = { "album" : "-l", "artist" : "-a", "title" : "-a", "track" : "-N" } + tagopt["mp4"] = { "album" : "--album", "artist" : "--artist", "title" : "--title", "track" : "--track" } + #tagopt["flac"] = { "album" : "-Talbum=%s", "artist" : "-Tartist=%s", "title" : "-Ttitle=%s", "track" : "-Ttracknumber=%s" } def __init__(self, _inurl, _tofmt): self.errormsg = None @@ -133,8 +185,39 @@ self.outurl = urlparse.urlunsplit(["file", None, self.outfname, None, None]) log.debug("Outputting to " + self.outfname + " " + self.outurl + ")") log.debug("Errors to " + self.errfname) - self.decoder = subprocess.Popen(self.decode[self.inext], stdin=self.inputfile, stdout=subprocess.PIPE, stderr=self.errfd) - self.encoder = subprocess.Popen(self.encode[self.tofmt], stdin=self.decoder.stdout, stdout=self.outfd, stderr=self.errfd) + + # assemble command line for encoder + encoder = [] + encoder += self.encode[self.tofmt] + + try: + if (self.tofmt in self.tagopt): + taginfo = tagpywrap(self.inurl) + for f in taginfo.allfields: + if (f in taginfo and f in self.tagopt[self.tofmt]): + inf = taginfo[f] + opt = self.tagopt[self.tofmt][f] + log.debug(" %s = %s %s" % (f, opt, inf)) + # If we have a substitution, make it. If + # not append the info as a separate + # arg. Note that the tag options are + # passed in as the second option because a + # lot of programs don't parse options + # after their file list. + if ('%s' in opt): + opt = opt.replace('%s', inf) + encoder.insert(1, opt) + else: + encoder.insert(1, opt) + encoder.insert(2, inf) + finally: + pass + + log.debug("decoder -> " + str(self.decode[self.inext])) + log.debug("encoder -> " + str(encoder)) + self.decoder = subprocess.Popen(self.decode[self.inext], stdin=self.inputfile, stdout=subprocess.PIPE, stderr=self.errfh) + self.encoder = subprocess.Popen(encoder, stdin=self.decoder.stdout, stdout=self.outfd, stderr=self.errfh) + log.debug("Processes connected") except Exception, e: log.debug("Failed to start - " + str(e)) self.errormsg = str(e) @@ -167,7 +250,7 @@ ############################################################################ # amaKode ############################################################################ -class amaKode: +class amaKode(object): """ The main application""" def __init__(self, args): @@ -290,6 +373,7 @@ signal.signal(signal.SIGHUP, onStop) signal.signal(signal.SIGTERM, onStop) if 1: + # Run normal application app = amaKode(sys.argv) else: # Quick test case