1 # helpers.py: functions to interpret coder program output.
2 # mp3togo Portable Music Manager
4 # Copyright 2005: Simeon Veldstra <reallifesim@gmail.com>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
19 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 # ***********************************************************
22 # The code to parse output from external programs is based on
23 # the jack CD ripping program by Arne Zellentin.
25 # 'jack' is responsible for my full hard disks
26 # and has inspired me to produce this program.
27 # Thanks for everything Arne.
33 import mp3togo.conf as conf
41 def parse_ogg123(buf):
44 sum = float(t.split(':')[0]) * 60
45 sum += float(t.split(':')[1])
48 if l.startswith('Time') and l.endswith('% '):
50 return sumtime(line[1])/sumtime(line[4]) * 100.0
53 def parse_mpg321(buf, f=frames()):
62 if y0 != -1 and y1 != -1:
64 f.tframes = float(s[y0+1:y1])
69 r = float(s.split()[1])
73 f.tframes = f.frames = 0
76 return f.frames/f.tframes * 100.0
79 def parse_oggenc(buf):
88 if y0 != -1 and y1 != -1:
89 percent = float(s[y0 + 1:y1])
95 # originaly from "jack"
99 if len(s) == 1: s=s[0]
100 if s.find("%") >= 0: # status reporting starts here
102 y1 = y[1].split("(")[0]
103 percent = float(y[0]) / float(y1) * 100.0
104 elif s.find("Frame:") >= 0: # older versions, like 3.13
106 y0 = y[0].split("[")[-1]
107 y1 = y[1].split("]")[0]
108 percent = float(y0) / float(y1) * 100.0
113 def parse_flac_enc(buf):
116 if len (s) >= 2: s = s[-2]
117 if len (s) == 1: s = s[0]
120 if y0 != -1 and y1 != -1:
121 return float(s[y0 + 1:y1])
125 def parse_flac_dec(buf):
126 # I wrote this one myself
127 buf = buf.split('\r')
129 buf = buf.replace('%', '')
131 return int(buf.split()[1])
135 ### wav file "encoder/decoder"
136 def recode_wav(input, output, args=None):
137 """Factory returns function to copy wav file
139 Returned function takes no args and copies
140 input to output. Throws OSError on error."""
141 return lambda: shutil.copyfile(input, output)
143 ## Command line escape sequences:
146 # ---------------------
153 'oggenc' : {'parser': parse_oggenc,
154 'cmd': 'oggenc %a -o %o %i',
157 'lame' : {'parser': parse_lame,
158 'cmd': 'lame --nohist %a %i %o',
161 'flac_enc':{'parser': parse_flac_enc,
162 'cmd': 'flac ???????',
165 'wav_enc': {'parser': None,
169 'ogg123' : {'parser': parse_ogg123,
170 'cmd': 'ogg123 -d wav -f %o %i',
173 'mpg321' : {'parser': parse_mpg321,
174 'cmd': 'mpg321 -v -w %o %i',
177 'flac_dec':{'parser': parse_flac_dec,
178 'cmd': 'flac --decode -F -o %o %i',
181 'wav_dec': {'parser': None,
188 def find_helper(type, action):
189 """Return the name of the helper that performs action on type
191 Raises KeyError if type or action is unknown."""
192 return dict([(helpers[x]['type'], x)
193 for x in helpers.keys()
194 if helpers[x]['action'] == action]
197 def make_args(helper, input, output, args=''):
198 """Substitute for command line args"""
199 esc = {'z': '%', 'i': "###input###", 'o': "###output###", 'a': args}
201 fmt = helpers[helper]['cmd']
202 fmt = fmt.replace('%%', '%z')
209 code = fmt[0] and fmt[0][0]
210 if code in esc.keys():
211 fmt[0] = esc[code] + fmt[0][1:]
213 raise conf.ErrorBadFormat
215 if "###input###" in out:
216 out[out.index("###input###")] = input
217 if "###output###" in out:
218 out[out.index("###output###")] = output
221 def est_decoded_size(filename):
222 # This could be much better
223 tp = conf.getfiletype(filename)
224 factors = {'mp3': 16.5, 'ogg': 16.5, 'flac': 2.8, 'wav': 1}
225 return os.stat(filename).st_size * factors[tp]