]> diplodocus.org Git - flac-archive/blob - flac.c
9df8fcd8b7be0f0c2801524d723f0845b6282486
[flac-archive] / flac.c
1 #include <FLAC/metadata.h>
2
3 #include <Python.h>
4
5 static PyObject *flac_error;
6
7 static PyObject *
8 flac_pictures(char *fn)
9 {
10 FLAC__Metadata_Chain *chain;
11 FLAC__Metadata_Iterator *iterator;
12 FLAC__StreamMetadata *block;
13 PyObject *tuple, *list;
14
15 chain = FLAC__metadata_chain_new();
16 if (chain == NULL) {
17 return PyErr_NoMemory();
18 }
19
20 if(!FLAC__metadata_chain_read(chain, fn)) {
21 PyObject *s = PyString_FromFormat("metadata_chain_read (%d)",
22 FLAC__metadata_chain_status(chain));
23 if (s != NULL) {
24 PyErr_SetObject(flac_error, s);
25 }
26 return NULL;
27 }
28
29 iterator = FLAC__metadata_iterator_new();
30 if (iterator == NULL) {
31 return PyErr_NoMemory();
32 }
33
34 FLAC__metadata_iterator_init(iterator, chain);
35
36 list = PyList_New(0);
37 if (list == NULL) {
38 return NULL;
39 }
40
41 do {
42 /* This can fail, but the documentation doesn't say how, why,
43 * or how to react. metaflac/operations.c just prints a
44 * useless error message and keeps going. */
45 block = FLAC__metadata_iterator_get_block(iterator);
46 if (block == NULL) {
47 PyErr_SetString(flac_error,
48 "metadata_iterator_get_block returned NULL");
49 return NULL;
50 }
51
52 if (block->type != FLAC__METADATA_TYPE_PICTURE) {
53 continue;
54 }
55
56 tuple = Py_BuildValue("(s#issiiii)",
57 block->data.picture.data,
58 block->data.picture.data_length,
59 block->data.picture.type,
60 block->data.picture.mime_type,
61 block->data.picture.description,
62 block->data.picture.width,
63 block->data.picture.height,
64 block->data.picture.depth,
65 block->data.picture.colors);
66 if (tuple == NULL) {
67 return NULL;
68 }
69
70 if (PyList_Append(list, tuple) == -1) {
71 return NULL;
72 }
73 } while(FLAC__metadata_iterator_next(iterator));
74
75 FLAC__metadata_iterator_delete(iterator);
76 FLAC__metadata_chain_delete(chain);
77
78 return list;
79 }
80
81 static PyObject *
82 get_pictures(PyObject *self, PyObject *args)
83 {
84 char *fn;
85
86 if (!PyArg_ParseTuple(args, "s", &fn)) {
87 return NULL;
88 }
89
90 return flac_pictures(fn);
91 }
92
93 static
94 PyMethodDef methods[] = {
95 {"get_pictures", get_pictures, METH_VARARGS,
96 "document me"},
97
98 {NULL, NULL, 0, NULL}
99 };
100
101 static void
102 export_constants(PyObject *m)
103 {
104 PyObject *n;
105
106 #define foo(x) \
107 n = PyInt_FromLong(FLAC__STREAM_METADATA_ ## x); \
108 if (n == NULL || PyModule_AddObject(m, #x, n) == -1) return;
109
110 foo(PICTURE_TYPE_OTHER);
111 foo(PICTURE_TYPE_FILE_ICON_STANDARD);
112 foo(PICTURE_TYPE_FILE_ICON);
113 foo(PICTURE_TYPE_FRONT_COVER);
114 foo(PICTURE_TYPE_BACK_COVER);
115 foo(PICTURE_TYPE_LEAFLET_PAGE);
116 foo(PICTURE_TYPE_MEDIA);
117 foo(PICTURE_TYPE_LEAD_ARTIST);
118 foo(PICTURE_TYPE_ARTIST);
119 foo(PICTURE_TYPE_CONDUCTOR);
120 foo(PICTURE_TYPE_BAND);
121 foo(PICTURE_TYPE_COMPOSER);
122 foo(PICTURE_TYPE_LYRICIST);
123 foo(PICTURE_TYPE_RECORDING_LOCATION);
124 foo(PICTURE_TYPE_DURING_RECORDING);
125 foo(PICTURE_TYPE_DURING_PERFORMANCE);
126 foo(PICTURE_TYPE_VIDEO_SCREEN_CAPTURE);
127 foo(PICTURE_TYPE_FISH);
128 foo(PICTURE_TYPE_ILLUSTRATION);
129 foo(PICTURE_TYPE_BAND_LOGOTYPE);
130 foo(PICTURE_TYPE_PUBLISHER_LOGOTYPE);
131 foo(PICTURE_TYPE_UNDEFINED);
132
133 #undef foo
134 }
135
136 PyMODINIT_FUNC
137 initflac(void)
138 {
139 PyObject *m = Py_InitModule("flac", methods);
140 if (m == NULL) {
141 return;
142 }
143
144 flac_error = PyErr_NewException("org.diplodocus.flac.error", NULL, NULL);
145 if (flac_error == NULL) {
146 return;
147 }
148 PyModule_AddObject(m, "error", flac_error);
149
150 export_constants(m);
151 }