Protected backtrace: don't print all of a very long sourceCode string
[supercollider.git] / lang / LangPrimSource / PyrFilePrim.cpp
blobf3edf64792311b5ca724691e3de6c340ddc5f210
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 "SC_DirUtils.h"
36 #include "sc_popen.h"
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <cerrno>
43 #include "../../common/SC_SndFileHelpers.hpp"
45 #ifdef NOCLASSIC
46 #include <TextUtils.h>
47 #include <Navigation.h>
48 #endif
50 #ifndef _WIN32
51 # include <unistd.h>
52 #else
53 # include <direct.h>
54 # include <malloc.h>
55 # define strcasecmp stricmp
56 #endif
58 #ifdef _WIN32
59 #include <stdio.h>
60 #include "SC_Win32Utils.h"
61 #include "SC_DirUtils.h"
62 #endif
64 #include <fcntl.h>
65 #include <math.h>
67 #include <boost/filesystem.hpp>
69 #if defined(__APPLE__) || defined(SC_IPHONE)
70 #ifndef _SC_StandAloneInfo_
71 # include "SC_StandAloneInfo_Darwin.h"
72 #endif
73 # include <CoreFoundation/CFString.h>
74 # include <CoreFoundation/CFBundle.h>
75 #ifndef SC_IPHONE
76 # include <CoreServices/CoreServices.h>
77 #endif
78 #endif
80 #define DELIMITOR ':'
82 bool filelen(FILE *file, size_t *length);
84 int prFileDelete(struct VMGlobals *g, int numArgsPushed)
86 PyrSlot *a = g->sp - 1, *b = g->sp;
87 char filename[PATH_MAX];
89 int error = slotStrVal(b, filename, PATH_MAX);
90 if (error != errNone)
91 return error;
93 int err = unlink(filename);
94 SetBool(a, err == 0);
96 return errNone;
99 int prFileMTime(struct VMGlobals * g, int numArgsPushed)
101 PyrSlot *a = g->sp - 1, *b = g->sp;
102 char filename[PATH_MAX];
104 int error = slotStrVal(b, filename, PATH_MAX);
105 if (error != errNone)
106 return error;
108 time_t mtime = boost::filesystem::last_write_time(filename);
109 SetInt(a, mtime);
110 return errNone;
113 int prFileExists(struct VMGlobals * g, int numArgsPushed)
115 PyrSlot *a = g->sp - 1, *b = g->sp;
116 char filename[PATH_MAX];
118 int error = slotStrVal(b, filename, PATH_MAX);
119 if (error != errNone)
120 return error;
122 bool res = boost::filesystem::exists(filename);
123 SetBool(a, res);
124 return errNone;
127 int prFileRealPath(struct VMGlobals* g, int numArgsPushed )
129 PyrSlot *a = g->sp - 1, *b = g->sp;
130 char ipath[PATH_MAX];
131 char opath[PATH_MAX];
132 int err;
134 err = slotStrVal(b, ipath, PATH_MAX);
135 if (err) return err;
137 bool isAlias = false;
138 if(sc_ResolveIfAlias(ipath, opath, isAlias, PATH_MAX)!=0) {
139 return errFailed;
142 boost::system::error_code error_code;
143 boost::filesystem::path p = boost::filesystem::canonical(opath,error_code);
144 if(error_code) {
145 SetNil(a);
146 return errNone;
148 strcpy(opath,p.string().c_str());
150 #if SC_DARWIN
151 CFStringRef cfstring =
152 CFStringCreateWithCString(NULL,
153 opath,
154 kCFStringEncodingUTF8);
155 err = !CFStringGetFileSystemRepresentation(cfstring, opath, PATH_MAX);
156 CFRelease(cfstring);
157 if (err) return errFailed;
158 #endif // SC_DARWIN
160 PyrString* pyrString = newPyrString(g->gc, opath, 0, true);
161 SetObject(a, pyrString);
163 return errNone;
166 int prFileMkDir(struct VMGlobals * g, int numArgsPushed)
168 PyrSlot *a = g->sp - 1, *b = g->sp;
169 char filename[PATH_MAX];
171 int error = slotStrVal(b, filename, PATH_MAX);
172 if (error != errNone)
173 return error;
175 boost::system::error_code error_code;
176 boost::filesystem::create_directories(filename, error_code);
177 if (error_code)
178 postfl("Warning: %s (\"%s\")\n", error_code.message().c_str(), filename);
180 return errNone;
183 int prFileCopy(struct VMGlobals * g, int numArgsPushed)
185 PyrSlot *a = g->sp - 2, *b = g->sp - 1, *c = g->sp;
186 char filename1[PATH_MAX];
187 char filename2[PATH_MAX];
188 int error;
189 error = slotStrVal(b, filename1, PATH_MAX);
190 if (error != errNone)
191 return error;
192 error = slotStrVal(c, filename2, PATH_MAX);
193 if (error != errNone)
194 return error;
196 boost::filesystem3::copy(filename1, filename2);
197 return errNone;
200 int prFileType(struct VMGlobals * g, int numArgsPushed)
202 PyrSlot *a = g->sp - 1, *b = g->sp;
203 char filename[PATH_MAX];
205 int error = slotStrVal(b, filename, PATH_MAX);
206 if (error != errNone)
207 return error;
209 boost::filesystem::file_status s(boost::filesystem::symlink_status(filename));
210 SetInt(a, s.type());
211 return errNone;
214 int prFileSize(struct VMGlobals * g, int numArgsPushed)
216 PyrSlot *a = g->sp - 1, *b = g->sp;
217 char filename[PATH_MAX];
219 int error = slotStrVal(b, filename, PATH_MAX);
220 if (error != errNone)
221 return error;
223 uintmax_t sz = boost::filesystem::file_size(filename);
224 SetInt(a, sz);
225 return errNone;
229 int prFileOpen(struct VMGlobals *g, int numArgsPushed)
231 PyrSlot *a, *b, *c;
232 char filename[PATH_MAX];
233 char mode[12];
234 PyrFile *pfile;
235 FILE *file;
237 a = g->sp - 2;
238 b = g->sp - 1;
239 c = g->sp;
240 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
241 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
242 return errWrongType;
243 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
244 if (slotRawObject(c)->size > 11) return errFailed;
245 pfile = (PyrFile*)slotRawObject(a);
247 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
248 filename[slotRawString(b)->size] = 0;
250 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
251 mode[slotRawString(c)->size] = 0;
253 #ifdef SC_WIN32
254 win32_ReplaceCharInString(filename,PATH_MAX,'/','\\');
255 if(strcmp(mode,"w") == 0)
256 strcpy(mode,"wb");
257 if(strcmp(mode,"r") == 0)
258 strcpy(mode,"rb");
259 #endif
260 //SC_WIN32
261 file = fopen(filename, mode);
262 if (file) {
263 SetPtr(&pfile->fileptr, file);
264 SetTrue(a);
265 } else {
266 #ifdef SC_WIN32
267 // check if directory exisits
268 // create a temporary file (somewhere) for a handle
269 // the file is deleted automatically when closed
270 if (sc_DirectoryExists(filename)) {
271 int err;
272 #ifdef _MSC_VER
273 err = tmpfile_s(&file);
274 if (!err) {
275 SetPtr(&pfile->fileptr, file);
276 SetTrue(a);
277 return errNone;
279 #elif defined(__MINGW32__)
280 file = tmpfile();
281 if (file) {
282 SetPtr(&pfile->fileptr, file);
283 SetTrue(a);
284 return errNone;
286 #else
287 #error compiler unsupported
288 #endif
290 #endif
291 SetNil(a);
292 SetFalse(a);
294 return errNone;
297 int prFileClose(struct VMGlobals *g, int numArgsPushed)
299 PyrSlot *a;
300 PyrFile *pfile;
301 FILE *file;
303 a = g->sp;
304 pfile = (PyrFile*)slotRawObject(a);
305 file = (FILE*)slotRawPtr(&pfile->fileptr);
306 if (file == NULL) return errNone;
307 SetPtr(&pfile->fileptr, NULL);
308 if (fclose(file)) return errFailed;
309 return errNone;
312 int prFileFlush(struct VMGlobals *g, int numArgsPushed)
314 PyrSlot *a;
315 PyrFile *pfile;
316 FILE *file;
318 a = g->sp;
319 pfile = (PyrFile*)slotRawObject(a);
320 file = (FILE*)slotRawPtr(&pfile->fileptr);
321 if (file != NULL) fflush(file);
322 return errNone;
325 int prFilePos(struct VMGlobals *g, int numArgsPushed)
327 PyrSlot *a;
328 PyrFile *pfile;
329 FILE *file;
330 fpos_t pos;
331 int length;
333 a = g->sp;
334 pfile = (PyrFile*)slotRawObject(a);
335 file = (FILE*)slotRawPtr(&pfile->fileptr);
336 if (file == NULL) return errFailed;
337 if (fgetpos(file, &pos)) return errFailed;
339 #ifdef SC_LINUX
340 // sk: hack alert!
341 length = pos.__pos;
342 #else
343 length = pos;
344 #endif
346 SetInt(a, length);
347 return errNone;
350 int prFileLength(struct VMGlobals *g, int numArgsPushed)
352 PyrSlot *a;
353 PyrFile *pfile;
354 FILE *file;
355 fpos_t pos;
356 size_t length;
358 a = g->sp;
359 pfile = (PyrFile*)slotRawObject(a);
360 file = (FILE*)slotRawPtr(&pfile->fileptr);
361 if (file == NULL) return errFailed;
362 // preserve file position
363 if (fgetpos(file, &pos)) return errFailed;
364 if (filelen(file, &length)) return errFailed;
365 if (fsetpos(file, &pos)) return errFailed;
367 SetInt(a, length);
368 return errNone;
371 int prFileSeek(struct VMGlobals *g, int numArgsPushed)
373 PyrSlot *a, *b, *c;
374 PyrFile *pfile;
375 FILE *file;
376 size_t offset;
377 int origin;
378 static int originTable[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
380 a = g->sp - 2;
381 b = g->sp - 1;
382 c = g->sp;
383 if (NotInt(b)) return errWrongType;
384 if (NotInt(c)) return errWrongType;
385 pfile = (PyrFile*)slotRawObject(a);
386 file = (FILE*)slotRawPtr(&pfile->fileptr);
387 if (file == NULL) return errFailed;
388 offset = slotRawInt(b);
389 origin = slotRawInt(c);
390 if (origin < 0 || origin > 2) return errIndexOutOfRange;
391 origin = originTable[origin]; // translate in case ANSI constants ever change..
392 if (fseek(file, offset, origin)) return errFailed;
393 return errNone;
397 int prFileWrite(struct VMGlobals *g, int numArgsPushed)
399 PyrSlot *a, *b, *ptr;
400 PyrFile *pfile;
401 FILE *file;
402 PyrObject *obj;
403 char chr;
405 a = g->sp - 1;
406 b = g->sp;
407 pfile = (PyrFile*)slotRawObject(a);
408 file = (FILE*)slotRawPtr(&pfile->fileptr);
409 if (file == NULL) return errFailed;
410 switch (GetTag(b)) {
411 case tagInt :
413 SC_IOStream<FILE*> scio(file);
414 scio.writeInt32_be(slotRawInt(b));
415 break;
417 case tagSym :
418 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
419 break;
420 case tagChar :
421 chr = slotRawChar(b);
422 fwrite(&chr, sizeof(char), 1, file);
423 break;
424 case tagNil :
425 case tagFalse :
426 case tagTrue :
427 case tagPtr :
428 return errWrongType;
429 case tagObj :
431 // writes the indexable part of any non obj_slot format object
432 obj = slotRawObject(b);
433 if (!isKindOf(obj, class_rawarray)
434 || isKindOf(obj, class_symbolarray)) return errWrongType;
435 if (obj->size) {
436 ptr = obj->slots;
437 int elemSize = gFormatElemSize[obj->obj_format];
438 int numElems = obj->size;
439 #if BYTE_ORDER != BIG_ENDIAN
440 switch (elemSize) {
441 case 1:
442 fwrite(ptr, elemSize, numElems, file);
443 break;
444 case 2:
446 char *ptr = slotRawString(b)->s;
447 char *ptrend = ptr + numElems*2;
448 for (; ptr < ptrend; ptr+=2) {
449 fputc(ptr[1], file);
450 fputc(ptr[0], file);
452 break;
454 case 4:
456 char *ptr = slotRawString(b)->s;
457 char *ptrend = ptr + numElems*4;
458 for (; ptr < ptrend; ptr+=4) {
459 fputc(ptr[3], file);
460 fputc(ptr[2], file);
461 fputc(ptr[1], file);
462 fputc(ptr[0], file);
464 break;
466 case 8:
468 char *ptr = slotRawString(b)->s;
469 char *ptrend = ptr + numElems*8;
470 for (; ptr < ptrend; ptr+=8) {
471 fputc(ptr[7], file);
472 fputc(ptr[6], file);
473 fputc(ptr[5], file);
474 fputc(ptr[4], file);
475 fputc(ptr[3], file);
476 fputc(ptr[2], file);
477 fputc(ptr[1], file);
478 fputc(ptr[0], file);
480 break;
483 #else
484 fwrite(ptr, elemSize, numElems, file);
485 #endif
487 break;
489 default : // double
491 SC_IOStream<FILE*> scio(file);
492 scio.writeDouble_be(slotRawFloat(b));
493 break;
496 return errNone;
500 int prFileWriteLE(struct VMGlobals *g, int numArgsPushed)
502 PyrSlot *a, *b, *ptr;
503 PyrFile *pfile;
504 FILE *file;
505 PyrObject *obj;
506 char chr;
508 a = g->sp - 1;
509 b = g->sp;
510 pfile = (PyrFile*)slotRawObject(a);
511 file = (FILE*)slotRawPtr(&pfile->fileptr);
512 if (file == NULL) return errFailed;
513 switch (GetTag(b)) {
514 case tagInt :
516 SC_IOStream<FILE*> scio(file);
517 scio.writeInt32_le(slotRawInt(b));
518 break;
520 case tagSym :
521 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
522 break;
523 case tagChar :
524 chr = slotRawInt(b);
525 fwrite(&chr, sizeof(char), 1, file);
526 break;
527 case tagNil :
528 case tagFalse :
529 case tagTrue :
530 case tagPtr :
531 return errWrongType;
532 case tagObj :
534 // writes the indexable part of any non obj_slot format object
535 obj = slotRawObject(b);
536 if (!isKindOf(obj, class_rawarray)
537 || isKindOf(obj, class_symbolarray)) return errWrongType;
538 if (obj->size) {
539 ptr = obj->slots;
540 int elemSize = gFormatElemSize[obj->obj_format];
541 int numElems = obj->size;
542 #if BYTE_ORDER == BIG_ENDIAN
543 switch (elemSize) {
544 case 1:
545 fwrite(ptr, elemSize, numElems, file);
546 break;
547 case 2:
549 char *ptr = slotRawString(b)->s;
550 char *ptrend = ptr + numElems*2;
551 for (; ptr < ptrend; ptr+=2) {
552 fputc(ptr[1], file);
553 fputc(ptr[0], file);
555 break;
557 case 4:
559 char *ptr = slotRawString(b)->s;
560 char *ptrend = ptr + numElems*4;
561 for (; ptr < ptrend; ptr+=4) {
562 fputc(ptr[3], file);
563 fputc(ptr[2], file);
564 fputc(ptr[1], file);
565 fputc(ptr[0], file);
567 break;
569 case 8:
571 char *ptr = slotRawString(b)->s;
572 char *ptrend = ptr + numElems*8;
573 for (; ptr < ptrend; ptr+=8) {
574 fputc(ptr[7], file);
575 fputc(ptr[6], file);
576 fputc(ptr[5], file);
577 fputc(ptr[4], file);
578 fputc(ptr[3], file);
579 fputc(ptr[2], file);
580 fputc(ptr[1], file);
581 fputc(ptr[0], file);
583 break;
586 #else
587 fwrite(ptr, elemSize, numElems, file);
588 #endif
590 break;
592 default : // double
594 SC_IOStream<FILE*> scio(file);
595 scio.writeDouble_le(slotRawFloat(b));
596 break;
599 return errNone;
602 int prFileReadLine(struct VMGlobals *g, int numArgsPushed)
604 PyrSlot *a, *b; // receiver(a File), string
605 PyrFile *pfile;
606 FILE *file;
608 a = g->sp - 1;
609 b = g->sp;
611 pfile = (PyrFile*)slotRawObject(a);
612 file = (FILE*)slotRawPtr(&pfile->fileptr);
613 if (file == NULL) return errFailed;
615 char* result = fgets(slotRawString(b)->s, MAXINDEXSIZE(slotRawObject(b)) - 1, file);
616 if (!result) {
617 SetNil(a);
618 } else {
619 slotRawString(b)->size = strlen(slotRawString(b)->s);
620 if (slotRawString(b)->s[slotRawString(b)->size-1] == '\n') slotRawString(b)->size--;
621 slotCopy(a,b);
623 return errNone;
626 int prFilePutInt32(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) return errFailed;
639 int val;
640 int err = slotIntVal(b, &val);
641 if (err) return err;
643 SC_IOStream<FILE*> scio(file);
644 scio.writeInt32_be(val);
646 return errNone;
649 int prFilePutInt16(struct VMGlobals *g, int numArgsPushed)
651 PyrSlot *a, *b;
652 PyrFile *pfile;
653 FILE *file;
655 a = g->sp - 1;
656 b = g->sp;
658 pfile = (PyrFile*)slotRawObject(a);
659 file = (FILE*)slotRawPtr(&pfile->fileptr);
660 if (file == NULL) return errFailed;
662 int val;
663 int err = slotIntVal(b, &val);
664 if (err) return err;
667 SC_IOStream<FILE*> scio(file);
668 scio.writeInt16_be(val);
670 return errNone;
674 int prFilePutInt32LE(struct VMGlobals *g, int numArgsPushed)
676 PyrSlot *a, *b;
677 PyrFile *pfile;
678 FILE *file;
680 a = g->sp - 1;
681 b = g->sp;
683 pfile = (PyrFile*)slotRawObject(a);
684 file = (FILE*)slotRawPtr(&pfile->fileptr);
685 if (file == NULL) return errFailed;
687 int val;
688 int err = slotIntVal(b, &val);
689 if (err) return err;
691 SC_IOStream<FILE*> scio(file);
692 scio.writeInt32_le(val);
694 return errNone;
697 int prFilePutInt16LE(struct VMGlobals *g, int numArgsPushed)
699 PyrSlot *a, *b;
700 PyrFile *pfile;
701 FILE *file;
703 a = g->sp - 1;
704 b = g->sp;
706 pfile = (PyrFile*)slotRawObject(a);
707 file = (FILE*)slotRawPtr(&pfile->fileptr);
708 if (file == NULL) return errFailed;
710 int val;
711 int err = slotIntVal(b, &val);
712 if (err) return err;
715 SC_IOStream<FILE*> scio(file);
716 scio.writeInt16_le(val);
718 return errNone;
721 int prFilePutInt8(struct VMGlobals *g, int numArgsPushed)
723 PyrSlot *a, *b;
724 PyrFile *pfile;
725 FILE *file;
727 a = g->sp - 1;
728 b = g->sp;
730 pfile = (PyrFile*)slotRawObject(a);
731 file = (FILE*)slotRawPtr(&pfile->fileptr);
732 if (file == NULL) return errFailed;
734 int val;
735 int err = slotIntVal(b, &val);
736 if (err) return err;
739 SC_IOStream<FILE*> scio(file);
740 scio.writeInt8(val);
742 return errNone;
745 int prFilePutChar(struct VMGlobals *g, int numArgsPushed)
747 PyrSlot *a, *b;
748 PyrFile *pfile;
749 FILE *file;
750 char z;
752 a = g->sp - 1;
753 b = g->sp;
755 pfile = (PyrFile*)slotRawObject(a);
756 file = (FILE*)slotRawPtr(&pfile->fileptr);
757 if (file == NULL) return errFailed;
758 if (NotChar(b)) return errWrongType;
760 z = slotRawChar(b);
762 SC_IOStream<FILE*> scio(file);
763 scio.writeInt8(z);
765 return errNone;
768 int prFilePutFloat(struct VMGlobals *g, int numArgsPushed)
770 PyrSlot *a, *b;
771 PyrFile *pfile;
772 FILE *file;
774 a = g->sp - 1;
775 b = g->sp;
777 pfile = (PyrFile*)slotRawObject(a);
778 file = (FILE*)slotRawPtr(&pfile->fileptr);
779 if (file == NULL) {
780 dumpObjectSlot(a);
781 return errFailed;
784 float val;
785 int err = slotFloatVal(b, &val);
786 if (err) return err;
788 SC_IOStream<FILE*> scio(file);
789 scio.writeFloat_be(val);
791 return errNone;
794 int prFilePutDouble(struct VMGlobals *g, int numArgsPushed)
796 PyrSlot *a, *b;
797 PyrFile *pfile;
798 FILE *file;
800 a = g->sp - 1;
801 b = g->sp;
803 pfile = (PyrFile*)slotRawObject(a);
804 file = (FILE*)slotRawPtr(&pfile->fileptr);
805 if (file == NULL) return errFailed;
808 double val;
809 int err = slotDoubleVal(b, &val);
810 if (err) return err;
812 SC_IOStream<FILE*> scio(file);
813 scio.writeDouble_be(val);
815 return errNone;
819 int prFilePutFloatLE(struct VMGlobals *g, int numArgsPushed)
821 PyrSlot *a, *b;
822 PyrFile *pfile;
823 FILE *file;
825 a = g->sp - 1;
826 b = g->sp;
828 pfile = (PyrFile*)slotRawObject(a);
829 file = (FILE*)slotRawPtr(&pfile->fileptr);
830 if (file == NULL) {
831 dumpObjectSlot(a);
832 return errFailed;
835 float val;
836 int err = slotFloatVal(b, &val);
837 if (err) return err;
839 SC_IOStream<FILE*> scio(file);
840 scio.writeFloat_le(val);
842 return errNone;
845 int prFilePutDoubleLE(struct VMGlobals *g, int numArgsPushed)
847 PyrSlot *a, *b;
848 PyrFile *pfile;
849 FILE *file;
851 a = g->sp - 1;
852 b = g->sp;
854 pfile = (PyrFile*)slotRawObject(a);
855 file = (FILE*)slotRawPtr(&pfile->fileptr);
856 if (file == NULL) return errFailed;
859 double val;
860 int err = slotDoubleVal(b, &val);
861 if (err) return err;
863 SC_IOStream<FILE*> scio(file);
864 scio.writeDouble_le(val);
866 return errNone;
869 int prFilePutString(struct VMGlobals *g, int numArgsPushed)
871 PyrSlot *a, *b;
872 PyrFile *pfile;
873 FILE *file;
874 PyrString *string;
876 a = g->sp - 1;
877 b = g->sp;
878 pfile = (PyrFile*)slotRawObject(a);
879 file = (FILE*)slotRawPtr(&pfile->fileptr);
880 if (file == NULL) return errFailed;
881 if (NotObj(b) || slotRawObject(b)->classptr != class_string) return errWrongType;
882 string = slotRawString(b);
883 if (string->size) {
884 fwrite(string->s, 1, string->size, file);
886 return errNone;
890 int prFileGetDouble(struct VMGlobals *g, int numArgsPushed)
892 PyrSlot *a;
893 PyrFile *pfile;
894 FILE *file;
896 a = g->sp;
898 pfile = (PyrFile*)slotRawObject(a);
899 file = (FILE*)slotRawPtr(&pfile->fileptr);
900 if (file == NULL) return errFailed;
902 if (feof(file)) SetNil(a);
903 else {
904 SC_IOStream<FILE*> scio(file);
905 SetFloat(a, scio.readDouble_be());
907 return errNone;
910 int prFileGetFloat(struct VMGlobals *g, int numArgsPushed)
912 PyrSlot *a;
913 PyrFile *pfile;
914 FILE *file;
916 a = g->sp;
918 pfile = (PyrFile*)slotRawObject(a);
919 file = (FILE*)slotRawPtr(&pfile->fileptr);
920 if (file == NULL) return errFailed;
922 if (feof(file)) SetNil(a);
923 else {
924 SC_IOStream<FILE*> scio(file);
925 SetFloat(a, scio.readFloat_be());
927 return errNone;
931 int prFileGetDoubleLE(struct VMGlobals *g, int numArgsPushed)
933 PyrSlot *a;
934 PyrFile *pfile;
935 FILE *file;
937 a = g->sp;
939 pfile = (PyrFile*)slotRawObject(a);
940 file = (FILE*)slotRawPtr(&pfile->fileptr);
941 if (file == NULL) return errFailed;
943 if (feof(file)) SetNil(a);
944 else {
945 SC_IOStream<FILE*> scio(file);
946 SetFloat(a, scio.readDouble_le());
948 return errNone;
951 int prFileGetFloatLE(struct VMGlobals *g, int numArgsPushed)
953 PyrSlot *a;
954 PyrFile *pfile;
955 FILE *file;
957 a = g->sp;
959 pfile = (PyrFile*)slotRawObject(a);
960 file = (FILE*)slotRawPtr(&pfile->fileptr);
961 if (file == NULL) return errFailed;
963 if (feof(file)) SetNil(a);
964 else {
965 SC_IOStream<FILE*> scio(file);
966 SetFloat(a, scio.readFloat_le());
968 return errNone;
971 int prFileGetChar(struct VMGlobals *g, int numArgsPushed)
973 PyrSlot *a;
974 PyrFile *pfile;
975 FILE *file;
976 char z;
978 a = g->sp;
980 pfile = (PyrFile*)slotRawObject(a);
981 file = (FILE*)slotRawPtr(&pfile->fileptr);
982 if (file == NULL) return errFailed;
984 int count = fread(&z, sizeof(char), 1, file);
985 if (count==0) SetNil(a);
986 else SetChar(a, z);
987 return errNone;
990 int prFileGetInt8(struct VMGlobals *g, int numArgsPushed)
992 PyrSlot *a;
993 PyrFile *pfile;
994 FILE *file;
995 int8 z;
997 a = g->sp;
999 pfile = (PyrFile*)slotRawObject(a);
1000 file = (FILE*)slotRawPtr(&pfile->fileptr);
1001 if (file == NULL) return errFailed;
1003 int count = fread(&z, sizeof(int8), 1, file);
1004 if (count==0) SetNil(a);
1005 else SetInt(a, z);
1006 return errNone;
1009 int prFileGetInt16(struct VMGlobals *g, int numArgsPushed)
1011 PyrSlot *a;
1012 PyrFile *pfile;
1013 FILE *file;
1015 a = g->sp;
1017 pfile = (PyrFile*)slotRawObject(a);
1018 file = (FILE*)slotRawPtr(&pfile->fileptr);
1019 if (file == NULL) return errFailed;
1021 if (feof(file)) SetNil(a);
1022 else {
1023 SC_IOStream<FILE*> scio(file);
1024 SetInt(a, scio.readInt16_be());
1026 return errNone;
1029 int prFileGetInt32(struct VMGlobals *g, int numArgsPushed)
1031 PyrSlot *a;
1032 PyrFile *pfile;
1033 FILE *file;
1035 a = g->sp;
1037 pfile = (PyrFile*)slotRawObject(a);
1038 file = (FILE*)slotRawPtr(&pfile->fileptr);
1039 if (file == NULL)
1040 return errFailed;
1042 if (feof(file)) SetNil(a);
1043 else {
1044 SC_IOStream<FILE*> scio(file);
1045 SetInt(a, scio.readInt32_be());
1047 return errNone;
1051 int prFileGetInt16LE(struct VMGlobals *g, int numArgsPushed)
1053 PyrSlot *a;
1054 PyrFile *pfile;
1055 FILE *file;
1057 a = g->sp;
1059 pfile = (PyrFile*)slotRawObject(a);
1060 file = (FILE*)slotRawPtr(&pfile->fileptr);
1061 if (file == NULL) return errFailed;
1063 if (feof(file)) SetNil(a);
1064 else {
1065 SC_IOStream<FILE*> scio(file);
1066 SetInt(a, scio.readInt16_le());
1068 return errNone;
1071 int prFileGetInt32LE(struct VMGlobals *g, int numArgsPushed)
1073 PyrSlot *a;
1074 PyrFile *pfile;
1075 FILE *file;
1077 a = g->sp;
1079 pfile = (PyrFile*)slotRawObject(a);
1080 file = (FILE*)slotRawPtr(&pfile->fileptr);
1081 if (file == NULL) return errFailed;
1083 if (feof(file)) SetNil(a);
1084 else {
1085 SC_IOStream<FILE*> scio(file);
1086 SetInt(a, scio.readInt32_le());
1088 return errNone;
1091 int prFileReadRaw(struct VMGlobals *g, int numArgsPushed)
1093 PyrFile *pfile;
1094 FILE *file;
1096 PyrSlot* a = g->sp - 1;
1097 PyrSlot* b = g->sp;
1099 if (!isKindOfSlot(b, class_rawarray)
1100 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1102 pfile = (PyrFile*)slotRawObject(a);
1103 file = (FILE*)slotRawPtr(&pfile->fileptr);
1104 if (file == NULL) return errFailed;
1106 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1107 int numElems = slotRawObject(b)->size;
1108 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1109 slotRawObject(b)->size = numElems;
1111 #if BYTE_ORDER != BIG_ENDIAN
1112 switch (elemSize) {
1113 case 1:
1114 break;
1115 case 2:
1117 char *ptr = slotRawString(b)->s;
1118 char *ptrend = ptr + numElems*2;
1119 for (; ptr < ptrend; ptr+=2) {
1120 char temp = ptr[0];
1121 ptr[0] = ptr[1];
1122 ptr[1] = temp;
1124 break;
1126 case 4:
1128 char *ptr = slotRawString(b)->s;
1129 char *ptrend = ptr + numElems*4;
1130 for (; ptr < ptrend; ptr+=4) {
1131 char temp = ptr[0];
1132 ptr[0] = ptr[3];
1133 ptr[3] = temp;
1135 temp = ptr[1];
1136 ptr[1] = ptr[2];
1137 ptr[2] = temp;
1139 break;
1141 case 8:
1143 char *ptr = slotRawString(b)->s;
1144 char *ptrend = ptr + numElems*8;
1145 for (; ptr < ptrend; ptr+=8) {
1146 char temp = ptr[0];
1147 ptr[0] = ptr[7];
1148 ptr[7] = temp;
1150 temp = ptr[1];
1151 ptr[1] = ptr[6];
1152 ptr[6] = temp;
1154 temp = ptr[2];
1155 ptr[2] = ptr[5];
1156 ptr[5] = temp;
1158 temp = ptr[3];
1159 ptr[3] = ptr[4];
1160 ptr[4] = temp;
1162 break;
1165 #endif
1167 if (slotRawObject(b)->size==0) SetNil(a);
1168 else slotCopy(a,b);
1169 return errNone;
1172 int prFileReadRawLE(struct VMGlobals *g, int numArgsPushed)
1174 PyrFile *pfile;
1175 FILE *file;
1177 PyrSlot* a = g->sp - 1;
1178 PyrSlot* b = g->sp;
1180 if (!isKindOfSlot(b, class_rawarray)
1181 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1183 pfile = (PyrFile*)slotRawObject(a);
1184 file = (FILE*)slotRawPtr(&pfile->fileptr);
1185 if (file == NULL) return errFailed;
1187 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1188 int numElems = slotRawObject(b)->size;
1189 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1190 slotRawObject(b)->size = numElems;
1192 #if BYTE_ORDER == BIG_ENDIAN
1193 switch (elemSize) {
1194 case 1:
1195 break;
1196 case 2:
1198 char *ptr = slotRawString(b)->s;
1199 char *ptrend = ptr + numElems*2;
1200 for (; ptr < ptrend; ptr+=2) {
1201 char temp = ptr[0];
1202 ptr[0] = ptr[1];
1203 ptr[1] = temp;
1205 break;
1207 case 4:
1209 char *ptr = slotRawString(b)->s;
1210 char *ptrend = ptr + numElems*4;
1211 for (; ptr < ptrend; ptr+=4) {
1212 char temp = ptr[0];
1213 ptr[0] = ptr[3];
1214 ptr[3] = temp;
1216 temp = ptr[1];
1217 ptr[1] = ptr[2];
1218 ptr[2] = temp;
1220 break;
1222 case 8:
1224 char *ptr = slotRawString(b)->s;
1225 char *ptrend = ptr + numElems*8;
1226 for (; ptr < ptrend; ptr+=8) {
1227 char temp = ptr[0];
1228 ptr[0] = ptr[7];
1229 ptr[7] = temp;
1231 temp = ptr[1];
1232 ptr[1] = ptr[6];
1233 ptr[6] = temp;
1235 temp = ptr[2];
1236 ptr[2] = ptr[5];
1237 ptr[5] = temp;
1239 temp = ptr[3];
1240 ptr[3] = ptr[4];
1241 ptr[4] = temp;
1243 break;
1246 #endif
1248 if (slotRawObject(b)->size==0) SetNil(a);
1249 else slotCopy(a,b);
1250 return errNone;
1253 int prFileGetcwd(struct VMGlobals *g, int numArgsPushed)
1255 //PyrSlot* a = g->sp - 1; // File
1256 PyrSlot* string = g->sp;
1258 if (!isKindOfSlot(string, class_string)) return errWrongType;
1260 char * cwd = getcwd(slotRawString(string)->s,255);
1261 if (cwd == NULL) {
1262 error(strerror(errno));
1263 return errFailed;
1265 slotRawString(string)->size = strlen(slotRawString(string)->s);
1267 return errNone;
1270 ////////
1272 int prPipeOpen(struct VMGlobals *g, int numArgsPushed)
1274 PyrSlot *a, *b, *c;
1275 char mode[12];
1276 PyrFile *pfile;
1277 FILE *file;
1279 a = g->sp - 2;
1280 b = g->sp - 1;
1281 c = g->sp;
1283 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
1284 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
1285 return errWrongType;
1286 if (slotRawObject(c)->size > 11) return errFailed;
1287 pfile = (PyrFile*)slotRawObject(a);
1289 char *commandLine = (char*)malloc(slotRawObject(b)->size + 1);
1290 memcpy(commandLine, slotRawString(b)->s, slotRawObject(b)->size);
1291 commandLine[slotRawString(b)->size] = 0;
1293 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
1294 mode[slotRawString(c)->size] = 0;
1296 pid_t pid;
1297 file = sc_popen(commandLine, &pid, mode);
1298 free(commandLine);
1299 if (file) {
1300 SetPtr(&pfile->fileptr, file);
1301 SetInt(a, pid);
1302 } else {
1303 SetNil(a);
1305 return errNone;
1308 int prPipeClose(struct VMGlobals *g, int numArgsPushed)
1310 PyrSlot *a;
1311 PyrSlot *b;
1312 PyrFile *pfile;
1313 FILE *file;
1314 pid_t pid;
1316 a = g->sp - 1;
1317 b = g->sp;
1318 pfile = (PyrFile*)slotRawObject(a);
1319 file = (FILE*)slotRawPtr(&pfile->fileptr);
1320 if (file == NULL) return errNone;
1321 pid = (pid_t) slotRawInt(b);
1323 SetPtr(&pfile->fileptr, NULL);
1324 int perr = sc_pclose(file, pid);
1325 SetInt(a, perr);
1326 if (perr == -1)
1327 return errFailed;
1328 return errNone;
1331 ////////
1333 #ifndef NO_LIBSNDFILE
1335 #ifdef SC_WIN32
1336 #include <sndfile-win.h>
1337 #else
1338 #include <sndfile.h>
1339 #endif
1342 int sampleFormatToString(struct SF_INFO *info, const char **string);
1343 int sampleFormatToString(struct SF_INFO *info, const char **string)
1345 unsigned int format = info->format & SF_FORMAT_SUBMASK;
1346 switch (format)
1348 case SF_FORMAT_DPCM_8:
1349 case SF_FORMAT_PCM_S8:
1350 *string = "int16";
1351 break;
1352 case SF_FORMAT_DPCM_16:
1353 case SF_FORMAT_PCM_16:
1354 case SF_FORMAT_DWVW_16:
1355 *string = "int16";
1356 break;
1357 case SF_FORMAT_PCM_24:
1358 case SF_FORMAT_DWVW_24:
1359 *string = "int24";
1360 break;
1361 case SF_FORMAT_PCM_32:
1362 *string = "int32";
1363 break;
1364 case SF_FORMAT_FLOAT:
1365 *string = "float";
1366 break;
1367 case SF_FORMAT_DOUBLE:
1368 *string = "double";
1369 break;
1370 case SF_FORMAT_ULAW:
1371 *string = "ulaw";
1372 break;
1373 case SF_FORMAT_ALAW:
1374 *string = "alaw";
1375 break;
1376 default:
1377 *string = "float";
1378 break;
1380 return errNone;
1384 int headerFormatToString(struct SF_INFO *info, const char **string);
1385 int headerFormatToString(struct SF_INFO *info, const char **string){
1386 switch (info->format & SF_FORMAT_TYPEMASK)
1388 case SF_FORMAT_WAV :
1389 *string = "WAV";
1390 break;
1391 case SF_FORMAT_AIFF :
1392 *string = "AIFF";
1393 break ;
1394 case SF_FORMAT_AU :
1395 *string = "SUN";
1396 break ;
1397 case SF_FORMAT_IRCAM :
1398 *string = "IRCAM";
1399 break ;
1400 case SF_FORMAT_RAW :
1401 *string = "raw";
1402 break ;
1403 case SF_FORMAT_W64 :
1404 *string = "WAV";
1405 break ;
1406 case SF_FORMAT_FLAC :
1407 *string = "FLAC";
1408 break ;
1409 // TODO allow other platforms to know vorbis once libsndfile 1.0.18 is established
1410 #if SC_DARWIN || SC_WIN32 || LIBSNDFILE_1018
1411 case SF_FORMAT_VORBIS :
1412 *string = "vorbis";
1413 break ;
1414 #endif
1416 case SF_FORMAT_PAF :
1418 break ;
1420 case SF_FORMAT_SVX :
1422 break ;
1424 case SF_FORMAT_NIST :
1426 break ;
1428 case SF_FORMAT_VOC :
1430 break ;
1432 case SF_FORMAT_MAT4 :
1434 break ;
1436 case SF_FORMAT_MAT5 :
1438 break ;
1440 case SF_FORMAT_PVF :
1442 break ;
1444 case SF_FORMAT_XI :
1446 break ;
1448 case SF_FORMAT_HTK :
1450 break ;
1452 case SF_FORMAT_SDS :
1454 break ;
1456 default :
1457 *string = " ";
1458 break ;
1460 return errNone;
1463 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample);
1464 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample)
1466 int error = 0;
1467 error = headerFormatToString(info, stringHead);
1468 error = sampleFormatToString(info, stringSample);
1469 return error;
1472 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed);
1473 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1475 PyrSlot *a, *b;
1476 char filename[PATH_MAX];
1477 SNDFILE *file;
1478 SF_INFO info;
1479 const char *headerstr;
1480 const char *sampleformatstr;
1482 a = g->sp - 1;
1483 b = g->sp;
1485 if (!isKindOfSlot(b, class_string)) return errWrongType;
1486 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1488 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1489 filename[slotRawString(b)->size] = 0;
1491 info.format = 0;
1492 file = sf_open(filename, SFM_READ, &info);
1495 if (file) {
1496 SetPtr(slotRawObject(a)->slots + 0, file);
1497 sndfileFormatInfoToStrings(&info, &headerstr, &sampleformatstr);
1498 //headerFormatToString(&info, &headerstr);
1499 PyrString *hpstr = newPyrString(g->gc, headerstr, 0, true);
1500 SetObject(slotRawObject(a)->slots+1, hpstr);
1501 PyrString *smpstr = newPyrString(g->gc, sampleformatstr, 0, true);
1502 SetObject(slotRawObject(a)->slots+2, smpstr);
1503 SetInt(slotRawObject(a)->slots + 3, info.frames);
1504 SetInt(slotRawObject(a)->slots + 4, info.channels);
1505 SetInt(slotRawObject(a)->slots + 5, info.samplerate);
1507 SetTrue(a);
1508 } else {
1509 SetNil(a);
1510 SetFalse(a);
1512 return errNone;
1515 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed);
1516 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1518 PyrSlot *a, *b;
1519 char filename[PATH_MAX];
1520 SNDFILE *file;
1521 SF_INFO info;
1522 PyrSlot *headerSlot;
1523 PyrSlot *formatSlot;
1524 int error;
1527 a = g->sp - 1;
1528 b = g->sp;
1530 headerSlot = (slotRawObject(a)->slots + 1);
1531 formatSlot = (slotRawObject(a)->slots + 2);
1534 if (!isKindOfSlot(headerSlot, class_string)) return errWrongType;
1535 if (!isKindOfSlot(formatSlot, class_string)) return errWrongType;
1537 if (!isKindOfSlot(b, class_string)) return errWrongType;
1538 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1540 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1541 filename[slotRawString(b)->size] = 0;
1543 #ifdef SC_WIN32
1544 char* headerFormat = (char *)malloc(slotRawObject(headerSlot)->size);
1545 #else
1546 char headerFormat[slotRawString(headerSlot)->size];
1547 #endif
1548 memcpy(headerFormat, slotRawString(headerSlot)->s, slotRawObject(headerSlot)->size);
1549 headerFormat[slotRawString(headerSlot)->size] = 0;
1551 #ifdef SC_WIN32
1552 char* sampleFormat = (char *)malloc(slotRawString(formatSlot)->size);
1553 #else
1554 char sampleFormat[slotRawString(formatSlot)->size];
1555 #endif
1556 memcpy(sampleFormat, slotRawString(formatSlot)->s, slotRawObject(formatSlot)->size);
1557 sampleFormat[slotRawString(formatSlot)->size] = 0;
1559 error = sndfileFormatInfoFromStrings(&info, headerFormat, sampleFormat);
1560 if(error) {
1561 #ifdef SC_WIN32
1562 free(sampleFormat);
1563 free(headerFormat);
1564 #endif
1565 return errFailed;
1568 if(error) return errFailed;
1569 //slotIntVal(slotRawObject(a)->slots + 3, &info.frames);
1570 slotIntVal(slotRawObject(a)->slots + 4, &info.channels);
1571 slotIntVal(slotRawObject(a)->slots + 5, &info.samplerate);
1573 file = sf_open(filename, SFM_WRITE, &info);
1574 if (file) {
1575 SetPtr(slotRawObject(a)->slots+0, file);
1576 SetTrue(a);
1577 } else {
1578 SetNil(a);
1579 SetFalse(a);
1582 return errNone;
1585 int prSFClose(struct VMGlobals *g, int numArgsPushed);
1586 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1588 PyrSlot *a;
1590 a = g->sp;
1592 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1593 if (file) {
1594 sf_close(file);
1595 SetNil(slotRawObject(a)->slots + 0);
1598 return errNone;
1601 int prSFRead(struct VMGlobals *g, int numArgsPushed);
1602 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1604 PyrSlot *a, *b;
1606 a = g->sp - 1;
1607 b = g->sp;
1609 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1611 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1613 switch (slotRawObject(b)->obj_format) {
1614 case obj_int16 :
1615 slotRawObject(b)->size = sf_read_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1616 break;
1617 case obj_int32 :
1618 slotRawObject(b)->size = sf_read_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1619 break;
1620 case obj_float :
1621 slotRawObject(b)->size = sf_read_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1622 break;
1623 case obj_double :
1624 slotRawObject(b)->size = sf_read_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1625 break;
1626 default:
1627 error("sample format not supported.\n");
1628 return errFailed;
1631 return errNone;
1634 int prSFWrite(struct VMGlobals *g, int numArgsPushed);
1635 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1637 PyrSlot *a, *b;
1639 a = g->sp - 1;
1640 b = g->sp;
1642 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1644 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1646 switch (slotRawObject(b)->obj_format) {
1647 case obj_int16 :
1648 sf_write_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1649 break;
1650 case obj_int32 :
1651 sf_write_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1652 break;
1653 case obj_float :
1654 sf_write_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1655 break;
1656 case obj_double :
1657 sf_write_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1658 break;
1659 default:
1660 error("sample format not supported.\n");
1661 return errFailed;
1664 return errNone;
1667 int prSFSeek(struct VMGlobals *g, int numArgsPushed);
1668 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1670 PyrSlot *a, *b, *c;
1672 a = g->sp - 2;
1673 b = g->sp - 1;
1674 c = g->sp;
1676 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1678 int origin, offset;
1679 int err = slotIntVal(b, &offset);
1680 if (err) return err;
1682 err = slotIntVal(c, &origin);
1683 if (err) return err;
1685 sf_seek(file, offset, origin);
1687 return errNone;
1690 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed);
1691 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1694 PyrSlot *a;
1695 a = g->sp;
1696 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1697 if(file){
1698 static char strbuffer [(1 << 16)] ;
1699 sf_command (file, SFC_GET_LOG_INFO, strbuffer, (1 << 16)) ;
1700 PyrString *pstring = newPyrString(g->gc, strbuffer, 0, true);
1701 // post(strbuffer);
1702 SetObject(a, pstring);
1703 return errNone;
1705 return errFailed;
1708 #else // !NO_LIBSNDFILE
1710 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1712 return errFailed;
1715 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1717 return errFailed;
1720 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1722 return errFailed;
1725 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1727 return errFailed;
1730 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1732 return errFailed;
1735 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1737 return errFailed;
1740 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1742 return errFailed;
1745 #endif // !NO_LIBSNDFILE
1748 //////////
1749 #ifdef NOCLASSIC
1751 int dir_Lookup(char *pathString, int pathStringLength, int index,
1752 /* outputs: */
1753 char *name, int *nameLength, int *creationDate, int *modificationDate,
1754 int *isDirectory, int *isVisible, int *sizeIfFile);
1756 int prDirectory_At(struct VMGlobals *g, int numArgsPushed);
1757 int prDirectory_At(struct VMGlobals *g, int numArgsPushed)
1759 PyrSlot *a = g->sp - 2;
1760 PyrSlot *b = g->sp - 1;
1761 PyrSlot *c = g->sp;
1763 PyrSlot *dirPathSlot = slotRawObject(a)->slots + 0;
1764 int err, index;
1765 err = slotIntVal(c, &index);
1766 if (err) {
1767 SetNil(a);
1768 return err;
1771 char name[256], fullPathName[256];
1772 int nameLength, creationDate, modificationDate, isDirectory, isVisible, sizeIfFile;
1773 int dirPathLength = slotRawObject(dirPathSlot)->size;
1775 err = dir_Lookup(slotRawObject(dirPathSlot)s->s, dirPathLength, index+1,
1776 name, &nameLength, &creationDate, &modificationDate, &isDirectory, &isVisible, &sizeIfFile);
1777 if (err == 1) {
1778 SetNil(a);
1779 return errNone;
1781 if (err) {
1782 error("Invalid path\n");
1783 SetNil(a);
1784 return errFailed;
1787 if (dirPathLength + nameLength + 1 > 255) {
1788 error("Full path name too long.\n");
1789 SetNil(a);
1790 return errFailed;
1793 PyrSlot *entryName = slotRawObject(b)->slots + 0;
1794 PyrSlot *entryPath = slotRawObject(b)->slots + 1;
1795 PyrSlot *entryIsDir = slotRawObject(b)->slots + 2;
1796 PyrSlot *entryIsVisible = slotRawObject(b)->slots + 3;
1798 PyrString *nameString = newPyrString(g->gc, name, 0, true);
1799 SetObject(entryName, nameString);
1800 g->gc->GCWrite(slotRawObject(b), (PyrObject*)nameString);
1802 memcpy(fullPathName, slotRawObject(dirPathSlot)s->s, dirPathLength);
1803 fullPathName[dirPathLength] = DELIMITOR;
1804 strcpy(fullPathName + dirPathLength + 1, name);
1806 PyrString *pathString = newPyrString(g->gc, fullPathName, 0, true);
1807 SetObject(entryPath, pathString);
1808 g->gc->GCWrite(slotRawObject(b), (PyrObject*)pathString);
1810 if (isDirectory) { SetTrue(entryIsDir); } else { SetFalse(entryIsDir); }
1811 if (isVisible) { SetTrue(entryIsVisible); } else { SetFalse(entryIsVisible); }
1813 slotCopy(a,b);
1815 return errNone;
1818 Boolean GetFullPathname(const FSSpec* aSpec, Str255 pathname);
1819 void pstrncpy(unsigned char *s1, unsigned char *s2, int n);
1821 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed);
1822 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed)
1825 PyrSlot *a = g->sp - 1;
1826 PyrSlot *b = g->sp;
1828 NavDialogOptions options;
1830 int err = NavGetDefaultDialogOptions(&options);
1831 if (err) return errFailed;
1833 options.dialogOptionFlags |= kNavNoTypePopup;
1834 options.dialogOptionFlags |= kNavDontAutoTranslate;
1835 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1836 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1837 options.dialogOptionFlags &= ~kNavAllowPreviews;
1838 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1840 if (isKindOfSlot(b, class_string)) {
1841 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1844 NavReplyRecord reply;
1845 err = NavGetFile(0, &reply, &options, 0, 0, 0, 0, 0);
1847 if (err == noErr && reply.validRecord) {
1848 AEKeyword keyword;
1849 DescType actualType;
1850 Size actualSize;
1851 FSSpec fsspec;
1853 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1854 &fsspec, sizeof(FSSpec), &actualSize);
1856 if (err == noErr) {
1857 Str255 pathname;
1858 GetFullPathname(&fsspec, pathname);
1859 p2cstr(pathname);
1860 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1861 SetObject(a, string);
1862 } else {
1863 SetNil(a);
1865 err = NavDisposeReply(&reply);
1866 } else {
1867 SetNil(a);
1869 return errNone;
1874 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed);
1875 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed)
1878 PyrSlot *a = g->sp - 2;
1879 PyrSlot *b = g->sp - 1;
1880 PyrSlot *c = g->sp;
1882 NavDialogOptions options;
1884 int err = NavGetDefaultDialogOptions(&options);
1885 if (err) return errFailed;
1887 options.dialogOptionFlags |= kNavNoTypePopup;
1888 options.dialogOptionFlags |= kNavDontAutoTranslate;
1889 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1890 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1891 options.dialogOptionFlags &= ~kNavAllowPreviews;
1892 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1894 if (isKindOfSlot(b, class_string)) {
1895 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1898 if (isKindOfSlot(c, class_string)) {
1899 pstringFromPyrString((PyrString*)slotRawObject(c), options.savedFileName, 256);
1900 } else {
1901 //pstrncpy(options.savedFileName, "\pUntitled", 255);
1904 NavReplyRecord reply;
1905 err = NavPutFile(0, &reply, &options, 0, 'TEXT', 'SCjm', 0);
1907 if (err == noErr && reply.validRecord) {
1908 AEKeyword keyword;
1909 DescType actualType;
1910 Size actualSize;
1911 FSSpec fsspec;
1913 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1914 &fsspec, sizeof(FSSpec), &actualSize);
1916 if (err == noErr) {
1917 Str255 pathname;
1918 GetFullPathname(&fsspec, pathname);
1919 p2cstr(pathname);
1920 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1921 SetObject(a, string);
1923 err = NavCompleteSave(&reply, kNavTranslateInPlace);
1924 } else {
1925 SetNil(a);
1927 err = NavDisposeReply(&reply);
1928 } else {
1929 SetNil(a);
1931 return errNone;
1934 #endif
1936 /////////////
1938 void initFilePrimitives()
1940 int base, index;
1942 base = nextPrimitiveIndex();
1943 index = 0;
1945 definePrimitive(base, index++, "_SFOpenRead", prSFOpenRead, 2, 0);
1946 definePrimitive(base, index++, "_SFOpenWrite", prSFOpenWrite, 2, 0);
1947 definePrimitive(base, index++, "_SFClose", prSFClose, 1, 0);
1948 definePrimitive(base, index++, "_SFWrite", prSFWrite, 2, 0);
1949 definePrimitive(base, index++, "_SFRead", prSFRead, 2, 0);
1950 definePrimitive(base, index++, "_SFSeek", prSFSeek, 3, 0);
1951 definePrimitive(base, index++, "_SFHeaderInfoString", prSFHeaderInfoString, 1, 0);
1953 definePrimitive(base, index++, "_PipeOpen", prPipeOpen, 3, 0);
1954 definePrimitive(base, index++, "_PipeClose", prPipeClose, 2, 0);
1956 definePrimitive(base, index++, "_FileDelete", prFileDelete, 2, 0);
1957 definePrimitive(base, index++, "_FileMTime", prFileMTime, 2, 0);
1958 definePrimitive(base, index++, "_FileExists", prFileExists, 2, 0);
1959 definePrimitive(base, index++, "_FileRealPath", prFileRealPath, 2, 0);
1960 definePrimitive(base, index++, "_FileMkDir", prFileMkDir, 2, 0);
1961 definePrimitive(base, index++, "_FileCopy", prFileCopy, 3, 0);
1962 definePrimitive(base, index++, "_FileType", prFileType, 2, 0);
1963 definePrimitive(base, index++, "_FileSize", prFileSize, 2, 0);
1965 definePrimitive(base, index++, "_FileOpen", prFileOpen, 3, 0);
1966 definePrimitive(base, index++, "_FileClose", prFileClose, 1, 0);
1967 definePrimitive(base, index++, "_FileFlush", prFileFlush, 1, 0);
1968 definePrimitive(base, index++, "_FileSeek", prFileSeek, 3, 0);
1969 definePrimitive(base, index++, "_FilePos", prFilePos, 1, 0);
1970 definePrimitive(base, index++, "_FileLength", prFileLength, 1, 0);
1971 definePrimitive(base, index++, "_FileWrite", prFileWrite, 2, 0);
1972 definePrimitive(base, index++, "_FileWriteLE", prFileWriteLE, 2, 0);
1973 definePrimitive(base, index++, "_FileReadLine", prFileReadLine, 2, 0);
1974 definePrimitive(base, index++, "_File_getcwd", prFileGetcwd, 2, 0);
1976 definePrimitive(base, index++, "_FilePutChar", prFilePutChar, 2, 0);
1977 definePrimitive(base, index++, "_FilePutInt8", prFilePutInt8, 2, 0);
1978 definePrimitive(base, index++, "_FilePutInt16", prFilePutInt16, 2, 0);
1979 definePrimitive(base, index++, "_FilePutInt32", prFilePutInt32, 2, 0);
1980 definePrimitive(base, index++, "_FilePutFloat", prFilePutFloat, 2, 0);
1981 definePrimitive(base, index++, "_FilePutDouble", prFilePutDouble, 2, 0);
1982 definePrimitive(base, index++, "_FilePutInt16LE", prFilePutInt16LE, 2, 0);
1983 definePrimitive(base, index++, "_FilePutInt32LE", prFilePutInt32LE, 2, 0);
1984 definePrimitive(base, index++, "_FilePutFloatLE", prFilePutFloatLE, 2, 0);
1985 definePrimitive(base, index++, "_FilePutDoubleLE", prFilePutDoubleLE, 2, 0);
1987 definePrimitive(base, index++, "_FileGetChar", prFileGetChar, 1, 0);
1988 definePrimitive(base, index++, "_FileGetInt8", prFileGetInt8, 1, 0);
1989 definePrimitive(base, index++, "_FileGetInt16", prFileGetInt16, 1, 0);
1990 definePrimitive(base, index++, "_FileGetInt32", prFileGetInt32, 1, 0);
1991 definePrimitive(base, index++, "_FileGetFloat", prFileGetFloat, 1, 0);
1992 definePrimitive(base, index++, "_FileGetDouble", prFileGetDouble, 1, 0);
1993 definePrimitive(base, index++, "_FileGetInt16LE", prFileGetInt16LE, 1, 0);
1994 definePrimitive(base, index++, "_FileGetInt32LE", prFileGetInt32LE, 1, 0);
1995 definePrimitive(base, index++, "_FileGetFloatLE", prFileGetFloatLE, 1, 0);
1996 definePrimitive(base, index++, "_FileGetDoubleLE", prFileGetDoubleLE, 1, 0);
1998 definePrimitive(base, index++, "_FilePutString", prFilePutString, 2, 0);
2000 definePrimitive(base, index++, "_FileReadRaw", prFileReadRaw, 2, 0);
2001 definePrimitive(base, index++, "_FileReadRawLE", prFileReadRawLE, 2, 0);
2003 #ifdef NOCLASSIC
2004 definePrimitive(base, index++, "_Directory_At", prDirectory_At, 3, 0);
2005 definePrimitive(base, index++, "_File_GetFile", prFile_GetFile, 2, 0);
2006 definePrimitive(base, index++, "_File_PutFile", prFile_PutFile, 3, 0);
2007 #endif