catori 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -0
- data/bin/catori +9 -0
- data/changelog.txt +3 -0
- data/construir +3 -0
- data/crear_vista.sql +8 -0
- data/ext/audiofile/MANIFEST +8 -0
- data/ext/audiofile/README +11 -0
- data/ext/audiofile/audiofile.c +833 -0
- data/ext/audiofile/audiofile.rd +265 -0
- data/ext/audiofile/depend +0 -0
- data/ext/audiofile/extconf.rb +8 -0
- data/ext/audiofile/fail.rb +22 -0
- data/ext/audiofile/mkmf.log +34 -0
- data/ext/audiofile/test.rb +229 -0
- data/ext/flac/extconf.rb +5 -0
- data/ext/flac/flac.c +75 -0
- data/ext/flac/mkmf.log +12 -0
- data/ext/flac/test.rb +3 -0
- data/ext/mahoro-0.1/INSTALL +9 -0
- data/ext/mahoro-0.1/extconf.rb +7 -0
- data/ext/mahoro-0.1/mahoro.c +187 -0
- data/ext/mahoro-0.1/mkmf.log +24 -0
- data/ext/mahoro-0.1/test.rb +41 -0
- data/ext/mpc/extconf.rb +5 -0
- data/ext/mpc/id3tag.c +245 -0
- data/ext/mpc/id3tag.h +5 -0
- data/ext/mpc/mkmf.log +12 -0
- data/ext/mpc/mpc.c +56 -0
- data/ext/mpc/mpp.h +194 -0
- data/ext/mpc/mppdec.h +1171 -0
- data/ext/mpc/test.rb +3 -0
- data/ext/rmac/extconf.rb +7 -0
- data/ext/rmac/mkmf.log +22 -0
- data/ext/rmac/rmac.cpp +162 -0
- data/ext/vorbisfile/ChangeLog +11 -0
- data/ext/vorbisfile/README +33 -0
- data/ext/vorbisfile/configure +2 -0
- data/ext/vorbisfile/extconf.rb +9 -0
- data/ext/vorbisfile/mkmf.log +68 -0
- data/ext/vorbisfile/test.rb +78 -0
- data/ext/vorbisfile/vorbisfile.c +482 -0
- data/instalar.txt +19 -0
- data/install.rb +11 -0
- data/lib/audioinfo.rb +321 -0
- data/lib/catori.rb +131 -0
- data/lib/catori/Catalogador.rb +71 -0
- data/lib/catori/Db.rb +81 -0
- data/lib/catori/Gui.rb +52 -0
- data/lib/catori/Installer.rb +16 -0
- data/lib/catori/Query.rb +82 -0
- data/lib/catori/XML.rb +42 -0
- data/lib/catori/catori_gui.glade +340 -0
- data/lib/catori/catori_gui.glade.bak +340 -0
- data/lib/catori/catori_gui.gladep +8 -0
- data/lib/catori/catori_gui.gladep.bak +8 -0
- data/lib/catori/taglib.rb +227 -0
- data/lib/pixmaps/album.png +0 -0
- data/lib/pixmaps/artist.png +0 -0
- data/lib/pixmaps/cdr.png +0 -0
- data/lib/pixmaps/song.png +0 -0
- data/lib/taglib.rb +230 -0
- data/sql/catori_mysql.sql +68 -0
- data/sql/catori_pg.sql +65 -0
- data/tests/saw.ape +0 -0
- data/tests/saw.flac +0 -0
- data/tests/saw.mp3 +0 -0
- data/tests/saw.mpc +0 -0
- data/tests/saw.ogg +0 -0
- data/tests/saw.wav +0 -0
- data/tests/test_audioinfo.rb +43 -0
- metadata +217 -0
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.5
|
data/bin/catori
ADDED
data/changelog.txt
ADDED
data/construir
ADDED
data/crear_vista.sql
ADDED
@@ -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,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
|
+
}
|