1 /*
2 * Copyright (c) 2009-2014 Kuan-Chung Chiu <buganini@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
14 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 #include <bsdconv.h>
17
18 #include "EXTERN.h"
19 #include "perl.h"
20 #include "XSUB.h"
21
22 #include "ppport.h"
23 #include <errno.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #ifndef WIN32
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #endif
32
33 typedef struct bsdconv_instance * Bsdconv;
34 typedef FILE * Bsdconv_file;
35
36 #define IBUFLEN 1024
37 #define TEMPLATE "bsdconv(\"%s\")"
38
39 MODULE = bsdconv PACKAGE = bsdconv
40
41 BOOT:
42 {
43 HV *m;
44
45 m = gv_stashpv("bsdconv", TRUE);
46 newCONSTSUB(m, "FILTER", newSViv(FILTER));
47 newCONSTSUB(m, "FROM", newSViv(FROM));
48 newCONSTSUB(m, "INTER", newSViv(INTER));
49 newCONSTSUB(m, "TO", newSViv(TO));
50
51 newCONSTSUB(m, "CTL_ATTACH_SCORE", newSViv(BSDCONV_CTL_ATTACH_SCORE));
52 newCONSTSUB(m, "CTL_ATTACH_OUTPUT_FILE", newSViv(BSDCONV_CTL_ATTACH_OUTPUT_FILE));
53 newCONSTSUB(m, "CTL_AMBIGUOUS_PAD", newSViv(BSDCONV_CTL_AMBIGUOUS_PAD));
54 }
55
56 SV*
57 insert_phase(conversion, codecs, phase_type, ophasen)
58 char* conversion
59 char* codecs
60 int phase_type
61 int ophasen
62 PREINIT:
63 char *s;
64 CODE:
65 s=bsdconv_insert_phase(conversion, codecs, phase_type, ophasen);
66 RETVAL=newSVpv(s, 0);
67 bsdconv_free(s);
68 OUTPUT:
69 RETVAL
70
71 SV*
72 insert_codec(conversion, codec, ophasen, ocodecn)
73 char* conversion
74 char* codec
75 int ophasen
76 int ocodecn
77 PREINIT:
78 char *s;
79 CODE:
80 s=bsdconv_insert_codec(conversion, codec, ophasen, ocodecn);
81 RETVAL=newSVpv(s, 0);
82 bsdconv_free(s);
83 OUTPUT:
84 RETVAL
85
86 SV*
87 replace_phase(conversion, codecs, phase_type, ophasen)
88 char* conversion
89 char* codecs
90 int phase_type
91 int ophasen
92 PREINIT:
93 char *s;
94 CODE:
95 s=bsdconv_replace_phase(conversion, codecs, phase_type, ophasen);
96 RETVAL=newSVpv(s, 0);
97 bsdconv_free(s);
98 OUTPUT:
99 RETVAL
100
101 SV*
102 replace_codec(conversion, codec, ophasen, ocodecn)
103 char* conversion
104 char* codec
105 int ophasen
106 int ocodecn
107 PREINIT:
108 char *s;
109 CODE:
110 s=bsdconv_replace_codec(conversion, codec, ophasen, ocodecn);
111 RETVAL=newSVpv(s, 0);
112 bsdconv_free(s);
113 OUTPUT:
114 RETVAL
115
116
117 SV*
118 error()
119 PREINIT:
120 char *s;
121 CODE:
122 s=bsdconv_error();
123 RETVAL=newSVpv(s, 0);
124 bsdconv_free(s);
125 OUTPUT:
126 RETVAL
127
128 SV*
129 module_check(phase_type, codec)
130 int phase_type
131 char *codec
132 CODE:
133 if(bsdconv_module_check(phase_type, codec))
134 XSRETURN_YES;
135 XSRETURN_NO;
136 OUTPUT:
137 RETVAL
138
139 SV*
140 codec_check(phase_type, codec)
141 int phase_type
142 char *codec
143 CODE:
144 if(bsdconv_module_check(phase_type, codec))
145 XSRETURN_YES;
146 XSRETURN_NO;
147 OUTPUT:
148 RETVAL
149
150 AV*
151 modules_list(phase_type)
152 int phase_type
153 PREINIT:
154 char **list;
155 char **p;
156 CODE:
157 RETVAL=newAV();
158 list=bsdconv_modules_list(phase_type);
159 p=list;
160 while(*p!=NULL){
161 av_push(RETVAL, newSVpv(*p, 0));
162 bsdconv_free(*p);
163 p+=1;
164 }
165 bsdconv_free(list);
166 OUTPUT:
167 RETVAL
168
169 AV*
170 codecs_list(phase_type)
171 int phase_type
172 PREINIT:
173 char **list;
174 char **p;
175 CODE:
176 RETVAL=newAV();
177 list=bsdconv_modules_list(phase_type);
178 p=list;
179 while(*p!=NULL){
180 av_push(RETVAL, newSVpv(*p, 0));
181 bsdconv_free(*p);
182 p+=1;
183 }
184 bsdconv_free(list);
185 OUTPUT:
186 RETVAL
187
188 AV*
189 mktemp(template)
190 char *template
191 CODE:
192 char *fn=strdup(template);
193 int fd=bsdconv_mkstemp(fn);
194 if(fd==-1)
195 XSRETURN_UNDEF;
196 FILE *fp=fdopen(fd, "wb+");
197 SV *bsdconv_file=sv_newmortal();
198 sv_setref_pv(bsdconv_file,"Bsdconv_file",(void *) fp);
199 RETVAL=newAV();
200 av_push(RETVAL, newSVsv(bsdconv_file));
201 av_push(RETVAL, newSVpv(fn, 0));
202 OUTPUT:
203 RETVAL
204
205 Bsdconv_file
206 fopen(filename, mode)
207 char *filename
208 char *mode
209 CODE:
210 RETVAL=fopen(filename, mode);
211 OUTPUT:
212 RETVAL
213
214 Bsdconv
215 new(package, conversion)
216 char *package
217 char *conversion
218 CODE:
219 RETVAL=bsdconv_create(conversion);
220 OUTPUT:
221 RETVAL
222
223 MODULE = bsdconv PACKAGE = Bsdconv
224
225 void
226 DESTROY(ins)
227 Bsdconv ins
228 CODE:
229 bsdconv_destroy(ins);
230
231 SV*
232 toString(ins)
233 Bsdconv ins
234 PREINIT:
235 char *s;
236 char *s2;
237 int len;
238 CODE:
239 len=sizeof(TEMPLATE);
240 s=bsdconv_pack(ins);
241 len+=strlen(s);
242 s2=malloc(len);
243 sprintf(s2, TEMPLATE, s);
244 bsdconv_free(s);
245 RETVAL=newSVpv(s2, 0);
246 free(s2);
247 OUTPUT:
248 RETVAL
249
250 void
251 init(ins)
252 Bsdconv ins
253 CODE:
254 bsdconv_init(ins);
255
256 void
257 ctl(ins, ctl, res, num)
258 Bsdconv ins
259 int ctl
260 SV* res
261 int num
262 CODE:
263 void *ptr=NULL;
264 if(sv_derived_from(res,"Bsdconv_file")){
265 IV tmp = SvIV((SV*)SvRV(res));
266 ptr=(void *)tmp;
267 }
268 bsdconv_ctl(ins, ctl, ptr, num);
269
270 SV*
271 conv_chunk(ins, str)
272 Bsdconv ins
273 SV* str
274 PREINIT:
275 char *s;
276 SSize_t l;
277 CODE:
278 s=SvPV(str, l);
279
280 ins->output_mode=BSDCONV_AUTOMALLOC;
281 ins->input.data=s;
282 ins->input.len=l;
283 ins->input.flags=0;
284 ins->input.next=NULL;
285 bsdconv(ins);
286
287 RETVAL=newSVpvn(ins->output.data, (STRLEN)ins->output.len);
288 bsdconv_free(ins->output.data);
289 OUTPUT:
290 RETVAL
291
292 SV*
293 conv_chunk_last(ins, str)
294 Bsdconv ins
295 SV* str
296 PREINIT:
297 char *s;
298 SSize_t l;
299 CODE:
300 s=SvPV(str, l);
301
302 ins->output_mode=BSDCONV_AUTOMALLOC;
303 ins->input.data=s;
304 ins->input.len=l;
305 ins->input.flags=0;
306 ins->input.next=NULL;
307 ins->flush=1;
308 bsdconv(ins);
309
310 RETVAL=newSVpvn(ins->output.data, (STRLEN)ins->output.len);
311 bsdconv_free(ins->output.data);
312 OUTPUT:
313 RETVAL
314
315 SV*
316 conv(ins, str)
317 Bsdconv ins
318 SV* str
319 PREINIT:
320 char *s;
321 SSize_t l;
322 CODE:
323 s=SvPV(str, l);
324
325 bsdconv_init(ins);
326 ins->output_mode=BSDCONV_AUTOMALLOC;
327 ins->input.data=s;
328 ins->input.len=l;
329 ins->input.flags=0;
330 ins->input.next=NULL;
331 ins->flush=1;
332 bsdconv(ins);
333
334 RETVAL=newSVpvn(ins->output.data, (STRLEN)ins->output.len);
335 bsdconv_free(ins->output.data);
336 OUTPUT:
337 RETVAL
338
339 SV*
340 conv_file(ins, f1, f2)
341 Bsdconv ins
342 SV* f1
343 SV* f2
344 PREINIT:
345 char *s1, *s2;
346 SSize_t l;
347 FILE *inf, *otf;
348 char *in;
349 char *tmp;
350 int fd;
351 CODE:
352 s1=SvPV(f1, l);
353 s2=SvPV(f2, l);
354 inf=fopen(s1,"r");
355 if(!inf) XSRETURN_UNDEF;
356 tmp=malloc(l+8);
357 strcpy(tmp, s2);
358 strcat(tmp, ".XXXXXX");
359 if((fd=mkstemp(tmp))==-1){
360 free(tmp);
361 XSRETURN_UNDEF;
362 }
363 otf=fdopen(fd,"w");
364 if(!otf){
365 free(tmp);
366 XSRETURN_UNDEF;
367 }
368 #ifndef WIN32
369 struct stat stat;
370 fstat(fileno(inf), &stat);
371 fchown(fileno(otf), stat.st_uid, stat.st_gid);
372 fchmod(fileno(otf), stat.st_mode);
373 #endif
374 bsdconv_init(ins);
375 do{
376 in=bsdconv_malloc(IBUFLEN);
377 ins->input.data=in;
378 ins->input.len=fread(in, 1, IBUFLEN, inf);
379 ins->input.flags|=F_FREE;
380 ins->input.next=NULL;
381 if(ins->input.len==0){
382 ins->flush=1;
383 }
384 ins->output_mode=BSDCONV_FILE;
385 ins->output.data=otf;
386 bsdconv(ins);
387 }while(ins->flush==0);
388
389 fclose(inf);
390 fclose(otf);
391 unlink(s2);
392 rename(tmp,s2);
393 free(tmp);
394 XSRETURN_YES;
395 OUTPUT:
396 RETVAL
397
398 void
399 counter(ins, ...)
400 Bsdconv ins
401 PREINIT:
402 char *key;
403 HV *hash;
404 struct bsdconv_counter_entry *p;
405 bsdconv_counter_t *v;
406 PPCODE:
407 if(items > 1){
408 key=(char *)SvPV_nolen(ST(1));
409 v=bsdconv_counter(ins, key);
410 PUSHs(sv_2mortal(newSViv(*v)));
411 }else{
412 hash=(HV *)sv_2mortal((SV *)newHV());
413 p=ins->counter;
414 while(p){
415 hv_store(hash, p->key, strlen(p->key), newSVuv(p->val), 0);
416 p=p->next;
417 }
418 EXTEND(SP, 1);
419 PUSHs(newRV_noinc((SV *)hash));
420 }
421
422 void
counter_reset(ins,...)423 counter_reset(ins, ...)
424 Bsdconv ins
425 PREINIT:
426 char *key;
427 PPCODE:
428 if(items > 1){
429 key=(char *)SvPV_nolen(ST(1));
430 bsdconv_counter_reset(ins, key);
431 }else{
432 bsdconv_counter_reset(ins, NULL);
433 }
434
435 MODULE = bsdconv PACKAGE = Bsdconv_file
436
437 void
438 DESTROY(fp)
439 Bsdconv_file fp
440 CODE:
441 fclose(fp);
442