Index: interfaces/python/gen_pyobject.py
===================================================================
--- interfaces/python/gen_pyobject.py	(revision 9b1e101b91b813ae0a8cde6b84408dca1347d79e)
+++ interfaces/python/gen_pyobject.py	(revision 0b2892fa076aea21f128617f7d21b826f53797a8)
@@ -18,4 +18,8 @@
 maintaining this bizarre file.
 """
+
+param_numbers = {
+  'source': [0, 2],
+}
 
 # TODO
@@ -81,18 +85,19 @@
 # move into the C library at some point.
 defaultsizes = {
-    'resampler':    'input->length * self->ratio',
-    'specdesc':     '1',
-    'onset':        '1',
-    'pitchyin':     '1',
-    'pitchyinfft':  '1',
-    'pitchschmitt': '1',
-    'pitchmcomb':   '1',
-    'pitchfcomb':   '1',
-    'pitch':        '1',
-    'tss':          'self->hop_size',
-    'mfcc':         'self->n_coeffs',
-    'beattracking': 'self->hop_size',
-    'tempo':        '1',
-    'peakpicker':   '1',
+    'resampler':    ['input->length * self->ratio'],
+    'specdesc':     ['1'],
+    'onset':        ['1'],
+    'pitchyin':     ['1'],
+    'pitchyinfft':  ['1'],
+    'pitchschmitt': ['1'],
+    'pitchmcomb':   ['1'],
+    'pitchfcomb':   ['1'],
+    'pitch':        ['1'],
+    'tss':          ['self->hop_size', 'self->hop_size'],
+    'mfcc':         ['self->n_coeffs'],
+    'beattracking': ['self->hop_size'],
+    'tempo':        ['1'],
+    'peakpicker':   ['1'],
+    'source':       ['self->hop_size', '1'],
 }
 
@@ -123,4 +128,5 @@
     'ratio': '0.5',
     'method': '"default"',
+    'uri': '"none"',
     }
 
@@ -146,4 +152,5 @@
     'cvec_t*': 'PyAubio_CCvecToPyCvec',
     'smpl_t': 'PyFloat_FromDouble',
+    'uint_t*': 'PyInt_FromLong',
 }
 
@@ -257,4 +264,70 @@
     return s
 
+def gen_do_input_params(inputparams):
+  inputdefs = ''
+  parseinput = ''
+  inputrefs = ''
+  inputvecs = ''
+  pytypes = ''
+
+  if len(inputparams):
+    # build the parsing string for PyArg_ParseTuple
+    pytypes = "".join([aubio2pytypes[p['type']] for p in inputparams])
+
+    inputdefs = "/* input vectors python prototypes */\n  "
+    inputdefs += "\n  ".join(["PyObject * " + p['name'] + "_obj;" for p in inputparams])
+
+    inputvecs = "/* input vectors prototypes */\n  "
+    inputvecs += "\n  ".join(map(lambda p: p['type'] + ' ' + p['name'] + ";", inputparams))
+
+    parseinput = "/* input vectors parsing */\n  "
+    for p in inputparams:
+        inputvec = p['name']
+        inputdef = p['name'] + "_obj"
+        converter = aubiovecfrompyobj[p['type']]
+        parseinput += """%(inputvec)s = %(converter)s (%(inputdef)s);
+
+  if (%(inputvec)s == NULL) {
+    return NULL;
+  }""" % locals()
+
+    # build the string for the input objects references
+    inputrefs = ", ".join(["&" + p['name'] + "_obj" for p in inputparams])
+    # end of inputs strings
+  return inputdefs, parseinput, inputrefs, inputvecs, pytypes
+
+def gen_do_output_params(outputparams, name):
+  outputvecs = ""
+  outputcreate = ""
+  if len(outputparams):
+    outputvecs = "  /* output vectors prototypes */\n"
+    for p in outputparams:
+      params = {
+        'name': p['name'], 'pytype': p['type'], 'autype': p['type'][:-3],
+        'length': defaultsizes[name].pop(0) }
+      if (p['type'] == 'uint_t*'):
+        outputvecs += '  uint_t' + ' ' + p['name'] + ";\n"
+        outputcreate += "  %(name)s = 0;\n" % params
+      else:
+        outputvecs += "  " + p['type'] + ' ' + p['name'] + ";\n"
+        outputcreate += "  /* creating output %(name)s as a new_%(autype)s of length %(length)s */\n" % params
+        outputcreate += "  %(name)s = new_%(autype)s (%(length)s);\n" % params
+
+  returnval = "";
+  if len(outputparams) > 1:
+    returnval += "  PyObject *outputs = PyList_New(0);\n"
+    for p in outputparams:
+      returnval += "  PyList_Append( outputs, (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" +");\n"
+    returnval += "  return outputs;"
+  elif len(outputparams) == 1:
+    if defaultsizes[name] == '1':
+      returnval += "  return (PyObject *)PyFloat_FromDouble(" + p['name'] + "->data[0])"
+    else:
+      returnval += "  return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")"
+  else:
+    returnval = "  return Py_None;";
+  # end of output strings
+  return outputvecs, outputcreate, returnval
+
 def gen_do(dofunc, name):
     funcname = dofunc.split()[1].split('(')[0]
@@ -265,73 +338,37 @@
     # and remove it
     doparams = doparams[1:]
-    # guess the input/output params, assuming we have less than 3
-    assert len(doparams) > 0, \
-        "no parameters for function do in object %s" % name
-    #assert (len(doparams) <= 2), \
-    #    "more than 3 parameters for do in object %s" % name
-
-    # build strings for inputs, assuming there is only one input 
-    inputparams = [doparams[0]]
-    # build the parsing string for PyArg_ParseTuple
-    pytypes = "".join([aubio2pytypes[p['type']] for p in doparams[0:1]])
-
-    inputdefs = "/* input vectors python prototypes */\n  "
-    inputdefs += "\n  ".join(["PyObject * " + p['name'] + "_obj;" for p in inputparams])
-
-    inputvecs = "/* input vectors prototypes */\n  "
-    inputvecs += "\n  ".join(map(lambda p: p['type'] + ' ' + p['name'] + ";", inputparams))
-
-    parseinput = "/* input vectors parsing */\n  "
-    for p in inputparams:
-        inputvec = p['name']
-        inputdef = p['name'] + "_obj"
-        converter = aubiovecfrompyobj[p['type']]
-        parseinput += """%(inputvec)s = %(converter)s (%(inputdef)s);
-
-  if (%(inputvec)s == NULL) {
-    return NULL;
-  }""" % locals()
-
-    # build the string for the input objects references
-    inputrefs = ", ".join(["&" + p['name'] + "_obj" for p in inputparams])
-    # end of inputs strings
+
+    n_param = len(doparams)
+
+    if name in param_numbers.keys():
+      n_input_param, n_output_param = param_numbers[name]
+    else:
+      n_input_param, n_output_param = 1, n_param - 1
+
+    assert n_output_param + n_input_param == n_param, "n_output_param + n_input_param != n_param for %s" % name
+
+    inputparams = doparams[:n_input_param]
+    outputparams = doparams[n_input_param:n_input_param + n_output_param]
+
+    inputdefs, parseinput, inputrefs, inputvecs, pytypes = gen_do_input_params(inputparams);
+    outputvecs, outputcreate, returnval = gen_do_output_params(outputparams, name)
 
     # build strings for outputs
-    outputparams = doparams[1:]
-    if len(outputparams) >= 1:
-        #assert len(outputparams) == 1, \
-        #    "too many output parameters"
-        outputvecs = "\n  /* output vectors prototypes */\n  "
-        outputvecs += "\n  ".join([p['type'] + ' ' + p['name'] + ";" for p in outputparams])
-        params = {
-          'name': p['name'], 'pytype': p['type'], 'autype': p['type'][:-3],
-          'length': defaultsizes[name]}
-        outputcreate = "\n  ".join(["""/* creating output %(name)s as a new_%(autype)s of length %(length)s */""" % \
-            params for p in outputparams]) 
-        outputcreate += "\n"
-        outputcreate += "\n  ".join(["""  %(name)s = new_%(autype)s (%(length)s);""" % \
-            params for p in outputparams]) 
-        returnval = ""
-        if len(outputparams) > 1:
-            returnval += "PyObject *outputs = PyList_New(0);\n"
-            for p in outputparams:
-                returnval += "  PyList_Append( outputs, (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" +");\n"
-            returnval += "  return outputs;"
-        else:
-            if defaultsizes[name] == '1':
-                returnval += "return (PyObject *)PyFloat_FromDouble(" + p['name'] + "->data[0])"
-            else:
-                returnval += "return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")"
+    # build the parameters for the  _do() call
+    doparams_string = "self->o"
+    for p in doparams:
+      if p['type'] == 'uint_t*':
+        doparams_string += ", &" + p['name']
+      else:
+        doparams_string += ", " + p['name']
+
+    if n_input_param:
+      arg_parse_tuple = """\
+  if (!PyArg_ParseTuple (args, "%(pytypes)s", %(inputrefs)s)) {
+    return NULL;
+  }
+""" % locals()
     else:
-        # no output
-        outputvecs = ""
-        outputcreate = ""
-        #returnval = "Py_None";
-        returnval = "return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")"
-    # end of output strings
-
-    # build the parameters for the  _do() call
-    doparams_string = "self->o, " + ", ".join([p['name'] for p in doparams])
-
+      arg_parse_tuple = ""
     # put it all together
     s = """\
@@ -340,20 +377,18 @@
 Py_%(name)s_do(Py_%(name)s * self, PyObject * args)
 {
-  %(inputdefs)s
-  %(inputvecs)s
-  %(outputvecs)s
-
-  if (!PyArg_ParseTuple (args, "%(pytypes)s", %(inputrefs)s)) {
-    return NULL;
-  }
-
-  %(parseinput)s
+%(inputdefs)s
+%(inputvecs)s
+%(outputvecs)s
+
+%(arg_parse_tuple)s
+
+%(parseinput)s
   
-  %(outputcreate)s
+%(outputcreate)s
 
   /* compute _do function */
   %(funcname)s (%(doparams_string)s);
 
-  %(returnval)s;
+%(returnval)s;
 }
 """ % locals()
