]> diplodocus.org Git - flac-archive/blob - flac.c
f539d1110cd2bb60150a367c1790be6db70232f1
[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 *description, *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 description = PyUnicode_DecodeUTF8(block->data.picture.description,
57 strlen(block->data.picture.description),
58 "strict");
59 if (description == NULL) {
60 return NULL;
61 }
62
63 tuple = Py_BuildValue("(isOiiiis#)",
64 block->data.picture.type,
65 block->data.picture.mime_type,
66 description,
67 block->data.picture.width,
68 block->data.picture.height,
69 block->data.picture.depth,
70 block->data.picture.colors,
71 block->data.picture.data,
72 block->data.picture.data_length);
73 if (tuple == NULL) {
74 return NULL;
75 }
76
77 if (PyList_Append(list, tuple) == -1) {
78 return NULL;
79 }
80 } while(FLAC__metadata_iterator_next(iterator));
81
82 FLAC__metadata_iterator_delete(iterator);
83 FLAC__metadata_chain_delete(chain);
84
85 return list;
86 }
87
88 static PyObject *
89 get_pictures(PyObject *self, PyObject *args)
90 {
91 char *fn;
92
93 if (!PyArg_ParseTuple(args, "s", &fn)) {
94 return NULL;
95 }
96
97 return flac_pictures(fn);
98 }
99
100 static
101 PyMethodDef methods[] = {
102 {"get_pictures", get_pictures, METH_VARARGS,
103 "document me"},
104
105 {NULL, NULL, 0, NULL}
106 };
107
108 static void
109 export_constants(PyObject *m)
110 {
111 PyObject *n;
112
113 #define foo(x) \
114 n = PyInt_FromLong(FLAC__STREAM_METADATA_ ## x); \
115 if (n == NULL || PyModule_AddObject(m, #x, n) == -1) return;
116
117 foo(PICTURE_TYPE_OTHER);
118 foo(PICTURE_TYPE_FILE_ICON_STANDARD);
119 foo(PICTURE_TYPE_FILE_ICON);
120 foo(PICTURE_TYPE_FRONT_COVER);
121 foo(PICTURE_TYPE_BACK_COVER);
122 foo(PICTURE_TYPE_LEAFLET_PAGE);
123 foo(PICTURE_TYPE_MEDIA);
124 foo(PICTURE_TYPE_LEAD_ARTIST);
125 foo(PICTURE_TYPE_ARTIST);
126 foo(PICTURE_TYPE_CONDUCTOR);
127 foo(PICTURE_TYPE_BAND);
128 foo(PICTURE_TYPE_COMPOSER);
129 foo(PICTURE_TYPE_LYRICIST);
130 foo(PICTURE_TYPE_RECORDING_LOCATION);
131 foo(PICTURE_TYPE_DURING_RECORDING);
132 foo(PICTURE_TYPE_DURING_PERFORMANCE);
133 foo(PICTURE_TYPE_VIDEO_SCREEN_CAPTURE);
134 foo(PICTURE_TYPE_FISH);
135 foo(PICTURE_TYPE_ILLUSTRATION);
136 foo(PICTURE_TYPE_BAND_LOGOTYPE);
137 foo(PICTURE_TYPE_PUBLISHER_LOGOTYPE);
138 foo(PICTURE_TYPE_UNDEFINED);
139
140 #undef foo
141 }
142
143 PyMODINIT_FUNC
144 initflac(void)
145 {
146 PyObject *m = Py_InitModule("flac", methods);
147 if (m == NULL) {
148 return;
149 }
150
151 flac_error = PyErr_NewException("flac_archive.flac.error", NULL, NULL);
152 if (flac_error == NULL) {
153 return;
154 }
155 PyModule_AddObject(m, "error", flac_error);
156
157 export_constants(m);
158 }