supernova: fix for small audio vector sizes
[supercollider.git] / lang / LangPrimSource / PyrFilePrim.cpp
blobeae2025a79fefcab89eb5773511134198638f02b
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU 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.
11 This program 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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 Primitives for File i/o.
27 #include "GC.h"
28 #include "PyrKernel.h"
29 #include "PyrPrimitive.h"
30 #include "PyrSymbol.h"
31 #include "PyrFilePrim.h"
32 #include "PyrFileUtils.h"
33 #include "ReadWriteMacros.h"
34 #include "SCBase.h"
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdarg.h>
38 #include <cerrno>
40 #ifdef NOCLASSIC
41 #include <TextUtils.h>
42 #include <Navigation.h>
43 #endif
45 #ifndef _WIN32
46 # include <unistd.h>
47 #else
48 # include <direct.h>
49 # include <malloc.h>
50 # define strcasecmp stricmp
51 #endif
53 #ifdef _WIN32
54 #include <stdio.h>
55 #include "SC_Win32Utils.h"
56 #include "SC_DirUtils.h"
57 #endif
59 #include <fcntl.h>
60 #include <math.h>
62 #define DELIMITOR ':'
64 bool filelen(FILE *file, size_t *length);
66 int prFileDelete(struct VMGlobals *g, int numArgsPushed)
68 PyrSlot *a, *b;
69 char filename[PATH_MAX];
71 a = g->sp - 1;
72 b = g->sp;
73 if (NotObj(b) || !isKindOf(slotRawObject(b), class_string))
74 return errWrongType;
75 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
77 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
78 filename[slotRawString(b)->size] = 0;
80 int err = unlink(filename);
81 SetBool(a, err == 0);
83 return errNone;
87 int prFileOpen(struct VMGlobals *g, int numArgsPushed)
89 PyrSlot *a, *b, *c;
90 char filename[PATH_MAX];
91 char mode[12];
92 PyrFile *pfile;
93 FILE *file;
95 a = g->sp - 2;
96 b = g->sp - 1;
97 c = g->sp;
98 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
99 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
100 return errWrongType;
101 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
102 if (slotRawObject(c)->size > 11) return errFailed;
103 pfile = (PyrFile*)slotRawObject(a);
105 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
106 filename[slotRawString(b)->size] = 0;
108 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
109 mode[slotRawString(c)->size] = 0;
111 #ifdef SC_WIN32
112 win32_ReplaceCharInString(filename,PATH_MAX,'/','\\');
113 if(strcmp(mode,"w") == 0)
114 strcpy(mode,"wb");
115 if(strcmp(mode,"r") == 0)
116 strcpy(mode,"rb");
117 #endif
118 //SC_WIN32
119 file = fopen(filename, mode);
120 if (file) {
121 SetPtr(&pfile->fileptr, file);
122 SetTrue(a);
123 } else {
124 #ifdef SC_WIN32
125 // check if directory exisits
126 // create a temporary file (somewhere) for a handle
127 // the file is deleted automatically when closed
128 if (sc_DirectoryExists(filename)) {
129 int err;
130 #ifdef _MSC_VER
131 err = tmpfile_s(&file);
132 if (!err) {
133 SetPtr(&pfile->fileptr, file);
134 SetTrue(a);
135 return errNone;
137 #elif defined(__MINGW32__)
138 file = tmpfile();
139 if (file) {
140 SetPtr(&pfile->fileptr, file);
141 SetTrue(a);
142 return errNone;
144 #else
145 #error compiler unsupported
146 #endif
148 #endif
149 SetNil(a);
150 SetFalse(a);
152 return errNone;
155 int prFileClose(struct VMGlobals *g, int numArgsPushed)
157 PyrSlot *a;
158 PyrFile *pfile;
159 FILE *file;
161 a = g->sp;
162 pfile = (PyrFile*)slotRawObject(a);
163 file = (FILE*)slotRawPtr(&pfile->fileptr);
164 if (file == NULL) return errNone;
165 SetPtr(&pfile->fileptr, NULL);
166 if (fclose(file)) return errFailed;
167 return errNone;
170 int prFileFlush(struct VMGlobals *g, int numArgsPushed)
172 PyrSlot *a;
173 PyrFile *pfile;
174 FILE *file;
176 a = g->sp;
177 pfile = (PyrFile*)slotRawObject(a);
178 file = (FILE*)slotRawPtr(&pfile->fileptr);
179 if (file != NULL) fflush(file);
180 return errNone;
183 int prFilePos(struct VMGlobals *g, int numArgsPushed)
185 PyrSlot *a;
186 PyrFile *pfile;
187 FILE *file;
188 fpos_t pos;
189 int length;
191 a = g->sp;
192 pfile = (PyrFile*)slotRawObject(a);
193 file = (FILE*)slotRawPtr(&pfile->fileptr);
194 if (file == NULL) return errFailed;
195 if (fgetpos(file, &pos)) return errFailed;
197 #ifdef SC_LINUX
198 // sk: hack alert!
199 length = pos.__pos;
200 #else
201 length = pos;
202 #endif
204 SetInt(a, length);
205 return errNone;
208 int prFileLength(struct VMGlobals *g, int numArgsPushed)
210 PyrSlot *a;
211 PyrFile *pfile;
212 FILE *file;
213 fpos_t pos;
214 size_t length;
216 a = g->sp;
217 pfile = (PyrFile*)slotRawObject(a);
218 file = (FILE*)slotRawPtr(&pfile->fileptr);
219 if (file == NULL) return errFailed;
220 // preserve file position
221 if (fgetpos(file, &pos)) return errFailed;
222 if (filelen(file, &length)) return errFailed;
223 if (fsetpos(file, &pos)) return errFailed;
225 SetInt(a, length);
226 return errNone;
229 int prFileSeek(struct VMGlobals *g, int numArgsPushed)
231 PyrSlot *a, *b, *c;
232 PyrFile *pfile;
233 FILE *file;
234 size_t offset;
235 int origin;
236 static int originTable[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
238 a = g->sp - 2;
239 b = g->sp - 1;
240 c = g->sp;
241 if (NotInt(b)) return errWrongType;
242 if (NotInt(c)) return errWrongType;
243 pfile = (PyrFile*)slotRawObject(a);
244 file = (FILE*)slotRawPtr(&pfile->fileptr);
245 if (file == NULL) return errFailed;
246 offset = slotRawInt(b);
247 origin = slotRawInt(c);
248 if (origin < 0 || origin > 2) return errIndexOutOfRange;
249 origin = originTable[origin]; // translate in case ANSI constants ever change..
250 if (fseek(file, offset, origin)) return errFailed;
251 return errNone;
255 int prFileWrite(struct VMGlobals *g, int numArgsPushed)
257 PyrSlot *a, *b, *ptr;
258 PyrFile *pfile;
259 FILE *file;
260 PyrObject *obj;
261 char chr;
263 a = g->sp - 1;
264 b = g->sp;
265 pfile = (PyrFile*)slotRawObject(a);
266 file = (FILE*)slotRawPtr(&pfile->fileptr);
267 if (file == NULL) return errFailed;
268 switch (GetTag(b)) {
269 case tagInt :
271 SC_IOStream<FILE*> scio(file);
272 scio.writeInt32_be(slotRawInt(b));
273 break;
275 case tagSym :
276 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
277 break;
278 case tagChar :
279 chr = slotRawChar(b);
280 fwrite(&chr, sizeof(char), 1, file);
281 break;
282 case tagNil :
283 case tagFalse :
284 case tagTrue :
285 case tagPtr :
286 return errWrongType;
287 case tagObj :
289 // writes the indexable part of any non obj_slot format object
290 obj = slotRawObject(b);
291 if (!isKindOf(obj, class_rawarray)
292 || isKindOf(obj, class_symbolarray)) return errWrongType;
293 if (obj->size) {
294 ptr = obj->slots;
295 int elemSize = gFormatElemSize[obj->obj_format];
296 int numElems = obj->size;
297 #if BYTE_ORDER != BIG_ENDIAN
298 switch (elemSize) {
299 case 1:
300 fwrite(ptr, elemSize, numElems, file);
301 break;
302 case 2:
304 char *ptr = slotRawString(b)->s;
305 char *ptrend = ptr + numElems*2;
306 for (; ptr < ptrend; ptr+=2) {
307 fputc(ptr[1], file);
308 fputc(ptr[0], file);
310 break;
312 case 4:
314 char *ptr = slotRawString(b)->s;
315 char *ptrend = ptr + numElems*4;
316 for (; ptr < ptrend; ptr+=4) {
317 fputc(ptr[3], file);
318 fputc(ptr[2], file);
319 fputc(ptr[1], file);
320 fputc(ptr[0], file);
322 break;
324 case 8:
326 char *ptr = slotRawString(b)->s;
327 char *ptrend = ptr + numElems*8;
328 for (; ptr < ptrend; ptr+=8) {
329 fputc(ptr[7], file);
330 fputc(ptr[6], file);
331 fputc(ptr[5], file);
332 fputc(ptr[4], file);
333 fputc(ptr[3], file);
334 fputc(ptr[2], file);
335 fputc(ptr[1], file);
336 fputc(ptr[0], file);
338 break;
341 #else
342 fwrite(ptr, elemSize, numElems, file);
343 #endif
345 break;
347 default : // double
349 SC_IOStream<FILE*> scio(file);
350 scio.writeDouble_be(slotRawFloat(b));
351 break;
354 return errNone;
358 int prFileWriteLE(struct VMGlobals *g, int numArgsPushed)
360 PyrSlot *a, *b, *ptr;
361 PyrFile *pfile;
362 FILE *file;
363 PyrObject *obj;
364 char chr;
366 a = g->sp - 1;
367 b = g->sp;
368 pfile = (PyrFile*)slotRawObject(a);
369 file = (FILE*)slotRawPtr(&pfile->fileptr);
370 if (file == NULL) return errFailed;
371 switch (GetTag(b)) {
372 case tagInt :
374 SC_IOStream<FILE*> scio(file);
375 scio.writeInt32_le(slotRawInt(b));
376 break;
378 case tagSym :
379 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
380 break;
381 case tagChar :
382 chr = slotRawInt(b);
383 fwrite(&chr, sizeof(char), 1, file);
384 break;
385 case tagNil :
386 case tagFalse :
387 case tagTrue :
388 case tagPtr :
389 return errWrongType;
390 case tagObj :
392 // writes the indexable part of any non obj_slot format object
393 obj = slotRawObject(b);
394 if (!isKindOf(obj, class_rawarray)
395 || isKindOf(obj, class_symbolarray)) return errWrongType;
396 if (obj->size) {
397 ptr = obj->slots;
398 int elemSize = gFormatElemSize[obj->obj_format];
399 int numElems = obj->size;
400 #if BYTE_ORDER == BIG_ENDIAN
401 switch (elemSize) {
402 case 1:
403 fwrite(ptr, elemSize, numElems, file);
404 break;
405 case 2:
407 char *ptr = slotRawString(b)->s;
408 char *ptrend = ptr + numElems*2;
409 for (; ptr < ptrend; ptr+=2) {
410 fputc(ptr[1], file);
411 fputc(ptr[0], file);
413 break;
415 case 4:
417 char *ptr = slotRawString(b)->s;
418 char *ptrend = ptr + numElems*4;
419 for (; ptr < ptrend; ptr+=4) {
420 fputc(ptr[3], file);
421 fputc(ptr[2], file);
422 fputc(ptr[1], file);
423 fputc(ptr[0], file);
425 break;
427 case 8:
429 char *ptr = slotRawString(b)->s;
430 char *ptrend = ptr + numElems*8;
431 for (; ptr < ptrend; ptr+=8) {
432 fputc(ptr[7], file);
433 fputc(ptr[6], file);
434 fputc(ptr[5], file);
435 fputc(ptr[4], file);
436 fputc(ptr[3], file);
437 fputc(ptr[2], file);
438 fputc(ptr[1], file);
439 fputc(ptr[0], file);
441 break;
444 #else
445 fwrite(ptr, elemSize, numElems, file);
446 #endif
448 break;
450 default : // double
452 SC_IOStream<FILE*> scio(file);
453 scio.writeDouble_le(slotRawFloat(b));
454 break;
457 return errNone;
460 int prFileReadLine(struct VMGlobals *g, int numArgsPushed)
462 PyrSlot *a, *b; // receiver(a File), string
463 PyrFile *pfile;
464 FILE *file;
466 a = g->sp - 1;
467 b = g->sp;
469 pfile = (PyrFile*)slotRawObject(a);
470 file = (FILE*)slotRawPtr(&pfile->fileptr);
471 if (file == NULL) return errFailed;
473 char* result = fgets(slotRawString(b)->s, MAXINDEXSIZE(slotRawObject(b)) - 1, file);
474 if (!result) {
475 SetNil(a);
476 } else {
477 slotRawString(b)->size = strlen(slotRawString(b)->s);
478 if (slotRawString(b)->s[slotRawString(b)->size-1] == '\n') slotRawString(b)->size--;
479 slotCopy(a,b);
481 return errNone;
484 int prFilePutInt32(struct VMGlobals *g, int numArgsPushed)
486 PyrSlot *a, *b;
487 PyrFile *pfile;
488 FILE *file;
490 a = g->sp - 1;
491 b = g->sp;
493 pfile = (PyrFile*)slotRawObject(a);
494 file = (FILE*)slotRawPtr(&pfile->fileptr);
495 if (file == NULL) return errFailed;
497 int val;
498 int err = slotIntVal(b, &val);
499 if (err) return err;
501 SC_IOStream<FILE*> scio(file);
502 scio.writeInt32_be(val);
504 return errNone;
507 int prFilePutInt16(struct VMGlobals *g, int numArgsPushed)
509 PyrSlot *a, *b;
510 PyrFile *pfile;
511 FILE *file;
513 a = g->sp - 1;
514 b = g->sp;
516 pfile = (PyrFile*)slotRawObject(a);
517 file = (FILE*)slotRawPtr(&pfile->fileptr);
518 if (file == NULL) return errFailed;
520 int val;
521 int err = slotIntVal(b, &val);
522 if (err) return err;
525 SC_IOStream<FILE*> scio(file);
526 scio.writeInt16_be(val);
528 return errNone;
532 int prFilePutInt32LE(struct VMGlobals *g, int numArgsPushed)
534 PyrSlot *a, *b;
535 PyrFile *pfile;
536 FILE *file;
538 a = g->sp - 1;
539 b = g->sp;
541 pfile = (PyrFile*)slotRawObject(a);
542 file = (FILE*)slotRawPtr(&pfile->fileptr);
543 if (file == NULL) return errFailed;
545 int val;
546 int err = slotIntVal(b, &val);
547 if (err) return err;
549 SC_IOStream<FILE*> scio(file);
550 scio.writeInt32_le(val);
552 return errNone;
555 int prFilePutInt16LE(struct VMGlobals *g, int numArgsPushed)
557 PyrSlot *a, *b;
558 PyrFile *pfile;
559 FILE *file;
561 a = g->sp - 1;
562 b = g->sp;
564 pfile = (PyrFile*)slotRawObject(a);
565 file = (FILE*)slotRawPtr(&pfile->fileptr);
566 if (file == NULL) return errFailed;
568 int val;
569 int err = slotIntVal(b, &val);
570 if (err) return err;
573 SC_IOStream<FILE*> scio(file);
574 scio.writeInt16_le(val);
576 return errNone;
579 int prFilePutInt8(struct VMGlobals *g, int numArgsPushed)
581 PyrSlot *a, *b;
582 PyrFile *pfile;
583 FILE *file;
585 a = g->sp - 1;
586 b = g->sp;
588 pfile = (PyrFile*)slotRawObject(a);
589 file = (FILE*)slotRawPtr(&pfile->fileptr);
590 if (file == NULL) return errFailed;
592 int val;
593 int err = slotIntVal(b, &val);
594 if (err) return err;
597 SC_IOStream<FILE*> scio(file);
598 scio.writeInt8(val);
600 return errNone;
603 int prFilePutChar(struct VMGlobals *g, int numArgsPushed)
605 PyrSlot *a, *b;
606 PyrFile *pfile;
607 FILE *file;
608 char z;
610 a = g->sp - 1;
611 b = g->sp;
613 pfile = (PyrFile*)slotRawObject(a);
614 file = (FILE*)slotRawPtr(&pfile->fileptr);
615 if (file == NULL) return errFailed;
616 if (NotChar(b)) return errWrongType;
618 z = slotRawInt(b);
620 SC_IOStream<FILE*> scio(file);
621 scio.writeInt8(z);
623 return errNone;
626 int prFilePutFloat(struct VMGlobals *g, int numArgsPushed)
628 PyrSlot *a, *b;
629 PyrFile *pfile;
630 FILE *file;
632 a = g->sp - 1;
633 b = g->sp;
635 pfile = (PyrFile*)slotRawObject(a);
636 file = (FILE*)slotRawPtr(&pfile->fileptr);
637 if (file == NULL) {
638 dumpObjectSlot(a);
639 return errFailed;
642 float val;
643 int err = slotFloatVal(b, &val);
644 if (err) return err;
646 SC_IOStream<FILE*> scio(file);
647 scio.writeFloat_be(val);
649 return errNone;
652 int prFilePutDouble(struct VMGlobals *g, int numArgsPushed)
654 PyrSlot *a, *b;
655 PyrFile *pfile;
656 FILE *file;
658 a = g->sp - 1;
659 b = g->sp;
661 pfile = (PyrFile*)slotRawObject(a);
662 file = (FILE*)slotRawPtr(&pfile->fileptr);
663 if (file == NULL) return errFailed;
666 double val;
667 int err = slotDoubleVal(b, &val);
668 if (err) return err;
670 SC_IOStream<FILE*> scio(file);
671 scio.writeDouble_be(val);
673 return errNone;
677 int prFilePutFloatLE(struct VMGlobals *g, int numArgsPushed)
679 PyrSlot *a, *b;
680 PyrFile *pfile;
681 FILE *file;
683 a = g->sp - 1;
684 b = g->sp;
686 pfile = (PyrFile*)slotRawObject(a);
687 file = (FILE*)slotRawPtr(&pfile->fileptr);
688 if (file == NULL) {
689 dumpObjectSlot(a);
690 return errFailed;
693 float val;
694 int err = slotFloatVal(b, &val);
695 if (err) return err;
697 SC_IOStream<FILE*> scio(file);
698 scio.writeFloat_le(val);
700 return errNone;
703 int prFilePutDoubleLE(struct VMGlobals *g, int numArgsPushed)
705 PyrSlot *a, *b;
706 PyrFile *pfile;
707 FILE *file;
709 a = g->sp - 1;
710 b = g->sp;
712 pfile = (PyrFile*)slotRawObject(a);
713 file = (FILE*)slotRawPtr(&pfile->fileptr);
714 if (file == NULL) return errFailed;
717 double val;
718 int err = slotDoubleVal(b, &val);
719 if (err) return err;
721 SC_IOStream<FILE*> scio(file);
722 scio.writeDouble_le(val);
724 return errNone;
727 int prFilePutString(struct VMGlobals *g, int numArgsPushed)
729 PyrSlot *a, *b;
730 PyrFile *pfile;
731 FILE *file;
732 PyrString *string;
734 a = g->sp - 1;
735 b = g->sp;
736 pfile = (PyrFile*)slotRawObject(a);
737 file = (FILE*)slotRawPtr(&pfile->fileptr);
738 if (file == NULL) return errFailed;
739 if (NotObj(b) || slotRawObject(b)->classptr != class_string) return errWrongType;
740 string = slotRawString(b);
741 if (string->size) {
742 fwrite(string->s, 1, string->size, file);
744 return errNone;
748 int prFileGetDouble(struct VMGlobals *g, int numArgsPushed)
750 PyrSlot *a;
751 PyrFile *pfile;
752 FILE *file;
754 a = g->sp;
756 pfile = (PyrFile*)slotRawObject(a);
757 file = (FILE*)slotRawPtr(&pfile->fileptr);
758 if (file == NULL) return errFailed;
760 if (feof(file)) SetNil(a);
761 else {
762 SC_IOStream<FILE*> scio(file);
763 SetFloat(a, scio.readDouble_be());
765 return errNone;
768 int prFileGetFloat(struct VMGlobals *g, int numArgsPushed)
770 PyrSlot *a;
771 PyrFile *pfile;
772 FILE *file;
774 a = g->sp;
776 pfile = (PyrFile*)slotRawObject(a);
777 file = (FILE*)slotRawPtr(&pfile->fileptr);
778 if (file == NULL) return errFailed;
780 if (feof(file)) SetNil(a);
781 else {
782 SC_IOStream<FILE*> scio(file);
783 SetFloat(a, scio.readFloat_be());
785 return errNone;
789 int prFileGetDoubleLE(struct VMGlobals *g, int numArgsPushed)
791 PyrSlot *a;
792 PyrFile *pfile;
793 FILE *file;
795 a = g->sp;
797 pfile = (PyrFile*)slotRawObject(a);
798 file = (FILE*)slotRawPtr(&pfile->fileptr);
799 if (file == NULL) return errFailed;
801 if (feof(file)) SetNil(a);
802 else {
803 SC_IOStream<FILE*> scio(file);
804 SetFloat(a, scio.readDouble_le());
806 return errNone;
809 int prFileGetFloatLE(struct VMGlobals *g, int numArgsPushed)
811 PyrSlot *a;
812 PyrFile *pfile;
813 FILE *file;
815 a = g->sp;
817 pfile = (PyrFile*)slotRawObject(a);
818 file = (FILE*)slotRawPtr(&pfile->fileptr);
819 if (file == NULL) return errFailed;
821 if (feof(file)) SetNil(a);
822 else {
823 SC_IOStream<FILE*> scio(file);
824 SetFloat(a, scio.readFloat_le());
826 return errNone;
829 int prFileGetChar(struct VMGlobals *g, int numArgsPushed)
831 PyrSlot *a;
832 PyrFile *pfile;
833 FILE *file;
834 char z;
836 a = g->sp;
838 pfile = (PyrFile*)slotRawObject(a);
839 file = (FILE*)slotRawPtr(&pfile->fileptr);
840 if (file == NULL) return errFailed;
842 int count = fread(&z, sizeof(char), 1, file);
843 if (count==0) SetNil(a);
844 else SetChar(a, z);
845 return errNone;
848 int prFileGetInt8(struct VMGlobals *g, int numArgsPushed)
850 PyrSlot *a;
851 PyrFile *pfile;
852 FILE *file;
853 char z;
855 a = g->sp;
857 pfile = (PyrFile*)slotRawObject(a);
858 file = (FILE*)slotRawPtr(&pfile->fileptr);
859 if (file == NULL) return errFailed;
861 int count = fread(&z, sizeof(char), 1, file);
862 if (count==0) SetNil(a);
863 else SetInt(a, z);
864 return errNone;
867 int prFileGetInt16(struct VMGlobals *g, int numArgsPushed)
869 PyrSlot *a;
870 PyrFile *pfile;
871 FILE *file;
873 a = g->sp;
875 pfile = (PyrFile*)slotRawObject(a);
876 file = (FILE*)slotRawPtr(&pfile->fileptr);
877 if (file == NULL) return errFailed;
879 if (feof(file)) SetNil(a);
880 else {
881 SC_IOStream<FILE*> scio(file);
882 SetInt(a, scio.readInt16_be());
884 return errNone;
887 int prFileGetInt32(struct VMGlobals *g, int numArgsPushed)
889 PyrSlot *a;
890 PyrFile *pfile;
891 FILE *file;
893 a = g->sp;
895 pfile = (PyrFile*)slotRawObject(a);
896 file = (FILE*)slotRawPtr(&pfile->fileptr);
897 if (file == NULL)
898 return errFailed;
900 if (feof(file)) SetNil(a);
901 else {
902 SC_IOStream<FILE*> scio(file);
903 SetInt(a, scio.readInt32_be());
905 return errNone;
909 int prFileGetInt16LE(struct VMGlobals *g, int numArgsPushed)
911 PyrSlot *a;
912 PyrFile *pfile;
913 FILE *file;
915 a = g->sp;
917 pfile = (PyrFile*)slotRawObject(a);
918 file = (FILE*)slotRawPtr(&pfile->fileptr);
919 if (file == NULL) return errFailed;
921 if (feof(file)) SetNil(a);
922 else {
923 SC_IOStream<FILE*> scio(file);
924 SetInt(a, scio.readInt16_le());
926 return errNone;
929 int prFileGetInt32LE(struct VMGlobals *g, int numArgsPushed)
931 PyrSlot *a;
932 PyrFile *pfile;
933 FILE *file;
935 a = g->sp;
937 pfile = (PyrFile*)slotRawObject(a);
938 file = (FILE*)slotRawPtr(&pfile->fileptr);
939 if (file == NULL) return errFailed;
941 if (feof(file)) SetNil(a);
942 else {
943 SC_IOStream<FILE*> scio(file);
944 SetInt(a, scio.readInt32_le());
946 return errNone;
949 int prFileReadRaw(struct VMGlobals *g, int numArgsPushed)
951 PyrFile *pfile;
952 FILE *file;
954 PyrSlot* a = g->sp - 1;
955 PyrSlot* b = g->sp;
957 if (!isKindOfSlot(b, class_rawarray)
958 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
960 pfile = (PyrFile*)slotRawObject(a);
961 file = (FILE*)slotRawPtr(&pfile->fileptr);
962 if (file == NULL) return errFailed;
964 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
965 int numElems = slotRawObject(b)->size;
966 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
967 slotRawObject(b)->size = numElems;
969 #if BYTE_ORDER != BIG_ENDIAN
970 switch (elemSize) {
971 case 1:
972 break;
973 case 2:
975 char *ptr = slotRawString(b)->s;
976 char *ptrend = ptr + numElems*2;
977 for (; ptr < ptrend; ptr+=2) {
978 char temp = ptr[0];
979 ptr[0] = ptr[1];
980 ptr[1] = temp;
982 break;
984 case 4:
986 char *ptr = slotRawString(b)->s;
987 char *ptrend = ptr + numElems*4;
988 for (; ptr < ptrend; ptr+=4) {
989 char temp = ptr[0];
990 ptr[0] = ptr[3];
991 ptr[3] = temp;
993 temp = ptr[1];
994 ptr[1] = ptr[2];
995 ptr[2] = temp;
997 break;
999 case 8:
1001 char *ptr = slotRawString(b)->s;
1002 char *ptrend = ptr + numElems*8;
1003 for (; ptr < ptrend; ptr+=8) {
1004 char temp = ptr[0];
1005 ptr[0] = ptr[7];
1006 ptr[7] = temp;
1008 temp = ptr[1];
1009 ptr[1] = ptr[6];
1010 ptr[6] = temp;
1012 temp = ptr[2];
1013 ptr[2] = ptr[5];
1014 ptr[5] = temp;
1016 temp = ptr[3];
1017 ptr[3] = ptr[4];
1018 ptr[4] = temp;
1020 break;
1023 #endif
1025 if (slotRawObject(b)->size==0) SetNil(a);
1026 else slotCopy(a,b);
1027 return errNone;
1030 int prFileReadRawLE(struct VMGlobals *g, int numArgsPushed)
1032 PyrFile *pfile;
1033 FILE *file;
1035 PyrSlot* a = g->sp - 1;
1036 PyrSlot* b = g->sp;
1038 if (!isKindOfSlot(b, class_rawarray)
1039 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1041 pfile = (PyrFile*)slotRawObject(a);
1042 file = (FILE*)slotRawPtr(&pfile->fileptr);
1043 if (file == NULL) return errFailed;
1045 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1046 int numElems = slotRawObject(b)->size;
1047 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1048 slotRawObject(b)->size = numElems;
1050 #if BYTE_ORDER == BIG_ENDIAN
1051 switch (elemSize) {
1052 case 1:
1053 break;
1054 case 2:
1056 char *ptr = slotRawString(b)->s;
1057 char *ptrend = ptr + numElems*2;
1058 for (; ptr < ptrend; ptr+=2) {
1059 char temp = ptr[0];
1060 ptr[0] = ptr[1];
1061 ptr[1] = temp;
1063 break;
1065 case 4:
1067 char *ptr = slotRawString(b)->s;
1068 char *ptrend = ptr + numElems*4;
1069 for (; ptr < ptrend; ptr+=4) {
1070 char temp = ptr[0];
1071 ptr[0] = ptr[3];
1072 ptr[3] = temp;
1074 temp = ptr[1];
1075 ptr[1] = ptr[2];
1076 ptr[2] = temp;
1078 break;
1080 case 8:
1082 char *ptr = slotRawString(b)->s;
1083 char *ptrend = ptr + numElems*8;
1084 for (; ptr < ptrend; ptr+=8) {
1085 char temp = ptr[0];
1086 ptr[0] = ptr[7];
1087 ptr[7] = temp;
1089 temp = ptr[1];
1090 ptr[1] = ptr[6];
1091 ptr[6] = temp;
1093 temp = ptr[2];
1094 ptr[2] = ptr[5];
1095 ptr[5] = temp;
1097 temp = ptr[3];
1098 ptr[3] = ptr[4];
1099 ptr[4] = temp;
1101 break;
1104 #endif
1106 if (slotRawObject(b)->size==0) SetNil(a);
1107 else slotCopy(a,b);
1108 return errNone;
1111 int prFileGetcwd(struct VMGlobals *g, int numArgsPushed)
1113 //PyrSlot* a = g->sp - 1; // File
1114 PyrSlot* string = g->sp;
1116 if (!isKindOfSlot(string, class_string)) return errWrongType;
1118 char * cwd = getcwd(slotRawString(string)->s,255);
1119 if (cwd == NULL) {
1120 error(strerror(errno));
1121 return errFailed;
1123 slotRawString(string)->size = strlen(slotRawString(string)->s);
1125 return errNone;
1128 ////////
1130 #ifndef SC_WIN32
1131 int prPipeOpen(struct VMGlobals *g, int numArgsPushed)
1133 PyrSlot *a, *b, *c;
1134 char mode[12];
1135 PyrFile *pfile;
1136 FILE *file;
1138 a = g->sp - 2;
1139 b = g->sp - 1;
1140 c = g->sp;
1142 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
1143 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
1144 return errWrongType;
1145 if (slotRawObject(c)->size > 11) return errFailed;
1146 pfile = (PyrFile*)slotRawObject(a);
1148 char *commandLine = (char*)malloc(slotRawObject(b)->size + 1);
1149 memcpy(commandLine, slotRawString(b)->s, slotRawObject(b)->size);
1150 commandLine[slotRawString(b)->size] = 0;
1152 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
1153 mode[slotRawString(c)->size] = 0;
1155 file = popen(commandLine, mode);
1156 free(commandLine);
1157 if (file) {
1158 SetPtr(&pfile->fileptr, file);
1159 SetTrue(a);
1160 } else {
1161 SetNil(a);
1162 SetFalse(a);
1164 return errNone;
1167 int prPipeClose(struct VMGlobals *g, int numArgsPushed)
1169 PyrSlot *a;
1170 PyrFile *pfile;
1171 FILE *file;
1173 a = g->sp;
1174 pfile = (PyrFile*)slotRawObject(a);
1175 file = (FILE*)slotRawPtr(&pfile->fileptr);
1176 if (file == NULL) return errNone;
1177 SetPtr(&pfile->fileptr, NULL);
1178 int perr = pclose(file);
1179 SetInt(a, perr);
1180 if (perr == -1)
1181 return errFailed;
1182 return errNone;
1184 #endif
1186 ////////
1188 #ifndef NO_LIBSNDFILE
1190 #ifdef SC_WIN32
1191 #include <sndfile-win.h>
1192 #else
1193 #include <sndfile.h>
1194 #endif
1197 int sampleFormatToString(struct SF_INFO *info, const char **string);
1198 int sampleFormatToString(struct SF_INFO *info, const char **string)
1200 unsigned int format = info->format & SF_FORMAT_SUBMASK;
1201 switch (format)
1203 case SF_FORMAT_DPCM_8:
1204 case SF_FORMAT_PCM_S8:
1205 *string = "int16";
1206 break;
1207 case SF_FORMAT_DPCM_16:
1208 case SF_FORMAT_PCM_16:
1209 case SF_FORMAT_DWVW_16:
1210 *string = "int16";
1211 break;
1212 case SF_FORMAT_PCM_24:
1213 case SF_FORMAT_DWVW_24:
1214 *string = "int24";
1215 break;
1216 case SF_FORMAT_PCM_32:
1217 *string = "int32";
1218 break;
1219 case SF_FORMAT_FLOAT:
1220 *string = "float";
1221 break;
1222 case SF_FORMAT_DOUBLE:
1223 *string = "double";
1224 break;
1225 case SF_FORMAT_ULAW:
1226 *string = "ulaw";
1227 break;
1228 case SF_FORMAT_ALAW:
1229 *string = "alaw";
1230 break;
1231 default:
1232 *string = "float";
1233 break;
1235 return errNone;
1239 int headerFormatToString(struct SF_INFO *info, const char **string);
1240 int headerFormatToString(struct SF_INFO *info, const char **string){
1241 switch (info->format & SF_FORMAT_TYPEMASK)
1243 case SF_FORMAT_WAV :
1244 *string = "WAV";
1245 break;
1246 case SF_FORMAT_AIFF :
1247 *string = "AIFF";
1248 break ;
1249 case SF_FORMAT_AU :
1250 *string = "SUN";
1251 break ;
1252 case SF_FORMAT_IRCAM :
1253 *string = "IRCAM";
1254 break ;
1255 case SF_FORMAT_RAW :
1256 *string = "raw";
1257 break ;
1258 case SF_FORMAT_W64 :
1259 *string = "WAV";
1260 break ;
1261 case SF_FORMAT_FLAC :
1262 *string = "FLAC";
1263 break ;
1264 // TODO allow other platforms to know vorbis once libsndfile 1.0.18 is established
1265 #if SC_DARWIN || SC_WIN32 || LIBSNDFILE_1018
1266 case SF_FORMAT_VORBIS :
1267 *string = "vorbis";
1268 break ;
1269 #endif
1271 case SF_FORMAT_PAF :
1273 break ;
1275 case SF_FORMAT_SVX :
1277 break ;
1279 case SF_FORMAT_NIST :
1281 break ;
1283 case SF_FORMAT_VOC :
1285 break ;
1287 case SF_FORMAT_MAT4 :
1289 break ;
1291 case SF_FORMAT_MAT5 :
1293 break ;
1295 case SF_FORMAT_PVF :
1297 break ;
1299 case SF_FORMAT_XI :
1301 break ;
1303 case SF_FORMAT_HTK :
1305 break ;
1307 case SF_FORMAT_SDS :
1309 break ;
1311 default :
1312 *string = " ";
1313 break ;
1315 return errNone;
1318 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample);
1319 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample)
1321 int error = 0;
1322 error = headerFormatToString(info, stringHead);
1323 error = sampleFormatToString(info, stringSample);
1324 return error;
1327 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed);
1328 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1330 PyrSlot *a, *b;
1331 char filename[PATH_MAX];
1332 SNDFILE *file;
1333 SF_INFO info;
1334 const char *headerstr;
1335 const char *sampleformatstr;
1337 a = g->sp - 1;
1338 b = g->sp;
1340 if (!isKindOfSlot(b, class_string)) return errWrongType;
1341 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1343 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1344 filename[slotRawString(b)->size] = 0;
1346 info.format = 0;
1347 file = sf_open(filename, SFM_READ, &info);
1350 if (file) {
1351 SetPtr(slotRawObject(a)->slots + 0, file);
1352 sndfileFormatInfoToStrings(&info, &headerstr, &sampleformatstr);
1353 //headerFormatToString(&info, &headerstr);
1354 PyrString *hpstr = newPyrString(g->gc, headerstr, 0, true);
1355 SetObject(slotRawObject(a)->slots+1, hpstr);
1356 PyrString *smpstr = newPyrString(g->gc, sampleformatstr, 0, true);
1357 SetObject(slotRawObject(a)->slots+2, smpstr);
1358 SetInt(slotRawObject(a)->slots + 3, info.frames);
1359 SetInt(slotRawObject(a)->slots + 4, info.channels);
1360 SetInt(slotRawObject(a)->slots + 5, info.samplerate);
1362 SetTrue(a);
1363 } else {
1364 SetNil(a);
1365 SetFalse(a);
1367 return errNone;
1369 /// copied from SC_World.cpp:
1371 int sampleFormatFromString(const char* name);
1372 int sampleFormatFromString(const char* name)
1374 if (!name) return SF_FORMAT_PCM_16;
1376 size_t len = strlen(name);
1377 if (len < 1) return 0;
1379 if (name[0] == 'u') {
1380 if (len < 5) return 0;
1381 if (name[4] == '8') return SF_FORMAT_PCM_U8; // uint8
1382 return 0;
1383 } else if (name[0] == 'i') {
1384 if (len < 4) return 0;
1385 if (name[3] == '8') return SF_FORMAT_PCM_S8; // int8
1386 else if (name[3] == '1') return SF_FORMAT_PCM_16; // int16
1387 else if (name[3] == '2') return SF_FORMAT_PCM_24; // int24
1388 else if (name[3] == '3') return SF_FORMAT_PCM_32; // int32
1389 } else if (name[0] == 'f') {
1390 return SF_FORMAT_FLOAT; // float
1391 } else if (name[0] == 'd') {
1392 return SF_FORMAT_DOUBLE; // double
1393 } else if (name[0] == 'm' || name[0] == 'u') {
1394 return SF_FORMAT_ULAW; // mulaw ulaw
1395 } else if (name[0] == 'a') {
1396 return SF_FORMAT_ALAW; // alaw
1398 return 0;
1401 int headerFormatFromString(const char *name);
1402 int headerFormatFromString(const char *name)
1404 if (!name) return SF_FORMAT_AIFF;
1405 if (strcasecmp(name, "AIFF")==0) return SF_FORMAT_AIFF;
1406 if (strcasecmp(name, "AIFC")==0) return SF_FORMAT_AIFF;
1407 if (strcasecmp(name, "RIFF")==0) return SF_FORMAT_WAV;
1408 if (strcasecmp(name, "WAVEX")==0) return SF_FORMAT_WAVEX;
1409 if (strcasecmp(name, "WAVE")==0) return SF_FORMAT_WAV;
1410 if (strcasecmp(name, "WAV" )==0) return SF_FORMAT_WAV;
1411 if (strcasecmp(name, "Sun" )==0) return SF_FORMAT_AU;
1412 if (strcasecmp(name, "IRCAM")==0) return SF_FORMAT_IRCAM;
1413 if (strcasecmp(name, "NeXT")==0) return SF_FORMAT_AU;
1414 if (strcasecmp(name, "raw")==0) return SF_FORMAT_RAW;
1415 if (strcasecmp(name, "MAT4")==0) return SF_FORMAT_MAT4;
1416 if (strcasecmp(name, "MAT5")==0) return SF_FORMAT_MAT5;
1417 if (strcasecmp(name, "PAF")==0) return SF_FORMAT_PAF;
1418 if (strcasecmp(name, "SVX")==0) return SF_FORMAT_SVX;
1419 if (strcasecmp(name, "NIST")==0) return SF_FORMAT_NIST;
1420 if (strcasecmp(name, "VOC")==0) return SF_FORMAT_VOC;
1421 if (strcasecmp(name, "W64")==0) return SF_FORMAT_W64;
1422 if (strcasecmp(name, "PVF")==0) return SF_FORMAT_PVF;
1423 if (strcasecmp(name, "XI")==0) return SF_FORMAT_XI;
1424 if (strcasecmp(name, "HTK")==0) return SF_FORMAT_HTK;
1425 if (strcasecmp(name, "SDS")==0) return SF_FORMAT_SDS;
1426 if (strcasecmp(name, "AVR")==0) return SF_FORMAT_AVR;
1427 if (strcasecmp(name, "SD2")==0) return SF_FORMAT_SD2;
1428 if (strcasecmp(name, "FLAC")==0) return SF_FORMAT_FLAC;
1429 if (strcasecmp(name, "CAF")==0) return SF_FORMAT_CAF;
1430 // TODO allow other platforms to know vorbis once libsndfile 1.0.18 is established
1431 #if SC_DARWIN || SC_WIN32
1432 if (strcasecmp(name, "VORBIS")==0) return SF_FORMAT_VORBIS;
1433 #endif
1434 return 0;
1438 int sndfileFormatInfoFromStrings(struct SF_INFO *info, const char *headerFormatString, const char *sampleFormatString)
1440 int headerFormat = headerFormatFromString(headerFormatString);
1441 if (!headerFormat) return errWrongType;
1443 int sampleFormat = sampleFormatFromString(sampleFormatString);
1444 if (!sampleFormat) return errWrongType;
1446 info->format = (unsigned int)(headerFormat | sampleFormat);
1447 return errNone;
1449 // end copy
1451 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed);
1452 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1454 PyrSlot *a, *b;
1455 char filename[PATH_MAX];
1456 SNDFILE *file;
1457 SF_INFO info;
1458 PyrSlot *headerSlot;
1459 PyrSlot *formatSlot;
1460 int error;
1463 a = g->sp - 1;
1464 b = g->sp;
1466 headerSlot = (slotRawObject(a)->slots + 1);
1467 formatSlot = (slotRawObject(a)->slots + 2);
1470 if (!isKindOfSlot(headerSlot, class_string)) return errWrongType;
1471 if (!isKindOfSlot(formatSlot, class_string)) return errWrongType;
1473 if (!isKindOfSlot(b, class_string)) return errWrongType;
1474 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1476 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1477 filename[slotRawString(b)->size] = 0;
1479 #ifdef SC_WIN32
1480 char* headerFormat = (char *)malloc(slotRawObject(headerSlot)->size);
1481 #else
1482 char headerFormat[slotRawString(headerSlot)->size];
1483 #endif
1484 memcpy(headerFormat, slotRawString(headerSlot)->s, slotRawObject(headerSlot)->size);
1485 headerFormat[slotRawString(headerSlot)->size] = 0;
1487 #ifdef SC_WIN32
1488 char* sampleFormat = (char *)malloc(slotRawString(formatSlot)->size);
1489 #else
1490 char sampleFormat[slotRawString(formatSlot)->size];
1491 #endif
1492 memcpy(sampleFormat, slotRawString(formatSlot)->s, slotRawObject(formatSlot)->size);
1493 sampleFormat[slotRawString(formatSlot)->size] = 0;
1495 error = sndfileFormatInfoFromStrings(&info, headerFormat, sampleFormat);
1496 if(error) {
1497 #ifdef SC_WIN32
1498 free(sampleFormat);
1499 free(headerFormat);
1500 #endif
1501 return errFailed;
1504 if(error) return errFailed;
1505 //slotIntVal(slotRawObject(a)->slots + 3, &info.frames);
1506 slotIntVal(slotRawObject(a)->slots + 4, &info.channels);
1507 slotIntVal(slotRawObject(a)->slots + 5, &info.samplerate);
1509 file = sf_open(filename, SFM_WRITE, &info);
1510 if (file) {
1511 SetPtr(slotRawObject(a)->slots+0, file);
1512 SetTrue(a);
1513 } else {
1514 SetNil(a);
1515 SetFalse(a);
1518 return errNone;
1521 int prSFClose(struct VMGlobals *g, int numArgsPushed);
1522 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1524 PyrSlot *a;
1526 a = g->sp;
1528 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1529 if (file) {
1530 sf_close(file);
1531 SetNil(slotRawObject(a)->slots + 0);
1534 return errNone;
1537 int prSFRead(struct VMGlobals *g, int numArgsPushed);
1538 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1540 PyrSlot *a, *b;
1542 a = g->sp - 1;
1543 b = g->sp;
1545 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1547 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1549 switch (slotRawObject(b)->obj_format) {
1550 case obj_int16 :
1551 slotRawObject(b)->size = sf_read_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1552 break;
1553 case obj_int32 :
1554 slotRawObject(b)->size = sf_read_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1555 break;
1556 case obj_float :
1557 slotRawObject(b)->size = sf_read_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1558 break;
1559 case obj_double :
1560 slotRawObject(b)->size = sf_read_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1561 break;
1562 default:
1563 error("sample format not supported.\n");
1564 return errFailed;
1567 return errNone;
1570 int prSFWrite(struct VMGlobals *g, int numArgsPushed);
1571 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1573 PyrSlot *a, *b;
1575 a = g->sp - 1;
1576 b = g->sp;
1578 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1580 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1582 switch (slotRawObject(b)->obj_format) {
1583 case obj_int16 :
1584 sf_write_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1585 break;
1586 case obj_int32 :
1587 sf_write_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1588 break;
1589 case obj_float :
1590 sf_write_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1591 break;
1592 case obj_double :
1593 sf_write_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1594 break;
1595 default:
1596 error("sample format not supported.\n");
1597 return errFailed;
1600 return errNone;
1603 int prSFSeek(struct VMGlobals *g, int numArgsPushed);
1604 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1606 PyrSlot *a, *b, *c;
1608 a = g->sp - 2;
1609 b = g->sp - 1;
1610 c = g->sp;
1612 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1614 int origin, offset;
1615 int err = slotIntVal(b, &offset);
1616 if (err) return err;
1618 err = slotIntVal(c, &origin);
1619 if (err) return err;
1621 sf_seek(file, offset, origin);
1623 return errNone;
1626 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed);
1627 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1630 PyrSlot *a;
1631 a = g->sp;
1632 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1633 if(file){
1634 static char strbuffer [(1 << 16)] ;
1635 sf_command (file, SFC_GET_LOG_INFO, strbuffer, (1 << 16)) ;
1636 PyrString *pstring = newPyrString(g->gc, strbuffer, 0, true);
1637 // post(strbuffer);
1638 SetObject(a, pstring);
1639 return errNone;
1641 return errFailed;
1644 #else // !NO_LIBSNDFILE
1646 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1648 return errFailed;
1651 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1653 return errFailed;
1656 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1658 return errFailed;
1661 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1663 return errFailed;
1666 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1668 return errFailed;
1671 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1673 return errFailed;
1676 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1678 return errFailed;
1681 #endif // !NO_LIBSNDFILE
1684 //////////
1685 #ifdef NOCLASSIC
1687 int dir_Lookup(char *pathString, int pathStringLength, int index,
1688 /* outputs: */
1689 char *name, int *nameLength, int *creationDate, int *modificationDate,
1690 int *isDirectory, int *isVisible, int *sizeIfFile);
1692 int prDirectory_At(struct VMGlobals *g, int numArgsPushed);
1693 int prDirectory_At(struct VMGlobals *g, int numArgsPushed)
1695 PyrSlot *a = g->sp - 2;
1696 PyrSlot *b = g->sp - 1;
1697 PyrSlot *c = g->sp;
1699 PyrSlot *dirPathSlot = slotRawObject(a)->slots + 0;
1700 int err, index;
1701 err = slotIntVal(c, &index);
1702 if (err) {
1703 SetNil(a);
1704 return err;
1707 char name[256], fullPathName[256];
1708 int nameLength, creationDate, modificationDate, isDirectory, isVisible, sizeIfFile;
1709 int dirPathLength = slotRawObject(dirPathSlot)->size;
1711 err = dir_Lookup(slotRawObject(dirPathSlot)s->s, dirPathLength, index+1,
1712 name, &nameLength, &creationDate, &modificationDate, &isDirectory, &isVisible, &sizeIfFile);
1713 if (err == 1) {
1714 SetNil(a);
1715 return errNone;
1717 if (err) {
1718 error("Invalid path\n");
1719 SetNil(a);
1720 return errFailed;
1723 if (dirPathLength + nameLength + 1 > 255) {
1724 error("Full path name too long.\n");
1725 SetNil(a);
1726 return errFailed;
1729 PyrSlot *entryName = slotRawObject(b)->slots + 0;
1730 PyrSlot *entryPath = slotRawObject(b)->slots + 1;
1731 PyrSlot *entryIsDir = slotRawObject(b)->slots + 2;
1732 PyrSlot *entryIsVisible = slotRawObject(b)->slots + 3;
1734 PyrString *nameString = newPyrString(g->gc, name, 0, true);
1735 SetObject(entryName, nameString);
1736 g->gc->GCWrite(slotRawObject(b), (PyrObject*)nameString);
1738 memcpy(fullPathName, slotRawObject(dirPathSlot)s->s, dirPathLength);
1739 fullPathName[dirPathLength] = DELIMITOR;
1740 strcpy(fullPathName + dirPathLength + 1, name);
1742 PyrString *pathString = newPyrString(g->gc, fullPathName, 0, true);
1743 SetObject(entryPath, pathString);
1744 g->gc->GCWrite(slotRawObject(b), (PyrObject*)pathString);
1746 if (isDirectory) { SetTrue(entryIsDir); } else { SetFalse(entryIsDir); }
1747 if (isVisible) { SetTrue(entryIsVisible); } else { SetFalse(entryIsVisible); }
1749 slotCopy(a,b);
1751 return errNone;
1754 Boolean GetFullPathname(const FSSpec* aSpec, Str255 pathname);
1755 void pstrncpy(unsigned char *s1, unsigned char *s2, int n);
1757 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed);
1758 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed)
1761 PyrSlot *a = g->sp - 1;
1762 PyrSlot *b = g->sp;
1764 NavDialogOptions options;
1766 int err = NavGetDefaultDialogOptions(&options);
1767 if (err) return errFailed;
1769 options.dialogOptionFlags |= kNavNoTypePopup;
1770 options.dialogOptionFlags |= kNavDontAutoTranslate;
1771 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1772 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1773 options.dialogOptionFlags &= ~kNavAllowPreviews;
1774 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1776 if (isKindOfSlot(b, class_string)) {
1777 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1780 NavReplyRecord reply;
1781 err = NavGetFile(0, &reply, &options, 0, 0, 0, 0, 0);
1783 if (err == noErr && reply.validRecord) {
1784 AEKeyword keyword;
1785 DescType actualType;
1786 Size actualSize;
1787 FSSpec fsspec;
1789 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1790 &fsspec, sizeof(FSSpec), &actualSize);
1792 if (err == noErr) {
1793 Str255 pathname;
1794 GetFullPathname(&fsspec, pathname);
1795 p2cstr(pathname);
1796 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1797 SetObject(a, string);
1798 } else {
1799 SetNil(a);
1801 err = NavDisposeReply(&reply);
1802 } else {
1803 SetNil(a);
1805 return errNone;
1810 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed);
1811 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed)
1814 PyrSlot *a = g->sp - 2;
1815 PyrSlot *b = g->sp - 1;
1816 PyrSlot *c = g->sp;
1818 NavDialogOptions options;
1820 int err = NavGetDefaultDialogOptions(&options);
1821 if (err) return errFailed;
1823 options.dialogOptionFlags |= kNavNoTypePopup;
1824 options.dialogOptionFlags |= kNavDontAutoTranslate;
1825 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1826 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1827 options.dialogOptionFlags &= ~kNavAllowPreviews;
1828 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1830 if (isKindOfSlot(b, class_string)) {
1831 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1834 if (isKindOfSlot(c, class_string)) {
1835 pstringFromPyrString((PyrString*)slotRawObject(c), options.savedFileName, 256);
1836 } else {
1837 //pstrncpy(options.savedFileName, "\pUntitled", 255);
1840 NavReplyRecord reply;
1841 err = NavPutFile(0, &reply, &options, 0, 'TEXT', 'SCjm', 0);
1843 if (err == noErr && reply.validRecord) {
1844 AEKeyword keyword;
1845 DescType actualType;
1846 Size actualSize;
1847 FSSpec fsspec;
1849 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1850 &fsspec, sizeof(FSSpec), &actualSize);
1852 if (err == noErr) {
1853 Str255 pathname;
1854 GetFullPathname(&fsspec, pathname);
1855 p2cstr(pathname);
1856 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1857 SetObject(a, string);
1859 err = NavCompleteSave(&reply, kNavTranslateInPlace);
1860 } else {
1861 SetNil(a);
1863 err = NavDisposeReply(&reply);
1864 } else {
1865 SetNil(a);
1867 return errNone;
1870 #endif
1872 /////////////
1874 void initFilePrimitives()
1876 int base, index;
1878 base = nextPrimitiveIndex();
1879 index = 0;
1881 definePrimitive(base, index++, "_SFOpenRead", prSFOpenRead, 2, 0);
1882 definePrimitive(base, index++, "_SFOpenWrite", prSFOpenWrite, 2, 0);
1883 definePrimitive(base, index++, "_SFClose", prSFClose, 1, 0);
1884 definePrimitive(base, index++, "_SFWrite", prSFWrite, 2, 0);
1885 definePrimitive(base, index++, "_SFRead", prSFRead, 2, 0);
1886 definePrimitive(base, index++, "_SFSeek", prSFSeek, 3, 0);
1887 definePrimitive(base, index++, "_SFHeaderInfoString", prSFHeaderInfoString, 1, 0);
1889 #ifndef SC_WIN32
1890 definePrimitive(base, index++, "_PipeOpen", prPipeOpen, 3, 0);
1891 definePrimitive(base, index++, "_PipeClose", prPipeClose, 1, 0);
1892 #endif
1894 definePrimitive(base, index++, "_FileDelete", prFileDelete, 2, 0);
1895 definePrimitive(base, index++, "_FileOpen", prFileOpen, 3, 0);
1896 definePrimitive(base, index++, "_FileClose", prFileClose, 1, 0);
1897 definePrimitive(base, index++, "_FileFlush", prFileFlush, 1, 0);
1898 definePrimitive(base, index++, "_FileSeek", prFileSeek, 3, 0);
1899 definePrimitive(base, index++, "_FilePos", prFilePos, 1, 0);
1900 definePrimitive(base, index++, "_FileLength", prFileLength, 1, 0);
1901 definePrimitive(base, index++, "_FileWrite", prFileWrite, 2, 0);
1902 definePrimitive(base, index++, "_FileWriteLE", prFileWriteLE, 2, 0);
1903 definePrimitive(base, index++, "_FileReadLine", prFileReadLine, 2, 0);
1904 definePrimitive(base, index++, "_File_getcwd", prFileGetcwd, 2, 0);
1906 definePrimitive(base, index++, "_FilePutChar", prFilePutChar, 2, 0);
1907 definePrimitive(base, index++, "_FilePutInt8", prFilePutInt8, 2, 0);
1908 definePrimitive(base, index++, "_FilePutInt16", prFilePutInt16, 2, 0);
1909 definePrimitive(base, index++, "_FilePutInt32", prFilePutInt32, 2, 0);
1910 definePrimitive(base, index++, "_FilePutFloat", prFilePutFloat, 2, 0);
1911 definePrimitive(base, index++, "_FilePutDouble", prFilePutDouble, 2, 0);
1912 definePrimitive(base, index++, "_FilePutInt16LE", prFilePutInt16LE, 2, 0);
1913 definePrimitive(base, index++, "_FilePutInt32LE", prFilePutInt32LE, 2, 0);
1914 definePrimitive(base, index++, "_FilePutFloatLE", prFilePutFloatLE, 2, 0);
1915 definePrimitive(base, index++, "_FilePutDoubleLE", prFilePutDoubleLE, 2, 0);
1917 definePrimitive(base, index++, "_FileGetChar", prFileGetChar, 1, 0);
1918 definePrimitive(base, index++, "_FileGetInt8", prFileGetInt8, 1, 0);
1919 definePrimitive(base, index++, "_FileGetInt16", prFileGetInt16, 1, 0);
1920 definePrimitive(base, index++, "_FileGetInt32", prFileGetInt32, 1, 0);
1921 definePrimitive(base, index++, "_FileGetFloat", prFileGetFloat, 1, 0);
1922 definePrimitive(base, index++, "_FileGetDouble", prFileGetDouble, 1, 0);
1923 definePrimitive(base, index++, "_FileGetInt16LE", prFileGetInt16LE, 1, 0);
1924 definePrimitive(base, index++, "_FileGetInt32LE", prFileGetInt32LE, 1, 0);
1925 definePrimitive(base, index++, "_FileGetFloatLE", prFileGetFloatLE, 1, 0);
1926 definePrimitive(base, index++, "_FileGetDoubleLE", prFileGetDoubleLE, 1, 0);
1928 definePrimitive(base, index++, "_FilePutString", prFilePutString, 2, 0);
1930 definePrimitive(base, index++, "_FileReadRaw", prFileReadRaw, 2, 0);
1931 definePrimitive(base, index++, "_FileReadRawLE", prFileReadRawLE, 2, 0);
1933 #ifdef NOCLASSIC
1934 definePrimitive(base, index++, "_Directory_At", prDirectory_At, 3, 0);
1935 definePrimitive(base, index++, "_File_GetFile", prFile_GetFile, 2, 0);
1936 definePrimitive(base, index++, "_File_PutFile", prFile_PutFile, 3, 0);
1937 #endif