catori 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/VERSION +1 -0
  2. data/bin/catori +9 -0
  3. data/changelog.txt +3 -0
  4. data/construir +3 -0
  5. data/crear_vista.sql +8 -0
  6. data/ext/audiofile/MANIFEST +8 -0
  7. data/ext/audiofile/README +11 -0
  8. data/ext/audiofile/audiofile.c +833 -0
  9. data/ext/audiofile/audiofile.rd +265 -0
  10. data/ext/audiofile/depend +0 -0
  11. data/ext/audiofile/extconf.rb +8 -0
  12. data/ext/audiofile/fail.rb +22 -0
  13. data/ext/audiofile/mkmf.log +34 -0
  14. data/ext/audiofile/test.rb +229 -0
  15. data/ext/flac/extconf.rb +5 -0
  16. data/ext/flac/flac.c +75 -0
  17. data/ext/flac/mkmf.log +12 -0
  18. data/ext/flac/test.rb +3 -0
  19. data/ext/mahoro-0.1/INSTALL +9 -0
  20. data/ext/mahoro-0.1/extconf.rb +7 -0
  21. data/ext/mahoro-0.1/mahoro.c +187 -0
  22. data/ext/mahoro-0.1/mkmf.log +24 -0
  23. data/ext/mahoro-0.1/test.rb +41 -0
  24. data/ext/mpc/extconf.rb +5 -0
  25. data/ext/mpc/id3tag.c +245 -0
  26. data/ext/mpc/id3tag.h +5 -0
  27. data/ext/mpc/mkmf.log +12 -0
  28. data/ext/mpc/mpc.c +56 -0
  29. data/ext/mpc/mpp.h +194 -0
  30. data/ext/mpc/mppdec.h +1171 -0
  31. data/ext/mpc/test.rb +3 -0
  32. data/ext/rmac/extconf.rb +7 -0
  33. data/ext/rmac/mkmf.log +22 -0
  34. data/ext/rmac/rmac.cpp +162 -0
  35. data/ext/vorbisfile/ChangeLog +11 -0
  36. data/ext/vorbisfile/README +33 -0
  37. data/ext/vorbisfile/configure +2 -0
  38. data/ext/vorbisfile/extconf.rb +9 -0
  39. data/ext/vorbisfile/mkmf.log +68 -0
  40. data/ext/vorbisfile/test.rb +78 -0
  41. data/ext/vorbisfile/vorbisfile.c +482 -0
  42. data/instalar.txt +19 -0
  43. data/install.rb +11 -0
  44. data/lib/audioinfo.rb +321 -0
  45. data/lib/catori.rb +131 -0
  46. data/lib/catori/Catalogador.rb +71 -0
  47. data/lib/catori/Db.rb +81 -0
  48. data/lib/catori/Gui.rb +52 -0
  49. data/lib/catori/Installer.rb +16 -0
  50. data/lib/catori/Query.rb +82 -0
  51. data/lib/catori/XML.rb +42 -0
  52. data/lib/catori/catori_gui.glade +340 -0
  53. data/lib/catori/catori_gui.glade.bak +340 -0
  54. data/lib/catori/catori_gui.gladep +8 -0
  55. data/lib/catori/catori_gui.gladep.bak +8 -0
  56. data/lib/catori/taglib.rb +227 -0
  57. data/lib/pixmaps/album.png +0 -0
  58. data/lib/pixmaps/artist.png +0 -0
  59. data/lib/pixmaps/cdr.png +0 -0
  60. data/lib/pixmaps/song.png +0 -0
  61. data/lib/taglib.rb +230 -0
  62. data/sql/catori_mysql.sql +68 -0
  63. data/sql/catori_pg.sql +65 -0
  64. data/tests/saw.ape +0 -0
  65. data/tests/saw.flac +0 -0
  66. data/tests/saw.mp3 +0 -0
  67. data/tests/saw.mpc +0 -0
  68. data/tests/saw.ogg +0 -0
  69. data/tests/saw.wav +0 -0
  70. data/tests/test_audioinfo.rb +43 -0
  71. metadata +217 -0
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.5
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(File.symlink?(__FILE__)? File.readlink(__FILE__) : __FILE__)+"/../lib/")
3
+ #begin
4
+ require 'catori'
5
+ #rescue LoadError
6
+ # require 'rubygems'
7
+ # gem 'catori'
8
+ #end
9
+ Catori::App.new.run
@@ -0,0 +1,3 @@
1
+ CHANGELOG
2
+ 0.2.4 : Update support for ruby-mp3info (0.5.1)
3
+ 0.2.3 : Added support to Mysql and installer
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ gem build catori.gemspec
3
+ sudo gem install catori-0.2.5.gem
@@ -0,0 +1,8 @@
1
+ DROP VIEW vista_cd;
2
+ CREATE VIEW vista_cd as
3
+ SELECT cd_id,file_name, a.artist_name, b.album_name, ab.as_track, s.song_name
4
+ FROM FILE f JOIN artist a ON f.artist_id= a.artist_id
5
+ JOIN ALBUM b ON f.artist_id = b.artist_id AND f.album_id = b.album_id
6
+ JOIN album_song ab ON f.artist_id=ab.artist_id AND f.album_id=ab.album_id
7
+ and f.song_id=ab.song_id
8
+ JOIN song s ON f.song_id::text = s.song_id::text;
@@ -0,0 +1,8 @@
1
+ MANIFEST
2
+ audiofile.c
3
+ audiofile.rd
4
+ audiofile.html
5
+ depend
6
+ extconf.rb
7
+ fail.rb
8
+ test.rb
@@ -0,0 +1,11 @@
1
+ to install, run these commands:
2
+
3
+ ruby extconf.rb
4
+ make
5
+ su
6
+ make install
7
+
8
+ the audiofile library and headers are required.
9
+
10
+ enjoy!
11
+ -jared
@@ -0,0 +1,833 @@
1
+ /*********************************************************
2
+
3
+ audiofile.c
4
+
5
+ a Ruby extension to bind Ruby to audiofile
6
+ (http://dreamscape.68k.org/~michael/audiofile/)
7
+
8
+ patterned very very closely off of gdbm.c by matz in
9
+ the ruby 1.6.4 distribution. very closely. thanks matz!
10
+
11
+ $Author: jaredj $
12
+ $Date: 2001/07/26 04:31:45 $
13
+
14
+ *********************************************************/
15
+
16
+ /* conventions:
17
+ *
18
+ * _s_ in function name: singleton method
19
+ * fh : filehandle
20
+ * fn : filename
21
+ * af : audiofile
22
+ * p : pointer
23
+ */
24
+
25
+ /* assumptions:
26
+ * you always mean AF_DEFAULT_TRACK.
27
+ * the audiofile lib currently supports only formats with one track.
28
+ * so we'll always use AF_DEFAULT_TRACK, at least for
29
+ * this version of the bindings.
30
+ * (this doesn't mean one *channel*; stereo files are fully supported.)
31
+ *
32
+ *
33
+ * you will always set everything about the file before attempting to write it.
34
+ * (rate, bits, channels, byte_order, compression, file_format, sample_format)
35
+ */
36
+
37
+ /* things supported:
38
+ *
39
+ * opening/closing/flushing audio files
40
+ * reading frames into a new string and an existing one
41
+ * NEW: writing audio files from strings
42
+ * NEW: setting things about files to be created (sample rate, etc)
43
+ * moving forward/telling position in a file
44
+ * getting frame count & size
45
+ * getting real sample rate
46
+ * getting real byte order
47
+ * getting/setting virtual byte order
48
+ * calling all this from ruby
49
+ *
50
+ */
51
+
52
+ /* things not yet supported (in order of importance):
53
+ *
54
+ * raw-reading files well
55
+ * (afInitDataOffset not supported, so you can't skip headers easily)
56
+ * setting parameters for compression schemes when writing
57
+ * (this might make the ability to set the compression scheme useless)
58
+ * really correct error handling
59
+ * querying the capabilities of the audiofile library (afQuery)
60
+ * things relating to loops, instruments or non-strictly-audio data
61
+ * things that audiofile has API for but doesn't actually support yet
62
+ * (e.g., virtual sample rates and virtual compression schemes)
63
+ */
64
+
65
+ /* open doesn't appear to work, even though i copied it straight from
66
+ * matz's gdbm extenstion. */
67
+
68
+ #include "ruby.h"
69
+ #include <audiofile.h>
70
+
71
+ static VALUE cAudioFile, rb_eAudioFileError;
72
+
73
+ /* I know AFfilehandle is just a struct _AFfilehandle *
74
+ * but i chose to keep it in its own structure instead of
75
+ * just using the _AFfilehandle structure for future
76
+ * expansibility and caching stuff, like matz did in
77
+ * the gdbm ext.
78
+ */
79
+
80
+ struct af_data {
81
+ char *name;
82
+ // char mode;
83
+ int sample_format;
84
+ int sample_width;
85
+ AFfilehandle handle;
86
+ AFfilesetup setup;
87
+ };
88
+
89
+
90
+ /* this will pad 24-bit values to 32 bits.
91
+ * replace 1 with 0 to disable */
92
+ #define EXPAND_3TO4 1
93
+
94
+ static VALUE af_close(VALUE obj);
95
+
96
+
97
+ static void closed_af()
98
+ {
99
+ rb_raise(rb_eRuntimeError, "audio file already closed");
100
+ }
101
+
102
+ #define GetAFP(obj, afp) {\
103
+ Data_Get_Struct(obj, struct af_data, afp);\
104
+ if(afp == NULL) closed_af();\
105
+ if(afp->handle == AF_NULL_FILEHANDLE) closed_af();\
106
+ }
107
+
108
+ #define GetAFPWithoutOpenChecking(obj, afp) {\
109
+ Data_Get_Struct(obj, struct af_data, afp);\
110
+ }
111
+
112
+ static void free_af(struct af_data *afp)
113
+ {
114
+ if(afp) {
115
+ if(afp->handle) {
116
+ afCloseFile(afp->handle);
117
+ /* the error handler will get it */
118
+ }
119
+ if(afp->setup) {
120
+ afFreeFileSetup(afp->setup);
121
+ }
122
+ if(afp->name) {
123
+ free(afp->name);
124
+ }
125
+ free(afp);
126
+ }
127
+ }
128
+
129
+ static int af_is_open(struct af_data *afp)
130
+ {
131
+ if(afp) {
132
+ return (afp->handle != NULL);
133
+ } else {
134
+ rb_raise(rb_eRuntimeError, "somehow an AudioFile with no data was asked if it was open");
135
+ return 0;
136
+ }
137
+ }
138
+
139
+ static VALUE af_initialize(int argc, VALUE *argv, VALUE obj)
140
+ {
141
+ AFfilehandle fh;
142
+ struct af_data *afp;
143
+ /* struct af_file_setup *fsp;
144
+ AFfilesetup file_setup; */
145
+ char *mode, *fn;
146
+
147
+ VALUE v_return;
148
+ VALUE v_fn, v_mode, v_file_setup;
149
+
150
+
151
+ switch(rb_scan_args(argc, argv, "12", &v_fn, &v_mode, &v_file_setup)) {
152
+ case 1: /* only filename specified. use default (read) */
153
+
154
+ mode = malloc(2);
155
+ mode[0] = 'r';
156
+ mode[1] = '\0';
157
+
158
+ break;
159
+ case 2: /* filename & mode */
160
+ Check_Type(v_mode, T_STRING);
161
+
162
+ /* get mode into a C-string */
163
+ mode = malloc(2);
164
+ mode[0] = *(RSTRING(v_mode)->ptr);
165
+ mode[1] = '\0';
166
+
167
+ switch(*mode) {
168
+ case 'r':
169
+ case 'w':
170
+ /* OK */
171
+ break;
172
+ default:
173
+ rb_raise(rb_eArgError, "unknown mode specification");
174
+ break;
175
+ }
176
+ break;
177
+ default:
178
+ rb_raise(rb_eArgError, "wrong number of arguments");
179
+ break;
180
+ }
181
+
182
+ Check_Type(v_fn, T_STRING);
183
+
184
+ /* i don't know exactly what this does, but matz did it so it must work :) */
185
+ v_fn = rb_str_to_str(v_fn);
186
+ Check_SafeStr(v_fn);
187
+
188
+ switch(*mode) {
189
+ case 'r':
190
+
191
+ fh = afOpenFile(RSTRING(v_fn)->ptr, mode, AF_NULL_FILESETUP);
192
+ if(fh != AF_NULL_FILEHANDLE) {
193
+ afp = ALLOC(struct af_data);
194
+ DATA_PTR(obj) = afp;
195
+
196
+ /* default sample format and width. see af_sample_format_eq
197
+ * below for details about this ugly hack. */
198
+
199
+ afp->sample_format = AF_SAMPFMT_TWOSCOMP;
200
+ afp->sample_width = 16;
201
+
202
+ afp->name = NULL;
203
+ afp->setup = AF_NULL_FILESETUP;
204
+ afp->handle = fh;
205
+
206
+ v_return = obj;
207
+ } else {
208
+ v_return = Qnil;
209
+ }
210
+ free(mode);
211
+ break;
212
+
213
+ case 'w':
214
+
215
+ fn = malloc(RSTRING(v_fn)->len+1);
216
+ strcpy(fn, RSTRING(v_fn)->ptr);
217
+
218
+ afp = ALLOC(struct af_data);
219
+ DATA_PTR(obj) = afp;
220
+
221
+ afp->sample_format = AF_SAMPFMT_TWOSCOMP;
222
+ afp->sample_width = 16;
223
+
224
+ afp->name = fn;
225
+ afp->handle = AF_NULL_FILEHANDLE;
226
+ afp->setup = afNewFileSetup();
227
+
228
+ v_return = obj;
229
+ free(mode);
230
+ break;
231
+
232
+ default:
233
+ free(mode);
234
+ rb_raise(rb_eArgError, "unknown mode specified");
235
+ break;
236
+ }
237
+
238
+ return v_return;
239
+ }
240
+
241
+
242
+ static VALUE af_s_new(int argc, VALUE *argv, VALUE klass)
243
+ {
244
+ /* i don't know what the last param is in this 'call' */
245
+
246
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_af, 0);
247
+ rb_obj_call_init(obj, argc, argv);
248
+ return obj;
249
+ }
250
+
251
+ /* ---------------- fundamental methods -------------------------*/
252
+
253
+ static VALUE af_s_open(int argc, VALUE *argv, VALUE klass)
254
+ {
255
+
256
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_af, 0);
257
+
258
+ if(NIL_P(af_initialize(argc, argv, obj))) {
259
+ return Qnil;
260
+ }
261
+
262
+ if(rb_block_given_p()) {
263
+ return rb_ensure(rb_yield, obj, af_close, obj);
264
+ }
265
+
266
+ return obj;
267
+ }
268
+
269
+ static VALUE af_close(VALUE obj)
270
+ {
271
+ struct af_data *afp;
272
+
273
+ GetAFPWithoutOpenChecking(obj, afp);
274
+ if(af_is_open(afp)) {
275
+ afCloseFile(afp->handle);
276
+ afp->handle = AF_NULL_FILEHANDLE;
277
+ }
278
+
279
+ return Qnil;
280
+ }
281
+
282
+ static VALUE af_flush(VALUE obj)
283
+ {
284
+ struct af_data *afp;
285
+
286
+ GetAFP(obj, afp);
287
+ if(af_is_open(afp)) {
288
+ afSyncFile(afp->handle);
289
+ }
290
+
291
+ return obj;
292
+ }
293
+
294
+
295
+
296
+ static VALUE af_read(int argc, VALUE *argv, VALUE obj)
297
+ {
298
+ VALUE v_frames;
299
+ VALUE returnString;
300
+ struct af_data *afp;
301
+ long int frames, actual_frames, frame_size;
302
+ long int bytes, actual_bytes;
303
+ void *buf;
304
+
305
+ GetAFP(obj, afp);
306
+ if(rb_scan_args(argc, argv, "01", &v_frames) == 1) {
307
+ if(FIXNUM_P(v_frames)) {
308
+ frames = NUM2INT(v_frames);
309
+ } else {
310
+ rb_raise(rb_eArgError, "invalid argument to AudioFile#read");
311
+ }
312
+ } else {
313
+ frames = afGetFrameCount(afp->handle, AF_DEFAULT_TRACK);
314
+ }
315
+
316
+ frame_size = afGetFrameSize(afp->handle, AF_DEFAULT_TRACK, EXPAND_3TO4);
317
+ bytes = frames * frame_size;
318
+ buf = malloc(bytes);
319
+
320
+ actual_frames = afReadFrames(afp->handle, AF_DEFAULT_TRACK, buf, frames);
321
+ actual_bytes = actual_frames * frame_size;
322
+
323
+ returnString = rb_str_new(buf, actual_bytes);
324
+ return returnString;
325
+ }
326
+
327
+ static VALUE af_read_into(VALUE obj, VALUE readIntoString)
328
+ {
329
+ struct af_data *afp;
330
+ long int frames, actual_frames, frame_size;
331
+ long int bytes, actual_bytes;
332
+ void *buf;
333
+
334
+ GetAFP(obj, afp);
335
+
336
+
337
+ Check_Type(readIntoString, T_STRING);
338
+ bytes = RSTRING(readIntoString)->len;
339
+ buf = RSTRING(readIntoString)->ptr;
340
+
341
+ frame_size = afGetFrameSize(afp->handle, AF_DEFAULT_TRACK, EXPAND_3TO4);
342
+ frames = bytes / frame_size;
343
+
344
+ actual_frames = afReadFrames(afp->handle, AF_DEFAULT_TRACK, buf, frames);
345
+ actual_bytes = actual_frames * frame_size;
346
+
347
+ return INT2NUM(actual_bytes);
348
+ }
349
+
350
+ static VALUE actually_write(VALUE obj, VALUE writeFromString)
351
+ {
352
+ struct af_data *afp;
353
+ long int frames, actual_frames, frame_size;
354
+ long int bytes, actual_bytes;
355
+ void *buf;
356
+
357
+ GetAFP(obj, afp);
358
+
359
+ Check_Type(writeFromString, T_STRING);
360
+ bytes = RSTRING(writeFromString)->len;
361
+ buf = RSTRING(writeFromString)->ptr;
362
+
363
+ frame_size = afGetFrameSize(afp->handle, AF_DEFAULT_TRACK, EXPAND_3TO4);
364
+ frames = bytes / frame_size;
365
+
366
+ actual_frames = afWriteFrames(afp->handle, AF_DEFAULT_TRACK, buf, frames);
367
+ actual_bytes = actual_frames * frame_size;
368
+
369
+ return INT2NUM(actual_bytes);
370
+ }
371
+
372
+ static VALUE af_write(VALUE obj, VALUE writeFromString)
373
+ {
374
+ struct af_data *afp;
375
+
376
+ GetAFPWithoutOpenChecking(obj, afp);
377
+ if(af_is_open(afp)) {
378
+ return actually_write(obj, writeFromString);
379
+ } else {
380
+ if(afp->name) {
381
+ afp->handle = afOpenFile(afp->name, "w", afp->setup);
382
+ free(afp->name);
383
+ afp->name = NULL;
384
+
385
+ return actually_write(obj, writeFromString);
386
+ } else {
387
+ rb_raise(rb_eAudioFileError, "write attempted on apparently unopenable file");
388
+ return Qnil;
389
+ }
390
+ }
391
+ }
392
+
393
+
394
+
395
+ /* ------ getters --------------------------------------------------------*/
396
+
397
+ static VALUE af_frame_size(VALUE obj)
398
+ {
399
+ struct af_data *afp;
400
+
401
+ GetAFP(obj, afp);
402
+ return INT2NUM((afGetFrameSize(afp->handle, AF_DEFAULT_TRACK, EXPAND_3TO4)));
403
+ }
404
+
405
+ static VALUE af_frame_count(VALUE obj)
406
+ {
407
+ struct af_data *afp;
408
+
409
+ GetAFP(obj, afp);
410
+ return INT2NUM((afGetFrameCount(afp->handle, AF_DEFAULT_TRACK)));
411
+ }
412
+
413
+ static VALUE af_pos(VALUE obj)
414
+ {
415
+ struct af_data *afp;
416
+
417
+ GetAFP(obj, afp);
418
+ return INT2NUM((afTellFrame(afp->handle, AF_DEFAULT_TRACK)));
419
+ }
420
+
421
+ static VALUE af_sample_rate(VALUE obj)
422
+ {
423
+ struct af_data *afp;
424
+
425
+ GetAFP(obj, afp);
426
+ return INT2NUM((afGetRate(afp->handle, AF_DEFAULT_TRACK)));
427
+ }
428
+
429
+
430
+ static VALUE af_byte_order(VALUE obj)
431
+ {
432
+ struct af_data *afp;
433
+ int byte_order;
434
+
435
+ GetAFP(obj, afp);
436
+ byte_order = afGetByteOrder(afp->handle, AF_DEFAULT_TRACK);
437
+
438
+ /* for now */
439
+ return INT2NUM(byte_order);
440
+ }
441
+
442
+ static VALUE af_virtual_byte_order(VALUE obj)
443
+ {
444
+ struct af_data *afp;
445
+ int byte_order;
446
+
447
+ GetAFP(obj, afp);
448
+ byte_order = afGetVirtualByteOrder(afp->handle, AF_DEFAULT_TRACK);
449
+
450
+ /* for now */
451
+ return INT2NUM(byte_order);
452
+ }
453
+
454
+ static VALUE af_channels(VALUE obj)
455
+ {
456
+ struct af_data *afp;
457
+
458
+ GetAFP(obj, afp);
459
+
460
+ return INT2NUM(afGetChannels(afp->handle, AF_DEFAULT_TRACK));
461
+ }
462
+
463
+
464
+ static VALUE af_sample_format(VALUE obj)
465
+ {
466
+ struct af_data *afp;
467
+ int format, width;
468
+
469
+ GetAFP(obj, afp);
470
+
471
+ afGetSampleFormat(afp->handle, AF_DEFAULT_TRACK, &format, &width);
472
+ return INT2FIX(format);
473
+ }
474
+
475
+ static VALUE af_sample_width(VALUE obj)
476
+ {
477
+ struct af_data *afp;
478
+ int format, width;
479
+
480
+ GetAFP(obj, afp);
481
+
482
+ afGetSampleFormat(afp->handle, AF_DEFAULT_TRACK, &format, &width);
483
+ return INT2FIX(width);
484
+ }
485
+
486
+ static VALUE af_compression(VALUE obj)
487
+ {
488
+ struct af_data *afp;
489
+
490
+ GetAFP(obj, afp);
491
+
492
+ return INT2NUM(afGetCompression(afp->handle, AF_DEFAULT_TRACK));
493
+ }
494
+
495
+ static VALUE af_pcm_mapping(VALUE obj)
496
+ {
497
+ struct af_data *afp;
498
+ double slope, intercept, min_clip, max_clip;
499
+
500
+ GetAFP(obj, afp);
501
+
502
+ afGetPCMMapping(afp->handle, AF_DEFAULT_TRACK, &slope,
503
+ &intercept, &min_clip, &max_clip);
504
+
505
+ return rb_ary_new3(4,
506
+ rb_float_new(slope),
507
+ rb_float_new(intercept),
508
+ rb_float_new(min_clip),
509
+ rb_float_new(max_clip));
510
+ }
511
+
512
+
513
+ static VALUE af_file_format(VALUE obj)
514
+ {
515
+ struct af_data *afp;
516
+ int ver;
517
+
518
+ GetAFP(obj, afp);
519
+
520
+ return INT2NUM(afGetFileFormat(afp->handle, &ver));
521
+ }
522
+
523
+ static VALUE af_file_format_version(VALUE obj)
524
+ {
525
+ struct af_data *afp;
526
+ int ver;
527
+
528
+ GetAFP(obj, afp);
529
+ afGetFileFormat(afp->handle, &ver);
530
+
531
+ return INT2NUM(ver);
532
+ }
533
+
534
+ /*
535
+ * ------ setters --------------------------------------------------------
536
+ */
537
+
538
+ static VALUE af_pos_eq(VALUE obj, VALUE new_pos)
539
+ {
540
+ struct af_data *afp;
541
+ AFfileoffset here, there;
542
+
543
+ GetAFP(obj, afp);
544
+ here = afTellFrame(afp->handle, AF_DEFAULT_TRACK);
545
+ there = NUM2INT(new_pos);
546
+ if(there >= here) {
547
+ return INT2NUM((afSeekFrame(afp->handle, AF_DEFAULT_TRACK, (there - here))));
548
+ } else {
549
+ rb_raise(rb_eArgError, "cannot seek backwards");
550
+ }
551
+ }
552
+
553
+
554
+ #define ATTEMPT(foo) ("attempt to set " foo " on an already-open file")
555
+ static void bail_if_open(struct af_data *afp, const char *message)
556
+ {
557
+ if(af_is_open(afp)) {
558
+ rb_raise(rb_eAudioFileError, message);
559
+ }
560
+ }
561
+
562
+ static VALUE af_file_format_eq(VALUE obj, VALUE format)
563
+ {
564
+ struct af_data *afp;
565
+
566
+ GetAFPWithoutOpenChecking(obj, afp);
567
+ bail_if_open(afp, ATTEMPT("file format"));
568
+
569
+ afInitFileFormat(afp->setup, NUM2INT(format));
570
+ return format;
571
+ }
572
+
573
+ static VALUE af_sample_rate_eq(VALUE obj, VALUE rate)
574
+ {
575
+ struct af_data *afp;
576
+
577
+ GetAFPWithoutOpenChecking(obj, afp);
578
+
579
+ bail_if_open(afp, ATTEMPT("sample rate"));
580
+
581
+ afInitRate(afp->setup, AF_DEFAULT_TRACK, NUM2INT(rate));
582
+ return rate;
583
+ }
584
+
585
+ static VALUE af_byte_order_eq(VALUE obj, VALUE byte_order)
586
+ {
587
+ struct af_data *afp;
588
+
589
+ GetAFPWithoutOpenChecking(obj, afp);
590
+ bail_if_open(afp, ATTEMPT("byte order"));
591
+
592
+ afInitByteOrder(afp->setup, AF_DEFAULT_TRACK, NUM2INT(byte_order));
593
+ return byte_order;
594
+ }
595
+
596
+ static VALUE af_virtual_byte_order_eq(VALUE obj, VALUE new_bo)
597
+ {
598
+ struct af_data *afp;
599
+
600
+ GetAFP(obj, afp);
601
+
602
+ /* for now */
603
+ afSetVirtualByteOrder(afp->handle, AF_DEFAULT_TRACK, NUM2INT(new_bo));
604
+
605
+ return new_bo;
606
+ }
607
+
608
+ static VALUE af_channels_eq(VALUE obj, VALUE channels)
609
+ {
610
+ struct af_data *afp;
611
+
612
+ GetAFPWithoutOpenChecking(obj, afp);
613
+
614
+ bail_if_open(afp, ATTEMPT("channels"));
615
+
616
+ afInitChannels(afp->setup, AF_DEFAULT_TRACK, NUM2INT(channels));
617
+ return channels;
618
+ }
619
+
620
+ /* Details about this dirty hack.
621
+ * I added two members, sample_format and sample_width, to the
622
+ * af_data structure because you can only set them both at a time,
623
+ * and you can't get inside the AFfilesetup structure prettily.
624
+ * So those are to preserve what you set the sample_format to so
625
+ * that the sample_width can set it to that, and vice versa.
626
+ * They only have defaults so that your program won't barf if you
627
+ * don't explicitly set one or both. Course, your program will barf
628
+ * if you don't set the rest of the stuff in the filesetup structure
629
+ * anyway... unless afNewFileSetup makes the new filesetup have defaults
630
+ *
631
+ */
632
+
633
+ static VALUE af_sample_format_eq(VALUE obj, VALUE sample_format)
634
+ {
635
+ struct af_data *afp;
636
+
637
+ GetAFPWithoutOpenChecking(obj, afp);
638
+ bail_if_open(afp, ATTEMPT("sample format"));
639
+
640
+ afp->sample_format = NUM2INT(sample_format);
641
+ afInitSampleFormat(afp->setup, AF_DEFAULT_TRACK,
642
+ afp->sample_format,
643
+ afp->sample_width);
644
+ return sample_format;
645
+ }
646
+
647
+ static VALUE af_sample_width_eq(VALUE obj, VALUE sample_width)
648
+ {
649
+ struct af_data *afp;
650
+
651
+ GetAFPWithoutOpenChecking(obj, afp);
652
+ bail_if_open(afp, ATTEMPT("sample width"));
653
+
654
+ afp->sample_width = NUM2INT(sample_width);
655
+ afInitSampleFormat(afp->setup, AF_DEFAULT_TRACK,
656
+ afp->sample_format,
657
+ afp->sample_width);
658
+ return sample_width;
659
+ }
660
+
661
+ static VALUE af_compression_eq(VALUE obj, VALUE compression)
662
+ {
663
+ struct af_data *afp;
664
+ GetAFPWithoutOpenChecking(obj, afp);
665
+ bail_if_open(afp, ATTEMPT("compression scheme"));
666
+
667
+ afInitCompression(afp->setup, AF_DEFAULT_TRACK, NUM2INT(compression));
668
+ return compression;
669
+ }
670
+
671
+
672
+
673
+
674
+
675
+ static VALUE af_pcm_mapping_eq(VALUE obj, VALUE args)
676
+ {
677
+ VALUE v_slope, v_intercept, v_min_clip, v_max_clip;
678
+ /* double slope, intercept, min_clip, max_clip; */
679
+ struct af_data *afp;
680
+
681
+ Check_Type(args, T_ARRAY);
682
+ if(RARRAY(args)->len != 1) {
683
+ rb_raise(rb_eArgError, "incorrect argument(s) to AudioFile#pcm_mapping=");
684
+ }
685
+ args = *(RARRAY(args)->ptr);
686
+ if(RARRAY(args)->len != 4) {
687
+ rb_raise(rb_eArgError, "incorrect argument(s) to AudioFile#pcm_mapping=");
688
+ }
689
+
690
+ v_slope = RARRAY(args)->ptr[0];
691
+ v_intercept = RARRAY(args)->ptr[1];
692
+ v_min_clip = RARRAY(args)->ptr[2];
693
+ v_max_clip = RARRAY(args)->ptr[3];
694
+ Check_Type(v_slope, T_FLOAT);
695
+ Check_Type(v_intercept, T_FLOAT);
696
+ Check_Type(v_min_clip, T_FLOAT);
697
+ Check_Type(v_max_clip, T_FLOAT);
698
+
699
+ GetAFPWithoutOpenChecking(obj, afp);
700
+
701
+ if(af_is_open(afp)) {
702
+ afSetTrackPCMMapping(afp->handle, AF_DEFAULT_TRACK,
703
+ RFLOAT(v_slope)->value, RFLOAT(v_intercept)->value,
704
+ RFLOAT(v_min_clip)->value, RFLOAT(v_max_clip)->value);
705
+ } else {
706
+ afInitPCMMapping(afp->setup, AF_DEFAULT_TRACK,
707
+ RFLOAT(v_slope)->value, RFLOAT(v_intercept)->value,
708
+ RFLOAT(v_min_clip)->value, RFLOAT(v_max_clip)->value);
709
+ }
710
+
711
+ return Qnil;
712
+ }
713
+
714
+
715
+ void af_error_function(long error_num, const char *message)
716
+ {
717
+ rb_raise(rb_eAudioFileError, message);
718
+ }
719
+
720
+ void Init_audiofile()
721
+ {
722
+ struct {
723
+ const char *name;
724
+ VALUE (*func)();
725
+ int args;
726
+ } instance_methods[] = {
727
+ { "initialize", af_initialize, -1 },
728
+ { "close", af_close, 0 },
729
+ { "read", af_read, -1 },
730
+ { "flush", af_flush, 0 },
731
+ { "write", af_write, 1 },
732
+ { "read_into", af_read_into, 1 },
733
+ { "frame_size", af_frame_size, 0 },
734
+ { "frame_count", af_frame_count, 0 },
735
+
736
+ /* getters */
737
+ { "pos", af_pos, 0 },
738
+ { "rate", af_sample_rate, 0 },
739
+ { "bits", af_sample_width, 0 },
740
+ { "channels", af_channels, 0 },
741
+ { "byte_order", af_byte_order, 0 },
742
+ { "compression", af_compression, 0 },
743
+ { "file_format", af_file_format, 0 },
744
+ { "sample_format", af_sample_format, 0 },
745
+ { "virtual_byte_order", af_virtual_byte_order, 0 },
746
+ { "pcm_mapping", af_pcm_mapping, 0 },
747
+ { "file_format_version", af_file_format_version, 0 },
748
+
749
+ /* setters */
750
+ { "pos=", af_pos_eq, 1 },
751
+ { "rate=", af_sample_rate_eq, 1 },
752
+ { "bits=", af_sample_width_eq, 1 },
753
+ { "channels=", af_channels_eq, 1 },
754
+ { "byte_order=", af_byte_order_eq, 1 },
755
+ { "compression=", af_compression_eq, 1 },
756
+ { "file_format=", af_file_format_eq, 1 },
757
+ { "sample_format=", af_sample_format_eq, 1 },
758
+ { "virtual_byte_order=", af_virtual_byte_order_eq, 1 },
759
+ { "pcm_mapping=", af_pcm_mapping_eq, -2 },
760
+ { 0 }
761
+ };
762
+
763
+ struct {
764
+ const char *name;
765
+ VALUE value;
766
+ } constants[] = {
767
+ { "BIG_ENDIAN", INT2FIX(AF_BYTEORDER_BIGENDIAN) },
768
+ { "LITTLE_ENDIAN", INT2FIX(AF_BYTEORDER_LITTLEENDIAN) },
769
+
770
+ { "TWOS_COMPLEMENT", INT2FIX(AF_SAMPFMT_TWOSCOMP) },
771
+ { "UNSIGNED", INT2FIX(AF_SAMPFMT_UNSIGNED) },
772
+ { "FLOAT", INT2FIX(AF_SAMPFMT_FLOAT) },
773
+ { "DOUBLE", INT2FIX(AF_SAMPFMT_DOUBLE) },
774
+
775
+ { "COMPRESSION_UNKNOWN", INT2FIX(AF_COMPRESSION_UNKNOWN) },
776
+ { "NONE", INT2FIX(AF_COMPRESSION_NONE) },
777
+ { "G722", INT2FIX(AF_COMPRESSION_G722) },
778
+ { "G711_ULAW", INT2FIX(AF_COMPRESSION_G711_ULAW) },
779
+ { "G711_ALAW", INT2FIX(AF_COMPRESSION_G711_ALAW) },
780
+ { "APPLE_ACE2", INT2FIX(AF_COMPRESSION_APPLE_ACE2) },
781
+ { "APPLE_ACE8", INT2FIX(AF_COMPRESSION_APPLE_ACE8) },
782
+ { "APPLE_MAC3", INT2FIX(AF_COMPRESSION_APPLE_MAC3) },
783
+ { "APPLE_MAC6", INT2FIX(AF_COMPRESSION_APPLE_MAC6) },
784
+ { "G726", INT2FIX(AF_COMPRESSION_G726) },
785
+ { "G728", INT2FIX(AF_COMPRESSION_G728) },
786
+ { "DVI_AUDIO", INT2FIX(AF_COMPRESSION_DVI_AUDIO) },
787
+ { "GSM", INT2FIX(AF_COMPRESSION_GSM) },
788
+ { "FS1016", INT2FIX(AF_COMPRESSION_FS1016) },
789
+
790
+ { "FILE_UNKNOWN", INT2FIX(AF_FILE_UNKNOWN) },
791
+ { "RAW", INT2FIX(AF_FILE_RAWDATA) },
792
+ { "AIFF_C", INT2FIX(AF_FILE_AIFFC) },
793
+ { "AIFF", INT2FIX(AF_FILE_AIFF) },
794
+ { "NEXT_SND", INT2FIX(AF_FILE_NEXTSND) },
795
+ { "WAV", INT2FIX(AF_FILE_WAVE) },
796
+ { 0 }
797
+ };
798
+
799
+ int i;
800
+
801
+ afSetErrorHandler(af_error_function);
802
+
803
+ cAudioFile = rb_define_class("AudioFile", rb_cObject);
804
+ rb_eAudioFileError = rb_define_class("AudioFileError", rb_eStandardError);
805
+
806
+ rb_define_singleton_method(cAudioFile, "new", af_s_new, -1);
807
+ rb_define_singleton_method(cAudioFile, "open", af_s_open, -1);
808
+
809
+ for(i=0; instance_methods[i].name; i++) {
810
+ rb_define_method(cAudioFile, instance_methods[i].name,
811
+ instance_methods[i].func, instance_methods[i].args);
812
+ }
813
+
814
+ /*rb_define_method(cAudioFile, "pcm_mapping", af_pcm_mapping, 0);
815
+ *
816
+ * afGetPCMMapping is declared in audiofile.h, but not defined in
817
+ * libaudiofile.so! So I can't call it. So this method doesn't get defined.
818
+ *
819
+ */
820
+
821
+
822
+ /*
823
+ * these might need synchronization with other people's constants
824
+ * this would require changing the sample_format and other functions
825
+ * (see "for now" in above functions.)
826
+ *
827
+ */
828
+
829
+ for(i=0; constants[i].name; i++) {
830
+ rb_define_const(cAudioFile, constants[i].name, constants[i].value);
831
+ }
832
+
833
+ }