python/lib/gen_code.py: use new proxy functions
[aubio.git] / python / lib / gen_external.py
1 import os
2
3 header = """// this file is generated! do not modify
4 #include "aubio-types.h"
5 """
6
7 skip_objects = [
8   # already in ext/
9   'fft',
10   'pvoc',
11   'filter',
12   'filterbank',
13   #'resampler',
14   # AUBIO_UNSTABLE
15   'hist',
16   'parameter',
17   'scale',
18   'beattracking',
19   'resampler',
20   'peakpicker',
21   'pitchfcomb',
22   'pitchmcomb',
23   'pitchschmitt',
24   'pitchspecacf',
25   'pitchyin',
26   'pitchyinfft',
27   'sink',
28   'sink_apple_audio',
29   'sink_sndfile',
30   'sink_wavwrite',
31   #'mfcc',
32   'source',
33   'source_apple_audio',
34   'source_sndfile',
35   'source_avcodec',
36   'source_wavread',
37   #'sampler',
38   'audio_unit',
39
40   'tss',
41   ]
42
43
44 def get_cpp_objects():
45
46     cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=1 -I../build/src ../src/aubio.h').readlines()]
47     #cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=0 -I../build/src ../src/onset/onset.h').readlines()]
48     #cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=0 -I../build/src ../src/pitch/pitch.h').readlines()]
49
50     cpp_output = filter(lambda y: len(y) > 1, cpp_output)
51     cpp_output = filter(lambda y: not y.startswith('#'), cpp_output)
52     cpp_output = list(cpp_output)
53
54     i = 1
55     while 1:
56         if i >= len(cpp_output): break
57         if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
58             cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
59             cpp_output.pop(i-1)
60         else:
61             i += 1
62
63     typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
64
65     cpp_objects = [a.split()[3][:-1] for a in typedefs]
66
67     return cpp_output, cpp_objects
68
69 def generate_external(output_path):
70     os.mkdir(output_path)
71     sources_list = []
72     cpp_output, cpp_objects = get_cpp_objects()
73     lib = {}
74
75     for o in cpp_objects:
76         if o[:6] != 'aubio_':
77             continue
78         shortname = o[6:-2]
79         if shortname in skip_objects:
80             continue
81         lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []}
82         lib[shortname]['longname'] = o
83         lib[shortname]['shortname'] = shortname
84         for fn in cpp_output:
85             if o[:-1] in fn:
86                 #print "found", o[:-1], "in", fn
87                 if 'typedef struct ' in fn:
88                     lib[shortname]['struct'].append(fn)
89                 elif '_do' in fn:
90                     lib[shortname]['do'].append(fn)
91                 elif 'new_' in fn:
92                     lib[shortname]['new'].append(fn)
93                 elif 'del_' in fn:
94                     lib[shortname]['del'].append(fn)
95                 elif '_get_' in fn:
96                     lib[shortname]['get'].append(fn)
97                 elif '_set_' in fn:
98                     lib[shortname]['set'].append(fn)
99                 else:
100                     #print "no idea what to do about", fn
101                     lib[shortname]['other'].append(fn)
102
103     """
104     for fn in cpp_output:
105         found = 0
106         for o in lib:
107             for family in lib[o]:
108                 if fn in lib[o][family]:
109                     found = 1
110         if found == 0:
111             print "missing", fn
112
113     for o in lib:
114         for family in lib[o]:
115             if type(lib[o][family]) == str:
116                 print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
117             elif len(lib[o][family]) == 1:
118                 print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family][0] ) )
119             else:
120                 print ( "{:15s} {:10s} {:d}".format(o, family, len(lib[o][family]) ) )
121     """
122
123     from .gen_code import MappedObject
124     for o in lib:
125         out = header
126         mapped = MappedObject(lib[o])
127         out += mapped.gen_code()
128         output_file = os.path.join(output_path, 'gen-%s.c' % o)
129         with open(output_file, 'w') as f:
130             f.write(out)
131             print ("wrote %s" % output_file )
132             sources_list.append(output_file)
133
134     out = header
135     out += "#include \"aubio-generated.h\""
136     check_types = "\n     ||  ".join(["PyType_Ready(&Py_%sType) < 0" % o for o in lib])
137     out += """
138
139 int generated_types_ready (void)
140 {{
141   return ({pycheck_types});
142 }}
143 """.format(pycheck_types = check_types)
144
145     add_types = "".join(["""
146   Py_INCREF (&Py_{name}Type);
147   PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name = o) for o in lib])
148     out += """
149
150 void add_generated_objects ( PyObject *m )
151 {{
152 {add_types}
153 }}
154 """.format(add_types = add_types)
155
156     output_file = os.path.join(output_path, 'aubio-generated.c')
157     with open(output_file, 'w') as f:
158         f.write(out)
159         print ("wrote %s" % output_file )
160         sources_list.append(output_file)
161
162     objlist = "".join(["extern PyTypeObject Py_%sType;\n" % p for p in lib])
163     out = """
164 // generated list of objects created with gen_external.py
165 #include <Python.h>
166
167 {objlist}
168 int generated_objects ( void );
169 void add_generated_objects( PyObject *m );
170 """.format(objlist = objlist)
171
172     output_file = os.path.join(output_path, 'aubio-generated.h')
173     with open(output_file, 'w') as f:
174         f.write(out)
175         print ("wrote %s" % output_file )
176         # no need to add header to list of sources
177
178     return sources_list
179
180 if __name__ == '__main__':
181     output_path = 'gen'
182     generate_external(output_path)