server: add support for RF64
[supercollider.git] / lang / LangPrimSource / PyrFilePrim.cpp
blobc431d645c8029c086576e14977b3da3bb2b8022f
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 <stdlib.h>
37 #include <string.h>
38 #include <stdarg.h>
39 #include <cerrno>
41 #ifdef NOCLASSIC
42 #include <TextUtils.h>
43 #include <Navigation.h>
44 #endif
46 #ifndef _WIN32
47 # include <unistd.h>
48 #else
49 # include <direct.h>
50 # include <malloc.h>
51 # define strcasecmp stricmp
52 #endif
54 #ifdef _WIN32
55 #include <stdio.h>
56 #include "SC_Win32Utils.h"
57 #include "SC_DirUtils.h"
58 #endif
60 #include <fcntl.h>
61 #include <math.h>
63 #include <boost/filesystem.hpp>
65 #if defined(__APPLE__) || defined(SC_IPHONE)
66 #ifndef _SC_StandAloneInfo_
67 # include "SC_StandAloneInfo_Darwin.h"
68 #endif
69 # include <CoreFoundation/CFString.h>
70 # include <CoreFoundation/CFBundle.h>
71 #ifndef SC_IPHONE
72 # include <CoreServices/CoreServices.h>
73 #endif
74 #endif
76 #define DELIMITOR ':'
78 bool filelen(FILE *file, size_t *length);
80 int prFileDelete(struct VMGlobals *g, int numArgsPushed)
82 PyrSlot *a = g->sp - 1, *b = g->sp;
83 char filename[PATH_MAX];
85 int error = slotStrVal(b, filename, PATH_MAX);
86 if (error != errNone)
87 return error;
89 int err = unlink(filename);
90 SetBool(a, err == 0);
92 return errNone;
95 int prFileMTime(struct VMGlobals * g, int numArgsPushed)
97 PyrSlot *a = g->sp - 1, *b = g->sp;
98 char filename[PATH_MAX];
100 int error = slotStrVal(b, filename, PATH_MAX);
101 if (error != errNone)
102 return error;
104 time_t mtime = boost::filesystem::last_write_time(filename);
105 SetInt(a, mtime);
106 return errNone;
109 int prFileExists(struct VMGlobals * g, int numArgsPushed)
111 PyrSlot *a = g->sp - 1, *b = g->sp;
112 char filename[PATH_MAX];
114 int error = slotStrVal(b, filename, PATH_MAX);
115 if (error != errNone)
116 return error;
118 bool res = boost::filesystem::exists(filename);
119 SetBool(a, res);
120 return errNone;
123 int prFileRealPath(struct VMGlobals* g, int numArgsPushed )
125 PyrSlot *a = g->sp - 1, *b = g->sp;
126 char ipath[PATH_MAX];
127 char opath[PATH_MAX];
128 int err;
130 err = slotStrVal(b, ipath, PATH_MAX);
131 if (err) return err;
133 bool isAlias = false;
134 if(sc_ResolveIfAlias(ipath, opath, isAlias, PATH_MAX)!=0) {
135 return errFailed;
138 boost::system::error_code error_code;
139 boost::filesystem::path p = boost::filesystem::canonical(opath,error_code);
140 if(error_code) {
141 SetNil(a);
142 return errNone;
144 strcpy(opath,p.string().c_str());
146 #if SC_DARWIN
147 CFStringRef cfstring =
148 CFStringCreateWithCString(NULL,
149 opath,
150 kCFStringEncodingUTF8);
151 err = !CFStringGetFileSystemRepresentation(cfstring, opath, PATH_MAX);
152 CFRelease(cfstring);
153 if (err) return errFailed;
154 #endif // SC_DARWIN
156 PyrString* pyrString = newPyrString(g->gc, opath, 0, true);
157 SetObject(a, pyrString);
159 return errNone;
162 int prFileMkDir(struct VMGlobals * g, int numArgsPushed)
164 PyrSlot *a = g->sp - 1, *b = g->sp;
165 char filename[PATH_MAX];
167 int error = slotStrVal(b, filename, PATH_MAX);
168 if (error != errNone)
169 return error;
171 boost::system::error_code error_code;
172 boost::filesystem::create_directories(filename, error_code);
173 if (error_code)
174 postfl("Warning: %s (\"%s\")\n", error_code.message().c_str(), filename);
176 return errNone;
179 int prFileCopy(struct VMGlobals * g, int numArgsPushed)
181 PyrSlot *a = g->sp - 2, *b = g->sp - 1, *c = g->sp;
182 char filename1[PATH_MAX];
183 char filename2[PATH_MAX];
184 int error;
185 error = slotStrVal(b, filename1, PATH_MAX);
186 if (error != errNone)
187 return error;
188 error = slotStrVal(c, filename2, PATH_MAX);
189 if (error != errNone)
190 return error;
192 boost::filesystem3::copy(filename1, filename2);
193 return errNone;
196 int prFileType(struct VMGlobals * g, int numArgsPushed)
198 PyrSlot *a = g->sp - 1, *b = g->sp;
199 char filename[PATH_MAX];
201 int error = slotStrVal(b, filename, PATH_MAX);
202 if (error != errNone)
203 return error;
205 boost::filesystem::file_status s(boost::filesystem::symlink_status(filename));
206 SetInt(a, s.type());
207 return errNone;
210 int prFileSize(struct VMGlobals * g, int numArgsPushed)
212 PyrSlot *a = g->sp - 1, *b = g->sp;
213 char filename[PATH_MAX];
215 int error = slotStrVal(b, filename, PATH_MAX);
216 if (error != errNone)
217 return error;
219 uintmax_t sz = boost::filesystem::file_size(filename);
220 SetInt(a, sz);
221 return errNone;
225 int prFileOpen(struct VMGlobals *g, int numArgsPushed)
227 PyrSlot *a, *b, *c;
228 char filename[PATH_MAX];
229 char mode[12];
230 PyrFile *pfile;
231 FILE *file;
233 a = g->sp - 2;
234 b = g->sp - 1;
235 c = g->sp;
236 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
237 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
238 return errWrongType;
239 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
240 if (slotRawObject(c)->size > 11) return errFailed;
241 pfile = (PyrFile*)slotRawObject(a);
243 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
244 filename[slotRawString(b)->size] = 0;
246 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
247 mode[slotRawString(c)->size] = 0;
249 #ifdef SC_WIN32
250 win32_ReplaceCharInString(filename,PATH_MAX,'/','\\');
251 if(strcmp(mode,"w") == 0)
252 strcpy(mode,"wb");
253 if(strcmp(mode,"r") == 0)
254 strcpy(mode,"rb");
255 #endif
256 //SC_WIN32
257 file = fopen(filename, mode);
258 if (file) {
259 SetPtr(&pfile->fileptr, file);
260 SetTrue(a);
261 } else {
262 #ifdef SC_WIN32
263 // check if directory exisits
264 // create a temporary file (somewhere) for a handle
265 // the file is deleted automatically when closed
266 if (sc_DirectoryExists(filename)) {
267 int err;
268 #ifdef _MSC_VER
269 err = tmpfile_s(&file);
270 if (!err) {
271 SetPtr(&pfile->fileptr, file);
272 SetTrue(a);
273 return errNone;
275 #elif defined(__MINGW32__)
276 file = tmpfile();
277 if (file) {
278 SetPtr(&pfile->fileptr, file);
279 SetTrue(a);
280 return errNone;
282 #else
283 #error compiler unsupported
284 #endif
286 #endif
287 SetNil(a);
288 SetFalse(a);
290 return errNone;
293 int prFileClose(struct VMGlobals *g, int numArgsPushed)
295 PyrSlot *a;
296 PyrFile *pfile;
297 FILE *file;
299 a = g->sp;
300 pfile = (PyrFile*)slotRawObject(a);
301 file = (FILE*)slotRawPtr(&pfile->fileptr);
302 if (file == NULL) return errNone;
303 SetPtr(&pfile->fileptr, NULL);
304 if (fclose(file)) return errFailed;
305 return errNone;
308 int prFileFlush(struct VMGlobals *g, int numArgsPushed)
310 PyrSlot *a;
311 PyrFile *pfile;
312 FILE *file;
314 a = g->sp;
315 pfile = (PyrFile*)slotRawObject(a);
316 file = (FILE*)slotRawPtr(&pfile->fileptr);
317 if (file != NULL) fflush(file);
318 return errNone;
321 int prFilePos(struct VMGlobals *g, int numArgsPushed)
323 PyrSlot *a;
324 PyrFile *pfile;
325 FILE *file;
326 fpos_t pos;
327 int length;
329 a = g->sp;
330 pfile = (PyrFile*)slotRawObject(a);
331 file = (FILE*)slotRawPtr(&pfile->fileptr);
332 if (file == NULL) return errFailed;
333 if (fgetpos(file, &pos)) return errFailed;
335 #ifdef SC_LINUX
336 // sk: hack alert!
337 length = pos.__pos;
338 #else
339 length = pos;
340 #endif
342 SetInt(a, length);
343 return errNone;
346 int prFileLength(struct VMGlobals *g, int numArgsPushed)
348 PyrSlot *a;
349 PyrFile *pfile;
350 FILE *file;
351 fpos_t pos;
352 size_t length;
354 a = g->sp;
355 pfile = (PyrFile*)slotRawObject(a);
356 file = (FILE*)slotRawPtr(&pfile->fileptr);
357 if (file == NULL) return errFailed;
358 // preserve file position
359 if (fgetpos(file, &pos)) return errFailed;
360 if (filelen(file, &length)) return errFailed;
361 if (fsetpos(file, &pos)) return errFailed;
363 SetInt(a, length);
364 return errNone;
367 int prFileSeek(struct VMGlobals *g, int numArgsPushed)
369 PyrSlot *a, *b, *c;
370 PyrFile *pfile;
371 FILE *file;
372 size_t offset;
373 int origin;
374 static int originTable[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
376 a = g->sp - 2;
377 b = g->sp - 1;
378 c = g->sp;
379 if (NotInt(b)) return errWrongType;
380 if (NotInt(c)) return errWrongType;
381 pfile = (PyrFile*)slotRawObject(a);
382 file = (FILE*)slotRawPtr(&pfile->fileptr);
383 if (file == NULL) return errFailed;
384 offset = slotRawInt(b);
385 origin = slotRawInt(c);
386 if (origin < 0 || origin > 2) return errIndexOutOfRange;
387 origin = originTable[origin]; // translate in case ANSI constants ever change..
388 if (fseek(file, offset, origin)) return errFailed;
389 return errNone;
393 int prFileWrite(struct VMGlobals *g, int numArgsPushed)
395 PyrSlot *a, *b, *ptr;
396 PyrFile *pfile;
397 FILE *file;
398 PyrObject *obj;
399 char chr;
401 a = g->sp - 1;
402 b = g->sp;
403 pfile = (PyrFile*)slotRawObject(a);
404 file = (FILE*)slotRawPtr(&pfile->fileptr);
405 if (file == NULL) return errFailed;
406 switch (GetTag(b)) {
407 case tagInt :
409 SC_IOStream<FILE*> scio(file);
410 scio.writeInt32_be(slotRawInt(b));
411 break;
413 case tagSym :
414 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
415 break;
416 case tagChar :
417 chr = slotRawChar(b);
418 fwrite(&chr, sizeof(char), 1, file);
419 break;
420 case tagNil :
421 case tagFalse :
422 case tagTrue :
423 case tagPtr :
424 return errWrongType;
425 case tagObj :
427 // writes the indexable part of any non obj_slot format object
428 obj = slotRawObject(b);
429 if (!isKindOf(obj, class_rawarray)
430 || isKindOf(obj, class_symbolarray)) return errWrongType;
431 if (obj->size) {
432 ptr = obj->slots;
433 int elemSize = gFormatElemSize[obj->obj_format];
434 int numElems = obj->size;
435 #if BYTE_ORDER != BIG_ENDIAN
436 switch (elemSize) {
437 case 1:
438 fwrite(ptr, elemSize, numElems, file);
439 break;
440 case 2:
442 char *ptr = slotRawString(b)->s;
443 char *ptrend = ptr + numElems*2;
444 for (; ptr < ptrend; ptr+=2) {
445 fputc(ptr[1], file);
446 fputc(ptr[0], file);
448 break;
450 case 4:
452 char *ptr = slotRawString(b)->s;
453 char *ptrend = ptr + numElems*4;
454 for (; ptr < ptrend; ptr+=4) {
455 fputc(ptr[3], file);
456 fputc(ptr[2], file);
457 fputc(ptr[1], file);
458 fputc(ptr[0], file);
460 break;
462 case 8:
464 char *ptr = slotRawString(b)->s;
465 char *ptrend = ptr + numElems*8;
466 for (; ptr < ptrend; ptr+=8) {
467 fputc(ptr[7], file);
468 fputc(ptr[6], file);
469 fputc(ptr[5], file);
470 fputc(ptr[4], file);
471 fputc(ptr[3], file);
472 fputc(ptr[2], file);
473 fputc(ptr[1], file);
474 fputc(ptr[0], file);
476 break;
479 #else
480 fwrite(ptr, elemSize, numElems, file);
481 #endif
483 break;
485 default : // double
487 SC_IOStream<FILE*> scio(file);
488 scio.writeDouble_be(slotRawFloat(b));
489 break;
492 return errNone;
496 int prFileWriteLE(struct VMGlobals *g, int numArgsPushed)
498 PyrSlot *a, *b, *ptr;
499 PyrFile *pfile;
500 FILE *file;
501 PyrObject *obj;
502 char chr;
504 a = g->sp - 1;
505 b = g->sp;
506 pfile = (PyrFile*)slotRawObject(a);
507 file = (FILE*)slotRawPtr(&pfile->fileptr);
508 if (file == NULL) return errFailed;
509 switch (GetTag(b)) {
510 case tagInt :
512 SC_IOStream<FILE*> scio(file);
513 scio.writeInt32_le(slotRawInt(b));
514 break;
516 case tagSym :
517 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
518 break;
519 case tagChar :
520 chr = slotRawInt(b);
521 fwrite(&chr, sizeof(char), 1, file);
522 break;
523 case tagNil :
524 case tagFalse :
525 case tagTrue :
526 case tagPtr :
527 return errWrongType;
528 case tagObj :
530 // writes the indexable part of any non obj_slot format object
531 obj = slotRawObject(b);
532 if (!isKindOf(obj, class_rawarray)
533 || isKindOf(obj, class_symbolarray)) return errWrongType;
534 if (obj->size) {
535 ptr = obj->slots;
536 int elemSize = gFormatElemSize[obj->obj_format];
537 int numElems = obj->size;
538 #if BYTE_ORDER == BIG_ENDIAN
539 switch (elemSize) {
540 case 1:
541 fwrite(ptr, elemSize, numElems, file);
542 break;
543 case 2:
545 char *ptr = slotRawString(b)->s;
546 char *ptrend = ptr + numElems*2;
547 for (; ptr < ptrend; ptr+=2) {
548 fputc(ptr[1], file);
549 fputc(ptr[0], file);
551 break;
553 case 4:
555 char *ptr = slotRawString(b)->s;
556 char *ptrend = ptr + numElems*4;
557 for (; ptr < ptrend; ptr+=4) {
558 fputc(ptr[3], file);
559 fputc(ptr[2], file);
560 fputc(ptr[1], file);
561 fputc(ptr[0], file);
563 break;
565 case 8:
567 char *ptr = slotRawString(b)->s;
568 char *ptrend = ptr + numElems*8;
569 for (; ptr < ptrend; ptr+=8) {
570 fputc(ptr[7], file);
571 fputc(ptr[6], file);
572 fputc(ptr[5], file);
573 fputc(ptr[4], file);
574 fputc(ptr[3], file);
575 fputc(ptr[2], file);
576 fputc(ptr[1], file);
577 fputc(ptr[0], file);
579 break;
582 #else
583 fwrite(ptr, elemSize, numElems, file);
584 #endif
586 break;
588 default : // double
590 SC_IOStream<FILE*> scio(file);
591 scio.writeDouble_le(slotRawFloat(b));
592 break;
595 return errNone;
598 int prFileReadLine(struct VMGlobals *g, int numArgsPushed)
600 PyrSlot *a, *b; // receiver(a File), string
601 PyrFile *pfile;
602 FILE *file;
604 a = g->sp - 1;
605 b = g->sp;
607 pfile = (PyrFile*)slotRawObject(a);
608 file = (FILE*)slotRawPtr(&pfile->fileptr);
609 if (file == NULL) return errFailed;
611 char* result = fgets(slotRawString(b)->s, MAXINDEXSIZE(slotRawObject(b)) - 1, file);
612 if (!result) {
613 SetNil(a);
614 } else {
615 slotRawString(b)->size = strlen(slotRawString(b)->s);
616 if (slotRawString(b)->s[slotRawString(b)->size-1] == '\n') slotRawString(b)->size--;
617 slotCopy(a,b);
619 return errNone;
622 int prFilePutInt32(struct VMGlobals *g, int numArgsPushed)
624 PyrSlot *a, *b;
625 PyrFile *pfile;
626 FILE *file;
628 a = g->sp - 1;
629 b = g->sp;
631 pfile = (PyrFile*)slotRawObject(a);
632 file = (FILE*)slotRawPtr(&pfile->fileptr);
633 if (file == NULL) return errFailed;
635 int val;
636 int err = slotIntVal(b, &val);
637 if (err) return err;
639 SC_IOStream<FILE*> scio(file);
640 scio.writeInt32_be(val);
642 return errNone;
645 int prFilePutInt16(struct VMGlobals *g, int numArgsPushed)
647 PyrSlot *a, *b;
648 PyrFile *pfile;
649 FILE *file;
651 a = g->sp - 1;
652 b = g->sp;
654 pfile = (PyrFile*)slotRawObject(a);
655 file = (FILE*)slotRawPtr(&pfile->fileptr);
656 if (file == NULL) return errFailed;
658 int val;
659 int err = slotIntVal(b, &val);
660 if (err) return err;
663 SC_IOStream<FILE*> scio(file);
664 scio.writeInt16_be(val);
666 return errNone;
670 int prFilePutInt32LE(struct VMGlobals *g, int numArgsPushed)
672 PyrSlot *a, *b;
673 PyrFile *pfile;
674 FILE *file;
676 a = g->sp - 1;
677 b = g->sp;
679 pfile = (PyrFile*)slotRawObject(a);
680 file = (FILE*)slotRawPtr(&pfile->fileptr);
681 if (file == NULL) return errFailed;
683 int val;
684 int err = slotIntVal(b, &val);
685 if (err) return err;
687 SC_IOStream<FILE*> scio(file);
688 scio.writeInt32_le(val);
690 return errNone;
693 int prFilePutInt16LE(struct VMGlobals *g, int numArgsPushed)
695 PyrSlot *a, *b;
696 PyrFile *pfile;
697 FILE *file;
699 a = g->sp - 1;
700 b = g->sp;
702 pfile = (PyrFile*)slotRawObject(a);
703 file = (FILE*)slotRawPtr(&pfile->fileptr);
704 if (file == NULL) return errFailed;
706 int val;
707 int err = slotIntVal(b, &val);
708 if (err) return err;
711 SC_IOStream<FILE*> scio(file);
712 scio.writeInt16_le(val);
714 return errNone;
717 int prFilePutInt8(struct VMGlobals *g, int numArgsPushed)
719 PyrSlot *a, *b;
720 PyrFile *pfile;
721 FILE *file;
723 a = g->sp - 1;
724 b = g->sp;
726 pfile = (PyrFile*)slotRawObject(a);
727 file = (FILE*)slotRawPtr(&pfile->fileptr);
728 if (file == NULL) return errFailed;
730 int val;
731 int err = slotIntVal(b, &val);
732 if (err) return err;
735 SC_IOStream<FILE*> scio(file);
736 scio.writeInt8(val);
738 return errNone;
741 int prFilePutChar(struct VMGlobals *g, int numArgsPushed)
743 PyrSlot *a, *b;
744 PyrFile *pfile;
745 FILE *file;
746 char z;
748 a = g->sp - 1;
749 b = g->sp;
751 pfile = (PyrFile*)slotRawObject(a);
752 file = (FILE*)slotRawPtr(&pfile->fileptr);
753 if (file == NULL) return errFailed;
754 if (NotChar(b)) return errWrongType;
756 z = slotRawInt(b);
758 SC_IOStream<FILE*> scio(file);
759 scio.writeInt8(z);
761 return errNone;
764 int prFilePutFloat(struct VMGlobals *g, int numArgsPushed)
766 PyrSlot *a, *b;
767 PyrFile *pfile;
768 FILE *file;
770 a = g->sp - 1;
771 b = g->sp;
773 pfile = (PyrFile*)slotRawObject(a);
774 file = (FILE*)slotRawPtr(&pfile->fileptr);
775 if (file == NULL) {
776 dumpObjectSlot(a);
777 return errFailed;
780 float val;
781 int err = slotFloatVal(b, &val);
782 if (err) return err;
784 SC_IOStream<FILE*> scio(file);
785 scio.writeFloat_be(val);
787 return errNone;
790 int prFilePutDouble(struct VMGlobals *g, int numArgsPushed)
792 PyrSlot *a, *b;
793 PyrFile *pfile;
794 FILE *file;
796 a = g->sp - 1;
797 b = g->sp;
799 pfile = (PyrFile*)slotRawObject(a);
800 file = (FILE*)slotRawPtr(&pfile->fileptr);
801 if (file == NULL) return errFailed;
804 double val;
805 int err = slotDoubleVal(b, &val);
806 if (err) return err;
808 SC_IOStream<FILE*> scio(file);
809 scio.writeDouble_be(val);
811 return errNone;
815 int prFilePutFloatLE(struct VMGlobals *g, int numArgsPushed)
817 PyrSlot *a, *b;
818 PyrFile *pfile;
819 FILE *file;
821 a = g->sp - 1;
822 b = g->sp;
824 pfile = (PyrFile*)slotRawObject(a);
825 file = (FILE*)slotRawPtr(&pfile->fileptr);
826 if (file == NULL) {
827 dumpObjectSlot(a);
828 return errFailed;
831 float val;
832 int err = slotFloatVal(b, &val);
833 if (err) return err;
835 SC_IOStream<FILE*> scio(file);
836 scio.writeFloat_le(val);
838 return errNone;
841 int prFilePutDoubleLE(struct VMGlobals *g, int numArgsPushed)
843 PyrSlot *a, *b;
844 PyrFile *pfile;
845 FILE *file;
847 a = g->sp - 1;
848 b = g->sp;
850 pfile = (PyrFile*)slotRawObject(a);
851 file = (FILE*)slotRawPtr(&pfile->fileptr);
852 if (file == NULL) return errFailed;
855 double val;
856 int err = slotDoubleVal(b, &val);
857 if (err) return err;
859 SC_IOStream<FILE*> scio(file);
860 scio.writeDouble_le(val);
862 return errNone;
865 int prFilePutString(struct VMGlobals *g, int numArgsPushed)
867 PyrSlot *a, *b;
868 PyrFile *pfile;
869 FILE *file;
870 PyrString *string;
872 a = g->sp - 1;
873 b = g->sp;
874 pfile = (PyrFile*)slotRawObject(a);
875 file = (FILE*)slotRawPtr(&pfile->fileptr);
876 if (file == NULL) return errFailed;
877 if (NotObj(b) || slotRawObject(b)->classptr != class_string) return errWrongType;
878 string = slotRawString(b);
879 if (string->size) {
880 fwrite(string->s, 1, string->size, file);
882 return errNone;
886 int prFileGetDouble(struct VMGlobals *g, int numArgsPushed)
888 PyrSlot *a;
889 PyrFile *pfile;
890 FILE *file;
892 a = g->sp;
894 pfile = (PyrFile*)slotRawObject(a);
895 file = (FILE*)slotRawPtr(&pfile->fileptr);
896 if (file == NULL) return errFailed;
898 if (feof(file)) SetNil(a);
899 else {
900 SC_IOStream<FILE*> scio(file);
901 SetFloat(a, scio.readDouble_be());
903 return errNone;
906 int prFileGetFloat(struct VMGlobals *g, int numArgsPushed)
908 PyrSlot *a;
909 PyrFile *pfile;
910 FILE *file;
912 a = g->sp;
914 pfile = (PyrFile*)slotRawObject(a);
915 file = (FILE*)slotRawPtr(&pfile->fileptr);
916 if (file == NULL) return errFailed;
918 if (feof(file)) SetNil(a);
919 else {
920 SC_IOStream<FILE*> scio(file);
921 SetFloat(a, scio.readFloat_be());
923 return errNone;
927 int prFileGetDoubleLE(struct VMGlobals *g, int numArgsPushed)
929 PyrSlot *a;
930 PyrFile *pfile;
931 FILE *file;
933 a = g->sp;
935 pfile = (PyrFile*)slotRawObject(a);
936 file = (FILE*)slotRawPtr(&pfile->fileptr);
937 if (file == NULL) return errFailed;
939 if (feof(file)) SetNil(a);
940 else {
941 SC_IOStream<FILE*> scio(file);
942 SetFloat(a, scio.readDouble_le());
944 return errNone;
947 int prFileGetFloatLE(struct VMGlobals *g, int numArgsPushed)
949 PyrSlot *a;
950 PyrFile *pfile;
951 FILE *file;
953 a = g->sp;
955 pfile = (PyrFile*)slotRawObject(a);
956 file = (FILE*)slotRawPtr(&pfile->fileptr);
957 if (file == NULL) return errFailed;
959 if (feof(file)) SetNil(a);
960 else {
961 SC_IOStream<FILE*> scio(file);
962 SetFloat(a, scio.readFloat_le());
964 return errNone;
967 int prFileGetChar(struct VMGlobals *g, int numArgsPushed)
969 PyrSlot *a;
970 PyrFile *pfile;
971 FILE *file;
972 char z;
974 a = g->sp;
976 pfile = (PyrFile*)slotRawObject(a);
977 file = (FILE*)slotRawPtr(&pfile->fileptr);
978 if (file == NULL) return errFailed;
980 int count = fread(&z, sizeof(char), 1, file);
981 if (count==0) SetNil(a);
982 else SetChar(a, z);
983 return errNone;
986 int prFileGetInt8(struct VMGlobals *g, int numArgsPushed)
988 PyrSlot *a;
989 PyrFile *pfile;
990 FILE *file;
991 char z;
993 a = g->sp;
995 pfile = (PyrFile*)slotRawObject(a);
996 file = (FILE*)slotRawPtr(&pfile->fileptr);
997 if (file == NULL) return errFailed;
999 int count = fread(&z, sizeof(char), 1, file);
1000 if (count==0) SetNil(a);
1001 else SetInt(a, z);
1002 return errNone;
1005 int prFileGetInt16(struct VMGlobals *g, int numArgsPushed)
1007 PyrSlot *a;
1008 PyrFile *pfile;
1009 FILE *file;
1011 a = g->sp;
1013 pfile = (PyrFile*)slotRawObject(a);
1014 file = (FILE*)slotRawPtr(&pfile->fileptr);
1015 if (file == NULL) return errFailed;
1017 if (feof(file)) SetNil(a);
1018 else {
1019 SC_IOStream<FILE*> scio(file);
1020 SetInt(a, scio.readInt16_be());
1022 return errNone;
1025 int prFileGetInt32(struct VMGlobals *g, int numArgsPushed)
1027 PyrSlot *a;
1028 PyrFile *pfile;
1029 FILE *file;
1031 a = g->sp;
1033 pfile = (PyrFile*)slotRawObject(a);
1034 file = (FILE*)slotRawPtr(&pfile->fileptr);
1035 if (file == NULL)
1036 return errFailed;
1038 if (feof(file)) SetNil(a);
1039 else {
1040 SC_IOStream<FILE*> scio(file);
1041 SetInt(a, scio.readInt32_be());
1043 return errNone;
1047 int prFileGetInt16LE(struct VMGlobals *g, int numArgsPushed)
1049 PyrSlot *a;
1050 PyrFile *pfile;
1051 FILE *file;
1053 a = g->sp;
1055 pfile = (PyrFile*)slotRawObject(a);
1056 file = (FILE*)slotRawPtr(&pfile->fileptr);
1057 if (file == NULL) return errFailed;
1059 if (feof(file)) SetNil(a);
1060 else {
1061 SC_IOStream<FILE*> scio(file);
1062 SetInt(a, scio.readInt16_le());
1064 return errNone;
1067 int prFileGetInt32LE(struct VMGlobals *g, int numArgsPushed)
1069 PyrSlot *a;
1070 PyrFile *pfile;
1071 FILE *file;
1073 a = g->sp;
1075 pfile = (PyrFile*)slotRawObject(a);
1076 file = (FILE*)slotRawPtr(&pfile->fileptr);
1077 if (file == NULL) return errFailed;
1079 if (feof(file)) SetNil(a);
1080 else {
1081 SC_IOStream<FILE*> scio(file);
1082 SetInt(a, scio.readInt32_le());
1084 return errNone;
1087 int prFileReadRaw(struct VMGlobals *g, int numArgsPushed)
1089 PyrFile *pfile;
1090 FILE *file;
1092 PyrSlot* a = g->sp - 1;
1093 PyrSlot* b = g->sp;
1095 if (!isKindOfSlot(b, class_rawarray)
1096 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1098 pfile = (PyrFile*)slotRawObject(a);
1099 file = (FILE*)slotRawPtr(&pfile->fileptr);
1100 if (file == NULL) return errFailed;
1102 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1103 int numElems = slotRawObject(b)->size;
1104 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1105 slotRawObject(b)->size = numElems;
1107 #if BYTE_ORDER != BIG_ENDIAN
1108 switch (elemSize) {
1109 case 1:
1110 break;
1111 case 2:
1113 char *ptr = slotRawString(b)->s;
1114 char *ptrend = ptr + numElems*2;
1115 for (; ptr < ptrend; ptr+=2) {
1116 char temp = ptr[0];
1117 ptr[0] = ptr[1];
1118 ptr[1] = temp;
1120 break;
1122 case 4:
1124 char *ptr = slotRawString(b)->s;
1125 char *ptrend = ptr + numElems*4;
1126 for (; ptr < ptrend; ptr+=4) {
1127 char temp = ptr[0];
1128 ptr[0] = ptr[3];
1129 ptr[3] = temp;
1131 temp = ptr[1];
1132 ptr[1] = ptr[2];
1133 ptr[2] = temp;
1135 break;
1137 case 8:
1139 char *ptr = slotRawString(b)->s;
1140 char *ptrend = ptr + numElems*8;
1141 for (; ptr < ptrend; ptr+=8) {
1142 char temp = ptr[0];
1143 ptr[0] = ptr[7];
1144 ptr[7] = temp;
1146 temp = ptr[1];
1147 ptr[1] = ptr[6];
1148 ptr[6] = temp;
1150 temp = ptr[2];
1151 ptr[2] = ptr[5];
1152 ptr[5] = temp;
1154 temp = ptr[3];
1155 ptr[3] = ptr[4];
1156 ptr[4] = temp;
1158 break;
1161 #endif
1163 if (slotRawObject(b)->size==0) SetNil(a);
1164 else slotCopy(a,b);
1165 return errNone;
1168 int prFileReadRawLE(struct VMGlobals *g, int numArgsPushed)
1170 PyrFile *pfile;
1171 FILE *file;
1173 PyrSlot* a = g->sp - 1;
1174 PyrSlot* b = g->sp;
1176 if (!isKindOfSlot(b, class_rawarray)
1177 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1179 pfile = (PyrFile*)slotRawObject(a);
1180 file = (FILE*)slotRawPtr(&pfile->fileptr);
1181 if (file == NULL) return errFailed;
1183 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1184 int numElems = slotRawObject(b)->size;
1185 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1186 slotRawObject(b)->size = numElems;
1188 #if BYTE_ORDER == BIG_ENDIAN
1189 switch (elemSize) {
1190 case 1:
1191 break;
1192 case 2:
1194 char *ptr = slotRawString(b)->s;
1195 char *ptrend = ptr + numElems*2;
1196 for (; ptr < ptrend; ptr+=2) {
1197 char temp = ptr[0];
1198 ptr[0] = ptr[1];
1199 ptr[1] = temp;
1201 break;
1203 case 4:
1205 char *ptr = slotRawString(b)->s;
1206 char *ptrend = ptr + numElems*4;
1207 for (; ptr < ptrend; ptr+=4) {
1208 char temp = ptr[0];
1209 ptr[0] = ptr[3];
1210 ptr[3] = temp;
1212 temp = ptr[1];
1213 ptr[1] = ptr[2];
1214 ptr[2] = temp;
1216 break;
1218 case 8:
1220 char *ptr = slotRawString(b)->s;
1221 char *ptrend = ptr + numElems*8;
1222 for (; ptr < ptrend; ptr+=8) {
1223 char temp = ptr[0];
1224 ptr[0] = ptr[7];
1225 ptr[7] = temp;
1227 temp = ptr[1];
1228 ptr[1] = ptr[6];
1229 ptr[6] = temp;
1231 temp = ptr[2];
1232 ptr[2] = ptr[5];
1233 ptr[5] = temp;
1235 temp = ptr[3];
1236 ptr[3] = ptr[4];
1237 ptr[4] = temp;
1239 break;
1242 #endif
1244 if (slotRawObject(b)->size==0) SetNil(a);
1245 else slotCopy(a,b);
1246 return errNone;
1249 int prFileGetcwd(struct VMGlobals *g, int numArgsPushed)
1251 //PyrSlot* a = g->sp - 1; // File
1252 PyrSlot* string = g->sp;
1254 if (!isKindOfSlot(string, class_string)) return errWrongType;
1256 char * cwd = getcwd(slotRawString(string)->s,255);
1257 if (cwd == NULL) {
1258 error(strerror(errno));
1259 return errFailed;
1261 slotRawString(string)->size = strlen(slotRawString(string)->s);
1263 return errNone;
1266 ////////
1268 #ifndef SC_WIN32
1269 int prPipeOpen(struct VMGlobals *g, int numArgsPushed)
1271 PyrSlot *a, *b, *c;
1272 char mode[12];
1273 PyrFile *pfile;
1274 FILE *file;
1276 a = g->sp - 2;
1277 b = g->sp - 1;
1278 c = g->sp;
1280 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
1281 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
1282 return errWrongType;
1283 if (slotRawObject(c)->size > 11) return errFailed;
1284 pfile = (PyrFile*)slotRawObject(a);
1286 char *commandLine = (char*)malloc(slotRawObject(b)->size + 1);
1287 memcpy(commandLine, slotRawString(b)->s, slotRawObject(b)->size);
1288 commandLine[slotRawString(b)->size] = 0;
1290 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
1291 mode[slotRawString(c)->size] = 0;
1293 file = popen(commandLine, mode);
1294 free(commandLine);
1295 if (file) {
1296 SetPtr(&pfile->fileptr, file);
1297 SetTrue(a);
1298 } else {
1299 SetNil(a);
1300 SetFalse(a);
1302 return errNone;
1305 int prPipeClose(struct VMGlobals *g, int numArgsPushed)
1307 PyrSlot *a;
1308 PyrFile *pfile;
1309 FILE *file;
1311 a = g->sp;
1312 pfile = (PyrFile*)slotRawObject(a);
1313 file = (FILE*)slotRawPtr(&pfile->fileptr);
1314 if (file == NULL) return errNone;
1315 SetPtr(&pfile->fileptr, NULL);
1316 int perr = pclose(file);
1317 SetInt(a, perr);
1318 if (perr == -1)
1319 return errFailed;
1320 return errNone;
1322 #endif
1324 ////////
1326 #ifndef NO_LIBSNDFILE
1328 #ifdef SC_WIN32
1329 #include <sndfile-win.h>
1330 #else
1331 #include <sndfile.h>
1332 #endif
1335 int sampleFormatToString(struct SF_INFO *info, const char **string);
1336 int sampleFormatToString(struct SF_INFO *info, const char **string)
1338 unsigned int format = info->format & SF_FORMAT_SUBMASK;
1339 switch (format)
1341 case SF_FORMAT_DPCM_8:
1342 case SF_FORMAT_PCM_S8:
1343 *string = "int16";
1344 break;
1345 case SF_FORMAT_DPCM_16:
1346 case SF_FORMAT_PCM_16:
1347 case SF_FORMAT_DWVW_16:
1348 *string = "int16";
1349 break;
1350 case SF_FORMAT_PCM_24:
1351 case SF_FORMAT_DWVW_24:
1352 *string = "int24";
1353 break;
1354 case SF_FORMAT_PCM_32:
1355 *string = "int32";
1356 break;
1357 case SF_FORMAT_FLOAT:
1358 *string = "float";
1359 break;
1360 case SF_FORMAT_DOUBLE:
1361 *string = "double";
1362 break;
1363 case SF_FORMAT_ULAW:
1364 *string = "ulaw";
1365 break;
1366 case SF_FORMAT_ALAW:
1367 *string = "alaw";
1368 break;
1369 default:
1370 *string = "float";
1371 break;
1373 return errNone;
1377 int headerFormatToString(struct SF_INFO *info, const char **string);
1378 int headerFormatToString(struct SF_INFO *info, const char **string){
1379 switch (info->format & SF_FORMAT_TYPEMASK)
1381 case SF_FORMAT_WAV :
1382 *string = "WAV";
1383 break;
1384 case SF_FORMAT_AIFF :
1385 *string = "AIFF";
1386 break ;
1387 case SF_FORMAT_AU :
1388 *string = "SUN";
1389 break ;
1390 case SF_FORMAT_IRCAM :
1391 *string = "IRCAM";
1392 break ;
1393 case SF_FORMAT_RAW :
1394 *string = "raw";
1395 break ;
1396 case SF_FORMAT_W64 :
1397 *string = "WAV";
1398 break ;
1399 case SF_FORMAT_FLAC :
1400 *string = "FLAC";
1401 break ;
1402 // TODO allow other platforms to know vorbis once libsndfile 1.0.18 is established
1403 #if SC_DARWIN || SC_WIN32 || LIBSNDFILE_1018
1404 case SF_FORMAT_VORBIS :
1405 *string = "vorbis";
1406 break ;
1407 #endif
1409 case SF_FORMAT_PAF :
1411 break ;
1413 case SF_FORMAT_SVX :
1415 break ;
1417 case SF_FORMAT_NIST :
1419 break ;
1421 case SF_FORMAT_VOC :
1423 break ;
1425 case SF_FORMAT_MAT4 :
1427 break ;
1429 case SF_FORMAT_MAT5 :
1431 break ;
1433 case SF_FORMAT_PVF :
1435 break ;
1437 case SF_FORMAT_XI :
1439 break ;
1441 case SF_FORMAT_HTK :
1443 break ;
1445 case SF_FORMAT_SDS :
1447 break ;
1449 default :
1450 *string = " ";
1451 break ;
1453 return errNone;
1456 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample);
1457 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample)
1459 int error = 0;
1460 error = headerFormatToString(info, stringHead);
1461 error = sampleFormatToString(info, stringSample);
1462 return error;
1465 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed);
1466 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1468 PyrSlot *a, *b;
1469 char filename[PATH_MAX];
1470 SNDFILE *file;
1471 SF_INFO info;
1472 const char *headerstr;
1473 const char *sampleformatstr;
1475 a = g->sp - 1;
1476 b = g->sp;
1478 if (!isKindOfSlot(b, class_string)) return errWrongType;
1479 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1481 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1482 filename[slotRawString(b)->size] = 0;
1484 info.format = 0;
1485 file = sf_open(filename, SFM_READ, &info);
1488 if (file) {
1489 SetPtr(slotRawObject(a)->slots + 0, file);
1490 sndfileFormatInfoToStrings(&info, &headerstr, &sampleformatstr);
1491 //headerFormatToString(&info, &headerstr);
1492 PyrString *hpstr = newPyrString(g->gc, headerstr, 0, true);
1493 SetObject(slotRawObject(a)->slots+1, hpstr);
1494 PyrString *smpstr = newPyrString(g->gc, sampleformatstr, 0, true);
1495 SetObject(slotRawObject(a)->slots+2, smpstr);
1496 SetInt(slotRawObject(a)->slots + 3, info.frames);
1497 SetInt(slotRawObject(a)->slots + 4, info.channels);
1498 SetInt(slotRawObject(a)->slots + 5, info.samplerate);
1500 SetTrue(a);
1501 } else {
1502 SetNil(a);
1503 SetFalse(a);
1505 return errNone;
1507 /// copied from SC_World.cpp:
1509 int sampleFormatFromString(const char* name);
1510 int sampleFormatFromString(const char* name)
1512 if (!name) return SF_FORMAT_PCM_16;
1514 size_t len = strlen(name);
1515 if (len < 1) return 0;
1517 if (name[0] == 'u') {
1518 if (len < 5) return 0;
1519 if (name[4] == '8') return SF_FORMAT_PCM_U8; // uint8
1520 return 0;
1521 } else if (name[0] == 'i') {
1522 if (len < 4) return 0;
1523 if (name[3] == '8') return SF_FORMAT_PCM_S8; // int8
1524 else if (name[3] == '1') return SF_FORMAT_PCM_16; // int16
1525 else if (name[3] == '2') return SF_FORMAT_PCM_24; // int24
1526 else if (name[3] == '3') return SF_FORMAT_PCM_32; // int32
1527 } else if (name[0] == 'f') {
1528 return SF_FORMAT_FLOAT; // float
1529 } else if (name[0] == 'd') {
1530 return SF_FORMAT_DOUBLE; // double
1531 } else if (name[0] == 'm' || name[0] == 'u') {
1532 return SF_FORMAT_ULAW; // mulaw ulaw
1533 } else if (name[0] == 'a') {
1534 return SF_FORMAT_ALAW; // alaw
1536 return 0;
1539 int headerFormatFromString(const char *name);
1540 int headerFormatFromString(const char *name)
1542 if (!name) return SF_FORMAT_AIFF;
1543 if (strcasecmp(name, "AIFF")==0) return SF_FORMAT_AIFF;
1544 if (strcasecmp(name, "AIFC")==0) return SF_FORMAT_AIFF;
1545 if (strcasecmp(name, "RIFF")==0) return SF_FORMAT_WAV;
1546 if (strcasecmp(name, "WAVEX")==0) return SF_FORMAT_WAVEX;
1547 if (strcasecmp(name, "WAVE")==0) return SF_FORMAT_WAV;
1548 if (strcasecmp(name, "WAV" )==0) return SF_FORMAT_WAV;
1549 if (strcasecmp(name, "Sun" )==0) return SF_FORMAT_AU;
1550 if (strcasecmp(name, "IRCAM")==0) return SF_FORMAT_IRCAM;
1551 if (strcasecmp(name, "NeXT")==0) return SF_FORMAT_AU;
1552 if (strcasecmp(name, "raw")==0) return SF_FORMAT_RAW;
1553 if (strcasecmp(name, "MAT4")==0) return SF_FORMAT_MAT4;
1554 if (strcasecmp(name, "MAT5")==0) return SF_FORMAT_MAT5;
1555 if (strcasecmp(name, "PAF")==0) return SF_FORMAT_PAF;
1556 if (strcasecmp(name, "SVX")==0) return SF_FORMAT_SVX;
1557 if (strcasecmp(name, "NIST")==0) return SF_FORMAT_NIST;
1558 if (strcasecmp(name, "VOC")==0) return SF_FORMAT_VOC;
1559 if (strcasecmp(name, "W64")==0) return SF_FORMAT_W64;
1560 if (strcasecmp(name, "PVF")==0) return SF_FORMAT_PVF;
1561 if (strcasecmp(name, "XI")==0) return SF_FORMAT_XI;
1562 if (strcasecmp(name, "HTK")==0) return SF_FORMAT_HTK;
1563 if (strcasecmp(name, "SDS")==0) return SF_FORMAT_SDS;
1564 if (strcasecmp(name, "AVR")==0) return SF_FORMAT_AVR;
1565 if (strcasecmp(name, "SD2")==0) return SF_FORMAT_SD2;
1566 if (strcasecmp(name, "FLAC")==0) return SF_FORMAT_FLAC;
1567 if (strcasecmp(name, "CAF")==0) return SF_FORMAT_CAF;
1568 // TODO allow other platforms to know vorbis once libsndfile 1.0.18 is established
1569 #if SC_DARWIN || SC_WIN32
1570 if (strcasecmp(name, "VORBIS")==0) return SF_FORMAT_VORBIS;
1571 #endif
1572 if (strcasecmp(name, "RF64")==0) return SF_FORMAT_RF64;
1573 return 0;
1577 int sndfileFormatInfoFromStrings(struct SF_INFO *info, const char *headerFormatString, const char *sampleFormatString)
1579 int headerFormat = headerFormatFromString(headerFormatString);
1580 if (!headerFormat) return errWrongType;
1582 int sampleFormat = sampleFormatFromString(sampleFormatString);
1583 if (!sampleFormat) return errWrongType;
1585 info->format = (unsigned int)(headerFormat | sampleFormat);
1586 return errNone;
1588 // end copy
1590 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed);
1591 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1593 PyrSlot *a, *b;
1594 char filename[PATH_MAX];
1595 SNDFILE *file;
1596 SF_INFO info;
1597 PyrSlot *headerSlot;
1598 PyrSlot *formatSlot;
1599 int error;
1602 a = g->sp - 1;
1603 b = g->sp;
1605 headerSlot = (slotRawObject(a)->slots + 1);
1606 formatSlot = (slotRawObject(a)->slots + 2);
1609 if (!isKindOfSlot(headerSlot, class_string)) return errWrongType;
1610 if (!isKindOfSlot(formatSlot, class_string)) return errWrongType;
1612 if (!isKindOfSlot(b, class_string)) return errWrongType;
1613 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1615 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1616 filename[slotRawString(b)->size] = 0;
1618 #ifdef SC_WIN32
1619 char* headerFormat = (char *)malloc(slotRawObject(headerSlot)->size);
1620 #else
1621 char headerFormat[slotRawString(headerSlot)->size];
1622 #endif
1623 memcpy(headerFormat, slotRawString(headerSlot)->s, slotRawObject(headerSlot)->size);
1624 headerFormat[slotRawString(headerSlot)->size] = 0;
1626 #ifdef SC_WIN32
1627 char* sampleFormat = (char *)malloc(slotRawString(formatSlot)->size);
1628 #else
1629 char sampleFormat[slotRawString(formatSlot)->size];
1630 #endif
1631 memcpy(sampleFormat, slotRawString(formatSlot)->s, slotRawObject(formatSlot)->size);
1632 sampleFormat[slotRawString(formatSlot)->size] = 0;
1634 error = sndfileFormatInfoFromStrings(&info, headerFormat, sampleFormat);
1635 if(error) {
1636 #ifdef SC_WIN32
1637 free(sampleFormat);
1638 free(headerFormat);
1639 #endif
1640 return errFailed;
1643 if(error) return errFailed;
1644 //slotIntVal(slotRawObject(a)->slots + 3, &info.frames);
1645 slotIntVal(slotRawObject(a)->slots + 4, &info.channels);
1646 slotIntVal(slotRawObject(a)->slots + 5, &info.samplerate);
1648 file = sf_open(filename, SFM_WRITE, &info);
1649 if (file) {
1650 SetPtr(slotRawObject(a)->slots+0, file);
1651 SetTrue(a);
1652 } else {
1653 SetNil(a);
1654 SetFalse(a);
1657 return errNone;
1660 int prSFClose(struct VMGlobals *g, int numArgsPushed);
1661 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1663 PyrSlot *a;
1665 a = g->sp;
1667 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1668 if (file) {
1669 sf_close(file);
1670 SetNil(slotRawObject(a)->slots + 0);
1673 return errNone;
1676 int prSFRead(struct VMGlobals *g, int numArgsPushed);
1677 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1679 PyrSlot *a, *b;
1681 a = g->sp - 1;
1682 b = g->sp;
1684 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1686 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1688 switch (slotRawObject(b)->obj_format) {
1689 case obj_int16 :
1690 slotRawObject(b)->size = sf_read_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1691 break;
1692 case obj_int32 :
1693 slotRawObject(b)->size = sf_read_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1694 break;
1695 case obj_float :
1696 slotRawObject(b)->size = sf_read_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1697 break;
1698 case obj_double :
1699 slotRawObject(b)->size = sf_read_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1700 break;
1701 default:
1702 error("sample format not supported.\n");
1703 return errFailed;
1706 return errNone;
1709 int prSFWrite(struct VMGlobals *g, int numArgsPushed);
1710 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1712 PyrSlot *a, *b;
1714 a = g->sp - 1;
1715 b = g->sp;
1717 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1719 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1721 switch (slotRawObject(b)->obj_format) {
1722 case obj_int16 :
1723 sf_write_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1724 break;
1725 case obj_int32 :
1726 sf_write_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1727 break;
1728 case obj_float :
1729 sf_write_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1730 break;
1731 case obj_double :
1732 sf_write_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1733 break;
1734 default:
1735 error("sample format not supported.\n");
1736 return errFailed;
1739 return errNone;
1742 int prSFSeek(struct VMGlobals *g, int numArgsPushed);
1743 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1745 PyrSlot *a, *b, *c;
1747 a = g->sp - 2;
1748 b = g->sp - 1;
1749 c = g->sp;
1751 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1753 int origin, offset;
1754 int err = slotIntVal(b, &offset);
1755 if (err) return err;
1757 err = slotIntVal(c, &origin);
1758 if (err) return err;
1760 sf_seek(file, offset, origin);
1762 return errNone;
1765 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed);
1766 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1769 PyrSlot *a;
1770 a = g->sp;
1771 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1772 if(file){
1773 static char strbuffer [(1 << 16)] ;
1774 sf_command (file, SFC_GET_LOG_INFO, strbuffer, (1 << 16)) ;
1775 PyrString *pstring = newPyrString(g->gc, strbuffer, 0, true);
1776 // post(strbuffer);
1777 SetObject(a, pstring);
1778 return errNone;
1780 return errFailed;
1783 #else // !NO_LIBSNDFILE
1785 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1787 return errFailed;
1790 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1792 return errFailed;
1795 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1797 return errFailed;
1800 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1802 return errFailed;
1805 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1807 return errFailed;
1810 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1812 return errFailed;
1815 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1817 return errFailed;
1820 #endif // !NO_LIBSNDFILE
1823 //////////
1824 #ifdef NOCLASSIC
1826 int dir_Lookup(char *pathString, int pathStringLength, int index,
1827 /* outputs: */
1828 char *name, int *nameLength, int *creationDate, int *modificationDate,
1829 int *isDirectory, int *isVisible, int *sizeIfFile);
1831 int prDirectory_At(struct VMGlobals *g, int numArgsPushed);
1832 int prDirectory_At(struct VMGlobals *g, int numArgsPushed)
1834 PyrSlot *a = g->sp - 2;
1835 PyrSlot *b = g->sp - 1;
1836 PyrSlot *c = g->sp;
1838 PyrSlot *dirPathSlot = slotRawObject(a)->slots + 0;
1839 int err, index;
1840 err = slotIntVal(c, &index);
1841 if (err) {
1842 SetNil(a);
1843 return err;
1846 char name[256], fullPathName[256];
1847 int nameLength, creationDate, modificationDate, isDirectory, isVisible, sizeIfFile;
1848 int dirPathLength = slotRawObject(dirPathSlot)->size;
1850 err = dir_Lookup(slotRawObject(dirPathSlot)s->s, dirPathLength, index+1,
1851 name, &nameLength, &creationDate, &modificationDate, &isDirectory, &isVisible, &sizeIfFile);
1852 if (err == 1) {
1853 SetNil(a);
1854 return errNone;
1856 if (err) {
1857 error("Invalid path\n");
1858 SetNil(a);
1859 return errFailed;
1862 if (dirPathLength + nameLength + 1 > 255) {
1863 error("Full path name too long.\n");
1864 SetNil(a);
1865 return errFailed;
1868 PyrSlot *entryName = slotRawObject(b)->slots + 0;
1869 PyrSlot *entryPath = slotRawObject(b)->slots + 1;
1870 PyrSlot *entryIsDir = slotRawObject(b)->slots + 2;
1871 PyrSlot *entryIsVisible = slotRawObject(b)->slots + 3;
1873 PyrString *nameString = newPyrString(g->gc, name, 0, true);
1874 SetObject(entryName, nameString);
1875 g->gc->GCWrite(slotRawObject(b), (PyrObject*)nameString);
1877 memcpy(fullPathName, slotRawObject(dirPathSlot)s->s, dirPathLength);
1878 fullPathName[dirPathLength] = DELIMITOR;
1879 strcpy(fullPathName + dirPathLength + 1, name);
1881 PyrString *pathString = newPyrString(g->gc, fullPathName, 0, true);
1882 SetObject(entryPath, pathString);
1883 g->gc->GCWrite(slotRawObject(b), (PyrObject*)pathString);
1885 if (isDirectory) { SetTrue(entryIsDir); } else { SetFalse(entryIsDir); }
1886 if (isVisible) { SetTrue(entryIsVisible); } else { SetFalse(entryIsVisible); }
1888 slotCopy(a,b);
1890 return errNone;
1893 Boolean GetFullPathname(const FSSpec* aSpec, Str255 pathname);
1894 void pstrncpy(unsigned char *s1, unsigned char *s2, int n);
1896 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed);
1897 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed)
1900 PyrSlot *a = g->sp - 1;
1901 PyrSlot *b = g->sp;
1903 NavDialogOptions options;
1905 int err = NavGetDefaultDialogOptions(&options);
1906 if (err) return errFailed;
1908 options.dialogOptionFlags |= kNavNoTypePopup;
1909 options.dialogOptionFlags |= kNavDontAutoTranslate;
1910 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1911 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1912 options.dialogOptionFlags &= ~kNavAllowPreviews;
1913 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1915 if (isKindOfSlot(b, class_string)) {
1916 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1919 NavReplyRecord reply;
1920 err = NavGetFile(0, &reply, &options, 0, 0, 0, 0, 0);
1922 if (err == noErr && reply.validRecord) {
1923 AEKeyword keyword;
1924 DescType actualType;
1925 Size actualSize;
1926 FSSpec fsspec;
1928 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1929 &fsspec, sizeof(FSSpec), &actualSize);
1931 if (err == noErr) {
1932 Str255 pathname;
1933 GetFullPathname(&fsspec, pathname);
1934 p2cstr(pathname);
1935 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1936 SetObject(a, string);
1937 } else {
1938 SetNil(a);
1940 err = NavDisposeReply(&reply);
1941 } else {
1942 SetNil(a);
1944 return errNone;
1949 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed);
1950 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed)
1953 PyrSlot *a = g->sp - 2;
1954 PyrSlot *b = g->sp - 1;
1955 PyrSlot *c = g->sp;
1957 NavDialogOptions options;
1959 int err = NavGetDefaultDialogOptions(&options);
1960 if (err) return errFailed;
1962 options.dialogOptionFlags |= kNavNoTypePopup;
1963 options.dialogOptionFlags |= kNavDontAutoTranslate;
1964 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1965 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1966 options.dialogOptionFlags &= ~kNavAllowPreviews;
1967 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1969 if (isKindOfSlot(b, class_string)) {
1970 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1973 if (isKindOfSlot(c, class_string)) {
1974 pstringFromPyrString((PyrString*)slotRawObject(c), options.savedFileName, 256);
1975 } else {
1976 //pstrncpy(options.savedFileName, "\pUntitled", 255);
1979 NavReplyRecord reply;
1980 err = NavPutFile(0, &reply, &options, 0, 'TEXT', 'SCjm', 0);
1982 if (err == noErr && reply.validRecord) {
1983 AEKeyword keyword;
1984 DescType actualType;
1985 Size actualSize;
1986 FSSpec fsspec;
1988 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1989 &fsspec, sizeof(FSSpec), &actualSize);
1991 if (err == noErr) {
1992 Str255 pathname;
1993 GetFullPathname(&fsspec, pathname);
1994 p2cstr(pathname);
1995 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1996 SetObject(a, string);
1998 err = NavCompleteSave(&reply, kNavTranslateInPlace);
1999 } else {
2000 SetNil(a);
2002 err = NavDisposeReply(&reply);
2003 } else {
2004 SetNil(a);
2006 return errNone;
2009 #endif
2011 /////////////
2013 void initFilePrimitives()
2015 int base, index;
2017 base = nextPrimitiveIndex();
2018 index = 0;
2020 definePrimitive(base, index++, "_SFOpenRead", prSFOpenRead, 2, 0);
2021 definePrimitive(base, index++, "_SFOpenWrite", prSFOpenWrite, 2, 0);
2022 definePrimitive(base, index++, "_SFClose", prSFClose, 1, 0);
2023 definePrimitive(base, index++, "_SFWrite", prSFWrite, 2, 0);
2024 definePrimitive(base, index++, "_SFRead", prSFRead, 2, 0);
2025 definePrimitive(base, index++, "_SFSeek", prSFSeek, 3, 0);
2026 definePrimitive(base, index++, "_SFHeaderInfoString", prSFHeaderInfoString, 1, 0);
2028 #ifndef SC_WIN32
2029 definePrimitive(base, index++, "_PipeOpen", prPipeOpen, 3, 0);
2030 definePrimitive(base, index++, "_PipeClose", prPipeClose, 1, 0);
2031 #endif
2033 definePrimitive(base, index++, "_FileDelete", prFileDelete, 2, 0);
2034 definePrimitive(base, index++, "_FileMTime", prFileMTime, 2, 0);
2035 definePrimitive(base, index++, "_FileExists", prFileExists, 2, 0);
2036 definePrimitive(base, index++, "_FileRealPath", prFileRealPath, 2, 0);
2037 definePrimitive(base, index++, "_FileMkDir", prFileMkDir, 2, 0);
2038 definePrimitive(base, index++, "_FileCopy", prFileCopy, 3, 0);
2039 definePrimitive(base, index++, "_FileType", prFileType, 2, 0);
2040 definePrimitive(base, index++, "_FileSize", prFileSize, 2, 0);
2042 definePrimitive(base, index++, "_FileOpen", prFileOpen, 3, 0);
2043 definePrimitive(base, index++, "_FileClose", prFileClose, 1, 0);
2044 definePrimitive(base, index++, "_FileFlush", prFileFlush, 1, 0);
2045 definePrimitive(base, index++, "_FileSeek", prFileSeek, 3, 0);
2046 definePrimitive(base, index++, "_FilePos", prFilePos, 1, 0);
2047 definePrimitive(base, index++, "_FileLength", prFileLength, 1, 0);
2048 definePrimitive(base, index++, "_FileWrite", prFileWrite, 2, 0);
2049 definePrimitive(base, index++, "_FileWriteLE", prFileWriteLE, 2, 0);
2050 definePrimitive(base, index++, "_FileReadLine", prFileReadLine, 2, 0);
2051 definePrimitive(base, index++, "_File_getcwd", prFileGetcwd, 2, 0);
2053 definePrimitive(base, index++, "_FilePutChar", prFilePutChar, 2, 0);
2054 definePrimitive(base, index++, "_FilePutInt8", prFilePutInt8, 2, 0);
2055 definePrimitive(base, index++, "_FilePutInt16", prFilePutInt16, 2, 0);
2056 definePrimitive(base, index++, "_FilePutInt32", prFilePutInt32, 2, 0);
2057 definePrimitive(base, index++, "_FilePutFloat", prFilePutFloat, 2, 0);
2058 definePrimitive(base, index++, "_FilePutDouble", prFilePutDouble, 2, 0);
2059 definePrimitive(base, index++, "_FilePutInt16LE", prFilePutInt16LE, 2, 0);
2060 definePrimitive(base, index++, "_FilePutInt32LE", prFilePutInt32LE, 2, 0);
2061 definePrimitive(base, index++, "_FilePutFloatLE", prFilePutFloatLE, 2, 0);
2062 definePrimitive(base, index++, "_FilePutDoubleLE", prFilePutDoubleLE, 2, 0);
2064 definePrimitive(base, index++, "_FileGetChar", prFileGetChar, 1, 0);
2065 definePrimitive(base, index++, "_FileGetInt8", prFileGetInt8, 1, 0);
2066 definePrimitive(base, index++, "_FileGetInt16", prFileGetInt16, 1, 0);
2067 definePrimitive(base, index++, "_FileGetInt32", prFileGetInt32, 1, 0);
2068 definePrimitive(base, index++, "_FileGetFloat", prFileGetFloat, 1, 0);
2069 definePrimitive(base, index++, "_FileGetDouble", prFileGetDouble, 1, 0);
2070 definePrimitive(base, index++, "_FileGetInt16LE", prFileGetInt16LE, 1, 0);
2071 definePrimitive(base, index++, "_FileGetInt32LE", prFileGetInt32LE, 1, 0);
2072 definePrimitive(base, index++, "_FileGetFloatLE", prFileGetFloatLE, 1, 0);
2073 definePrimitive(base, index++, "_FileGetDoubleLE", prFileGetDoubleLE, 1, 0);
2075 definePrimitive(base, index++, "_FilePutString", prFilePutString, 2, 0);
2077 definePrimitive(base, index++, "_FileReadRaw", prFileReadRaw, 2, 0);
2078 definePrimitive(base, index++, "_FileReadRawLE", prFileReadRawLE, 2, 0);
2080 #ifdef NOCLASSIC
2081 definePrimitive(base, index++, "_Directory_At", prDirectory_At, 3, 0);
2082 definePrimitive(base, index++, "_File_GetFile", prFile_GetFile, 2, 0);
2083 definePrimitive(base, index++, "_File_PutFile", prFile_PutFile, 3, 0);
2084 #endif