OSDN Git Service

Metadata keys for PCM decoding
[android-x86/system-media.git] / mca / structgen.py
1 #!/usr/bin/env python
2
3 #
4 # Copyright (C) 2011 The Android Open Source Project
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #      http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19 import os
20 import sys
21
22 hFileTemplate = """/**
23  * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
24  **/
25
26 #ifndef %s
27 #define %s
28
29 %s
30
31 #endif // %s
32 """
33
34 jniFileTemplate = """/**
35  * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
36  **/
37
38 #include <stdint.h>
39 #include "native/%s.h"
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 #include "jni.h"
46
47 // Helper functions ////////////////////////////////////////////////////////////////////////////////
48 %s* Get%sAtIndex(JNIEnv* env, jobject buffer, int index) {
49   jclass base_class = (*env)->FindClass(env, "android/filterfw/core/NativeBuffer");
50   jfieldID ptr_field = (*env)->GetFieldID(env, base_class, "mDataPointer", "J");
51   uintptr_t data_ptr = (*env)->GetLongField(env, buffer, ptr_field);
52   %s* array = (%s*)data_ptr;
53   (*env)->DeleteLocalRef(env, base_class);
54   return &array[index];
55 }
56
57 // Declarations ////////////////////////////////////////////////////////////////////////////////////
58 JNIEXPORT jint JNICALL
59 Java_%s_getElementSize(JNIEnv* env, jobject thiz);
60
61 %s
62
63 #ifdef __cplusplus
64 }
65 #endif
66
67 // Implementation //////////////////////////////////////////////////////////////////////////////////
68 jint Java_%s_getElementSize(JNIEnv* env, jobject thiz) {
69   return sizeof(%s);
70 }
71
72 %s
73 """
74
75 javaFileTemplate = """/**
76  * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
77  **/
78
79 package %s;
80
81 import android.filterfw.core.NativeBuffer;
82
83 %s
84 """
85
86
87 def ToJavaName(cname, start_upper_at = 1):
88   lower = cname.split("_")
89   upper = [c.title() for c in lower]
90   return "".join(lower[:start_upper_at] + upper[start_upper_at:])
91
92 def ToJNIPackage(package, jclassname):
93   return "%s_%s" % (package.replace(".", "_"), jclassname)
94
95 def ToMacroDefName(cname, pname):
96   return "%s_%s" % (pname.replace(".", "_").upper(), cname.upper())
97
98 class ParseError:
99   def __init__(self, lineno, message):
100     self.lineno = lineno
101     self.message = message
102
103   def __str__(self):
104     return "On line %d: %s" % (self.lineno, self.message)
105
106 class FieldType_BasePOD:
107   def __init__(self, name, structname, jclassname, package, ctype, jtype, defval):
108     self.name = name
109     self.structname = structname
110     self.jclassname = jclassname
111     self.package = package
112     self.ctype = ctype
113     self.jtype = jtype
114     self.defval = defval
115
116   def cString(self):
117     return "  %s %s;" % (self.ctype, self.name)
118
119   def javaGetter(self):
120     return "    public %s get%s(int index) {\n"\
121            "        assertReadable();\n"\
122            "        return nativeGet%s(index);\n"\
123            "    }" % (self.ctype, ToJavaName(self.name, 0), ToJavaName(self.name, 0))
124
125   def javaSetter(self):
126     return "    public void set%s(int index, %s value) {\n"\
127            "        assertWritable();\n"\
128            "        nativeSet%s(index, value);\n"\
129            "    }" % (ToJavaName(self.name, 0), self.ctype, ToJavaName(self.name, 0))
130
131   def javaNativeGetter(self):
132     return "    private native %s nativeGet%s(int index);"\
133            % (self.ctype, ToJavaName(self.name, 0))
134
135   def javaNativeSetter(self):
136     return "    private native boolean nativeSet%s(int index, %s value);"\
137            % (ToJavaName(self.name, 0), self.ctype)
138
139   def jniGetterDefString(self):
140     return "JNIEXPORT %s JNICALL\n" \
141            "Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index);" \
142            % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0))
143
144   def jniGetterImplString(self):
145     return \
146       "%s Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index) {\n"\
147       "  %s* instance = Get%sAtIndex(env, thiz, index);\n"\
148       "  return instance ? instance->%s : %s;\n"\
149       "}\n" % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\
150                self.structname, self.structname, self.name, self.defval)
151
152   def jniSetterDefString(self):
153     return "JNIEXPORT jboolean JNICALL\n" \
154            "Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value);" \
155            % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0), self.jtype)
156
157   def jniSetterImplString(self):
158     return \
159       "jboolean Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value) {\n"\
160       "  %s* instance = Get%sAtIndex(env, thiz, index);\n"\
161       "  if (instance) {\n"\
162       "    instance->%s = value;\n"\
163       "    return JNI_TRUE;\n"\
164       "  }\n"\
165       "  return JNI_FALSE;\n"\
166       "}\n" % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\
167                self.jtype, self.structname, self.structname, self.name)
168
169 class FieldType_Float(FieldType_BasePOD):
170   def __init__(self, name, structname, jclassname, package):
171     FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "float", "jfloat", "0.0")
172
173 class FieldType_Int(FieldType_BasePOD):
174   def __init__(self, name, structname, jclassname, package):
175     FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "int", "jint", "0")
176
177 class StructSpec:
178
179   def parseTextFile(self, filepath):
180     # Init
181     self.name = None
182     self.package = None
183     self.fields = []
184     self.structname = None
185     self.jclassname = None
186     self.libname = None
187
188     # Open the file
189     txtfile = open(filepath)
190
191     # Parse it line by line
192     lineno = 0
193     for line in txtfile:
194       # Split line into components
195       linecomps = line.split()
196       if len(linecomps) == 0:
197         continue
198
199       # Execute command
200       cmd = linecomps[0]
201       if cmd == "@name":
202         self.commandArgAssert(linecomps, 1, lineno)
203         self.name = linecomps[1]
204         if not self.structname:
205           self.structname = self.name
206         if not self.jclassname:
207           self.jclassname = self.name
208       elif cmd == "@package":
209         self.commandArgAssert(linecomps, 1, lineno)
210         self.package = linecomps[1]
211       elif cmd == "@libname":
212         self.commandArgAssert(linecomps, 1, lineno)
213         self.libname = linecomps[1]
214       elif cmd == "@structname":
215         self.commandArgAssert(linecomps, 1, lineno)
216         self.structname = linecomps[1]
217       elif cmd == "@javaclassname":
218         self.commandArgAssert(linecomps, 1, lineno)
219         self.jclassname = linecomps[1]
220       elif cmd == "@field":
221         self.commandArgAssert(linecomps, 2, lineno)
222         typestr = linecomps[1]
223         if typestr == "int":
224           fieldtype = FieldType_Int(linecomps[2], self.structname, self.jclassname, self.package)
225         elif typestr == "float":
226           fieldtype = FieldType_Float(linecomps[2], self.structname, self.jclassname, self.package)
227         else:
228           raise ParseError(lineno, "Unknown field type '%s'!" % typestr)
229         self.fields.append(fieldtype)
230       else:
231         raise ParseError(lineno, "Unknown command: '%s'!" % cmd)
232
233       lineno = lineno + 1
234
235     # Make sure we have all required info
236     if not self.name:
237       raise ParseError(lineno, "Required field '@name' missing!")
238     elif not self.package:
239       raise ParseError(lineno, "Required field '@package' missing!")
240     elif not self.libname:
241       raise ParseError(lineno, "Required field '@libname' missing!")
242
243     # Normalize values
244     if self.libname[:3] == "lib":
245       self.libname = self.libname[3:]
246
247   def commandArgAssert(self, linecomps, expectedcount, lineno):
248     foundcount = len(linecomps) - 1
249     if foundcount < expectedcount:
250       raise ParseError(lineno, "Not enough arguments specifed for command '%s'! Expected %d, " \
251                        "but got only %d!" % (linecomps[0], expectedcount, foundcount))
252     elif foundcount > expectedcount + 1:
253       raise ParseError(lineno, "Too many arguments specifed for command '%s'! Expected %d, " \
254                        "but got %d!" % (linecomps[0], expectedcount, foundcount))
255
256
257   def cStructString(self):
258     cfields = [f.cString() for f in self.fields]
259     return "typedef struct Struct%s {\n%s\n} %s;\n" % (self.structname,\
260                                                        "\n".join(cfields),\
261                                                        self.structname)
262
263   def javaClassString(self):
264     jgetters = [f.javaGetter() for f in self.fields]
265     jsetters = [f.javaSetter() for f in self.fields]
266     jnativesetters = [f.javaNativeSetter() for f in self.fields]
267     jnativegetters = [f.javaNativeGetter() for f in self.fields]
268     return "public class %s extends NativeBuffer {\n\n"\
269            "    public %s() {\n"\
270            "        super();\n"\
271            "    }\n"\
272            "\n"\
273            "    public %s(int count) {\n"\
274            "        super(count);\n"\
275            "    }\n"\
276            "\n"\
277            "    public native int getElementSize();\n"\
278            "\n"\
279            "%s\n\n"\
280            "%s\n\n"\
281            "%s\n\n"\
282            "%s\n\n"\
283            "    static {\n"\
284            "        System.loadLibrary(\"%s\");\n"\
285            "    }\n"\
286            "\n"\
287            "};\n" % (self.jclassname,\
288                      self.jclassname,\
289                      self.jclassname,\
290                      "\n\n".join(jgetters),\
291                      "\n\n".join(jsetters),\
292                      "\n\n".join(jnativegetters),\
293                      "\n\n".join(jnativesetters),\
294                      self.libname)
295
296   def jniDeclString(self):
297     jnigetters = [f.jniGetterDefString() for f in self.fields]
298     jnisetters = [f.jniSetterDefString() for f in self.fields]
299     return "\n\n".join(jnigetters + jnisetters)
300
301   def jniImplString(self):
302     jnigetters = [f.jniGetterImplString() for f in self.fields]
303     jnisetters = [f.jniSetterImplString() for f in self.fields]
304     return "\n\n".join(jnigetters + jnisetters)
305
306   def hFileString(self):
307     defname = ToMacroDefName(self.structname, self.package)
308     return hFileTemplate % (defname, defname, self.cStructString(), defname)
309
310   def javaFileString(self):
311     return javaFileTemplate % (self.package, self.javaClassString())
312
313   def jniFileString(self):
314     return jniFileTemplate % (self.structname.lower(),\
315                               self.structname,\
316                               self.structname,\
317                               self.structname,\
318                               self.structname,\
319                               ToJNIPackage(self.package, self.jclassname),\
320                               self.jniDeclString(),\
321                               ToJNIPackage(self.package, self.jclassname),\
322                               self.structname,
323                               self.jniImplString())
324
325 def main(argv):
326   if len(argv) != 2:
327     print("Usage: %s <file.struct>" % argv[0])
328     return -1
329
330   filepath = argv[1]
331
332   structspec = StructSpec()
333   structspec.parseTextFile(filepath)
334
335   hfilename = "%s.h" % structspec.structname.lower()
336   javafilename = "%s.java" % structspec.jclassname
337   jnifilename = "jni_%s.c" % structspec.structname.lower()
338
339   javapackagepath = structspec.package.replace('.','/')
340
341   rootdir = os.path.dirname(filepath)
342   hfilepath = "%s/../native/%s" % (rootdir, hfilename)
343   javafilepath = "%s/../java/%s/%s" % (rootdir, javapackagepath, javafilename)
344   jnifilepath = "%s/../jni/%s" % (rootdir, jnifilename)
345
346   hfile = open(hfilepath, 'w')
347   hfile.write(structspec.hFileString())
348   hfile.close()
349
350   javafile = open(javafilepath, 'w')
351   javafile.write(structspec.javaFileString())
352   javafile.close()
353
354   jnifile = open(jnifilepath, 'w')
355   jnifile.write(structspec.jniFileString())
356   jnifile.close()
357
358
359 if __name__ == "__main__":
360   sys.exit(main(sys.argv))