root/trunk/ocaml-taglib/src/taglib_stubs.c @ 6665

Revision 6665, 7.3 KB (checked in by dbaelde, 15 months ago)

Add blocking sections around file_new and file_new_type.
Those calls can indeed be long, when the file is ill-formed (e.g., when
trying to decode a .wav as a .mp3).
But this fixes an even nastier bug in liquidsoap running in daemon mode.
In that mode, liquidsoap attaches stderr to a pipe and has a task reading
this pipe and logging its contents. Since file_new* can write to stderr,
they could create a deadlock: the caml global lock is taken so the reading
task cannot read, the pipe becomes full and blocks file_new*.

Line 
1/*
2 * Copyright 2007 Romain Beauxis
3 *
4 * This file is part of ocaml-taglib.
5 *
6 * ocaml-taglib is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * ocaml-taglib is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with ocaml-taglib; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 *
20 * As a special exception to the GNU Library General Public License, you may
21 * link, statically or dynamically, a "work that uses the Library" with a publicly
22 * distributed version of the Library to produce an executable file containing
23 * portions of the Library, and distribute that executable file under terms of
24 * your choice, without any of the additional requirements listed in clause 6
25 * of the GNU Library General Public License.
26 * By "a publicly distributed version of the Library", we mean either the unmodified
27 * Library as distributed by INRIA, or a modified version of the Library that is
28 * distributed under the conditions defined in clause 3 of the GNU Library General
29 * Public License. This exception does not however invalidate any other reasons why
30 * the executable file might be covered by the GNU Library General Public License.
31 *
32 */
33
34
35/*
36 * Ocaml interface to taglib
37 *
38 * @author Romain Beauxis
39 */
40
41#include <taglib/tag_c.h>
42#include <string.h>
43
44#include <caml/alloc.h>
45#include <caml/callback.h>
46#include <caml/fail.h>
47#include <caml/memory.h>
48#include <caml/signals.h>
49
50CAMLprim value caml_taglib_init()
51{
52  CAMLparam0();
53  /* Desactivates string memory management */
54  taglib_set_string_management_enabled(0) ;
55  CAMLreturn(Val_unit);
56}
57
58CAMLprim value caml_taglib_set_strings_unicode(value b)
59{
60  CAMLparam1(b);
61
62  taglib_set_strings_unicode(Bool_val(b)) ;
63
64  CAMLreturn(Val_unit);
65}
66
67/* Returns #defined values that are used for C functions
68 * remove initial Taglib_ to avoid define :) */
69CAMLprim value caml_taglib_priv_value_int(value name)
70{
71  CAMLparam1(name);
72  char *s = String_val(name);
73    if (!strcmp(s,"File_MPEG"))
74      CAMLreturn(Val_int(TagLib_File_MPEG)) ;
75    if (!strcmp(s,"File_OggVorbis"))
76      CAMLreturn(Val_int(TagLib_File_OggVorbis)) ;
77    if (!strcmp(s,"File_FLAC"))
78      CAMLreturn(Val_int(TagLib_File_FLAC)) ;
79    if (!strcmp(s,"File_MPC"))
80      CAMLreturn(Val_int(TagLib_File_MPC)) ;
81
82  caml_failwith("Invalid value");
83}
84
85#define Taglib_file_val(v) ((TagLib_File *)v)
86#define Taglib_file_const_val(v) ((const TagLib_File *)v)
87#define Taglib_tag_val(v) ((TagLib_Tag *)v)
88#define Taglib_tag_const_val(v) ((const TagLib_Tag *)v)
89#define Taglib_audioproperties_val(v) ((const TagLib_AudioProperties *)v)
90
91CAMLprim value caml_taglib_file_new(value name)
92{
93  CAMLparam1(name);
94
95  int len = caml_string_length(name);
96  char *filename = malloc(len);
97  memcpy(filename, String_val(name), len);
98
99  caml_enter_blocking_section();
100  TagLib_File *f = taglib_file_new(filename) ;
101  caml_leave_blocking_section();
102
103  free(filename);
104
105  if (f == NULL)
106    caml_raise_constant(*caml_named_value("taglib_exn_not_found"));
107
108  CAMLreturn((value)f);
109}
110
111CAMLprim value caml_taglib_file_new_type(value name, value type)
112{
113  CAMLparam2(name,type);
114
115  int len = caml_string_length(name);
116  char *filename = malloc(len);
117  memcpy(filename, String_val(name), len);
118
119  caml_enter_blocking_section();
120  TagLib_File *f =
121    taglib_file_new_type((const char *)String_val(name),Int_val(type)) ;
122  caml_leave_blocking_section();
123
124  free(filename);
125
126  if (f == NULL)
127    caml_raise_constant(*caml_named_value("taglib_exn_not_found"));
128
129  CAMLreturn((value)f);
130}
131
132CAMLprim value caml_taglib_file_free(value f)
133{
134  CAMLparam1(f);
135  taglib_file_free(Taglib_file_val(f));
136
137  CAMLreturn(Val_unit);
138}
139
140CAMLprim value caml_taglib_file_tag(value f)
141{
142  CAMLparam1(f);
143  TagLib_Tag *t = taglib_file_tag(Taglib_file_val(f)) ;
144
145  if (t == NULL)
146    caml_raise_constant(*caml_named_value("taglib_exn_not_found"));
147
148  CAMLreturn((value)t);
149}
150
151CAMLprim value caml_taglib_file_audioproperties(value f)
152{
153  CAMLparam1(f);
154  TagLib_AudioProperties *p = taglib_file_audioproperties(Taglib_file_val(f)) ;
155
156  if (p == NULL)
157    caml_raise_constant(*caml_named_value("taglib_exn_not_found"));
158
159
160  CAMLreturn((value)p);
161}
162
163CAMLprim value caml_taglib_file_save(value f)
164{
165  CAMLparam1(f);
166  CAMLreturn(Val_bool(taglib_file_save(Taglib_file_val(f))));
167}
168
169CAMLprim value caml_taglib_tag_get_string(value t, value name)
170{
171  CAMLparam2(t,name);
172  CAMLlocal1(ans);
173  const TagLib_Tag *tag = Taglib_tag_const_val(t) ;
174  char *s = String_val(name);
175  char *tmp;
176
177    if (!strcmp(s,"title"))
178      tmp = taglib_tag_title(tag) ;
179    else if (!strcmp(s,"artist"))
180      tmp = taglib_tag_artist(tag) ;
181    else if (!strcmp(s,"album"))
182      tmp = taglib_tag_album(tag) ;
183    else if (!strcmp(s,"comment"))
184      tmp = taglib_tag_comment(tag) ;
185    else if (!strcmp(s,"genre"))
186      tmp = taglib_tag_genre(tag) ;
187    else
188      caml_failwith("Invalid value");
189
190  ans = caml_copy_string(tmp) ; 
191  free(tmp) ;
192  CAMLreturn(ans);
193}
194
195CAMLprim value caml_taglib_tag_get_int(value t, value name)
196{
197  CAMLparam2(t,name);
198  const TagLib_Tag *tag = Taglib_tag_const_val(t) ;
199  char *s = String_val(name);
200  int tmp;
201
202    if (!strcmp(s,"year"))
203      tmp = taglib_tag_year(tag) ;
204    else if (!strcmp(s,"track"))
205      tmp = taglib_tag_track(tag) ;
206    else
207      caml_failwith("Invalid value");
208
209  CAMLreturn(Val_int(tmp));
210}
211
212CAMLprim value caml_taglib_tag_set_string(value t, value name, value v)
213{
214  CAMLparam3(t,name, v);
215  TagLib_Tag *tag = Taglib_tag_val(t) ;
216  char *s = String_val(name);
217  char *x = String_val(v) ;
218
219    if (!strcmp(s,"title"))
220      taglib_tag_set_title(tag,x) ;
221    else if (!strcmp(s,"artist"))
222      taglib_tag_set_artist(tag,x) ;
223    else if (!strcmp(s,"album"))
224      taglib_tag_set_album(tag,x) ;
225    else if (!strcmp(s,"comment"))
226      taglib_tag_set_comment(tag,x) ;
227    else if (!strcmp(s,"genre"))
228      taglib_tag_set_genre(tag,x) ;
229    else
230      caml_failwith("Invalid value");
231
232  CAMLreturn(Val_unit);
233}
234
235CAMLprim value caml_taglib_tag_set_int(value t, value name, value v)
236{
237  CAMLparam3(t,name, v);
238  TagLib_Tag *tag = Taglib_tag_val(t) ;
239  char *s = String_val(name);
240  int x = Int_val(v) ;
241
242    if (!strcmp(s,"year"))
243      taglib_tag_set_year(tag,x) ;
244    else if (!strcmp(s,"track"))
245      taglib_tag_set_track(tag,x) ;
246    else
247      caml_failwith("Invalid value");
248
249  CAMLreturn(Val_unit);
250}
251
252CAMLprim value caml_taglib_audioproperties_get_int(value p, value name)
253{
254  CAMLparam2(p,name);
255  const TagLib_AudioProperties *prop = Taglib_audioproperties_val(p) ;
256  char *s = String_val(name);
257  int tmp;
258
259    if (!strcmp(s,"length"))
260      tmp = taglib_audioproperties_length(prop) ;
261    else if (!strcmp(s,"bitrate"))
262      tmp = taglib_audioproperties_bitrate(prop) ;
263    else if (!strcmp(s,"samplerate"))
264      tmp = taglib_audioproperties_samplerate(prop) ;
265    else if (!strcmp(s,"channels"))
266      tmp = taglib_audioproperties_channels(prop) ;
267    else
268      caml_failwith("Invalid value");
269
270  CAMLreturn(Val_int(tmp));
271}
272
273
274
Note: See TracBrowser for help on using the browser.