X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/autoys/blobdiff_plain/3589c4a40f6610b6a8a3b36c71eb09b9e0e33616..2a236d3a90eb57b444f90c2881aa42ae06c5e0c3:/gremlin/gremlin.in diff --git a/gremlin/gremlin.in b/gremlin/gremlin.in old mode 100755 new mode 100644 index e32d084..0a76641 --- a/gremlin/gremlin.in +++ b/gremlin/gremlin.in @@ -7,18 +7,20 @@ ###----- Licensing notice --------------------------------------------------- ### -### This program is free software; you can redistribute it and/or modify +### This file is part of the `autoys' audio tools collection. +### +### `autoys' is free software; you can redistribute it and/or modify ### it under the terms of the GNU General Public License as published by ### the Free Software Foundation; either version 2 of the License, or ### (at your option) any later version. ### -### This program is distributed in the hope that it will be useful, +### `autoys' is distributed in the hope that it will be useful, ### but WITHOUT ANY WARRANTY; without even the implied warranty of ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ### GNU General Public License for more details. ### ### You should have received a copy of the GNU General Public License -### along with this program; if not, write to the Free Software Foundation, +### along with `autoys'; if not, write to the Free Software Foundation, ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ###-------------------------------------------------------------------------- @@ -39,11 +41,11 @@ import shutil as SH import optparse as OP import threading as TH import shlex as L -from math import sqrt +from math import sqrt, ceil from contextlib import contextmanager ## eyeD3 tag fettling. -import eyeD3 as E3 +import eyed3 as E3 ## Gstreamer. It picks up command-line arguments -- most notably `--help' -- ## and processes them itself. Of course, its help is completely wrong. This @@ -245,7 +247,7 @@ class ProgressEyecandy (object): ## Work out -- well, guess -- the time remaining. if cur: t = T.time() - eta = me._fmt_time((t - me._start)*(max - cur)/cur) + eta = me._fmt_time(ceil((t - me._start)*(max - cur)/cur)) else: eta = '???' @@ -409,6 +411,8 @@ class FormatParser (P.ParserElement): named format and its superclasses. """ + name = 'format-spec' + ## We cache the parser elements we generate to avoid enormous consing. CACHE = {} @@ -710,6 +714,14 @@ def make_element(factory, name = None, **props): elt.set_properties(**props) return elt +def link_elements(elts): + "Link the elements ELTS together, in order." + GS.element_link_many(*elts) + +def bin_children(bin): + "Iterate over the (direct) children of a BIN." + for elt in bin.elements(): yield elt + class GStreamerProgressEyecandy (ProgressEyecandy): """ Provide amusement while GStreamer is busy doing something. @@ -822,8 +834,8 @@ class AudioIdentifier (object): if pad.get_caps()[0].get_name().startswith('audio/'): elt.link_pads(pad.get_name(), sink, 'sink') dpaid = decoder.connect('pad-added', decoder_pad_arrived) - me._pipe.add(source, decoder, sink) - GS.element_link_many(source, decoder) + for i in [source, decoder, sink]: me._pipe.add(i) + link_elements([source, decoder]) ## Arrange to collect tags from the pipeline's bus as they're reported. ## If we reuse the pipeline later, we'll want different bus-message @@ -851,7 +863,7 @@ class AudioIdentifier (object): ## things from being too awful.) me.cap = None me.dcap = None - for e in decoder.elements(): + for e in bin_children(decoder): if e.get_factory().get_name() == 'typefind': tfelt = e break @@ -986,8 +998,8 @@ class AudioFormat (BaseFormat): """ elts = me.encoder_chain() bin = GS.Bin() - bin.add(*elts) - GS.element_link_many(*elts) + for i in elts: bin.add(i) + link_elements(elts) bin.add_pad(GS.GhostPad('sink', elts[0].get_pad('sink'))) bin.add_pad(GS.GhostPad('src', elts[-1].get_pad('src'))) return bin @@ -1023,9 +1035,9 @@ class AudioFormat (BaseFormat): convert = make_element('audioconvert', 'convert') encoder = me.encoder() sink = make_element('filesink', 'sink', location = new) - pipe.add(source, decoder, convert, encoder, sink) - GS.element_link_many(source, decoder) - GS.element_link_many(convert, encoder, sink) + for i in [source, decoder, convert, encoder, sink]: pipe.add(i) + link_elements([source, decoder]) + link_elements([convert, encoder, sink]) ## Some decoders (e.g., the AC3 decoder) include channel-position ## indicators in their output caps. The Vorbis encoder interferes with @@ -1105,8 +1117,8 @@ class OggVorbisFormat (AudioFormat): for q, br in me.QMAP: if br >= me.bitrate: break - else: - raise ValueError, 'no suitable quality setting found' + else: + raise ValueError, 'no suitable quality setting found' encprops['quality'] = q/10.0 return [make_element('vorbisenc', **encprops), make_element('oggmux')] @@ -1134,13 +1146,16 @@ class MP3Format (AudioFormat): GStreamer produces ID3v2 tags, but not ID3v1. This seems unnecessarily unkind to stupid players. """ - tag = E3.Tag() - tag.link(path) - tag.setTextEncoding(E3.UTF_8_ENCODING) - try: - tag.update(E3.ID3_V1_1) - except (UnicodeEncodeError, E3.tag.GenreException): - pass + f = E3.load(path) + if f is None: return + t = f.tag + if t is None: return + for v in [E3.id3.ID3_V2_3, E3.id3.ID3_V1]: + try: f.tag.save(version = v) + except (UnicodeEncodeError, + E3.id3.GenreException, + E3.id3.TagException): + pass defformat('mp3', MP3Format) @@ -1498,8 +1513,9 @@ def grobble(master, targets, noact = False): ## the appropriate categories. Later, we'll apply policy to the ## files, by category, and work out what to do with them all. else: - gf = GIO.File(masterfile) - mime = gf.query_info('standard::content-type').get_content_type() + mime = GIO.File(masterfile) \ + .query_info('standard::content-type') \ + .get_content_type() cats = [] for cat in pmap.iterkeys(): id = cat.identify(masterfile, mime)