cmake: supernova - missing include_directories() for Jack
[supercollider.git] / lang / LangPrimSource / PyrFilePrim.cpp
bloba211efc111ab4da0258e021f736a2120135f8577
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 = slotRawChar(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 int8 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(int8), 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 return 0;
1576 int sndfileFormatInfoFromStrings(struct SF_INFO *info, const char *headerFormatString, const char *sampleFormatString)
1578 int headerFormat = headerFormatFromString(headerFormatString);
1579 if (!headerFormat) return errWrongType;
1581 int sampleFormat = sampleFormatFromString(sampleFormatString);
1582 if (!sampleFormat) return errWrongType;
1584 info->format = (unsigned int)(headerFormat | sampleFormat);
1585 return errNone;
1587 // end copy
1589 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed);
1590 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1592 PyrSlot *a, *b;
1593 char filename[PATH_MAX];
1594 SNDFILE *file;
1595 SF_INFO info;
1596 PyrSlot *headerSlot;
1597 PyrSlot *formatSlot;
1598 int error;
1601 a = g->sp - 1;
1602 b = g->sp;
1604 headerSlot = (slotRawObject(a)->slots + 1);
1605 formatSlot = (slotRawObject(a)->slots + 2);
1608 if (!isKindOfSlot(headerSlot, class_string)) return errWrongType;
1609 if (!isKindOfSlot(formatSlot, class_string)) return errWrongType;
1611 if (!isKindOfSlot(b, class_string)) return errWrongType;
1612 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1614 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1615 filename[slotRawString(b)->size] = 0;
1617 #ifdef SC_WIN32
1618 char* headerFormat = (char *)malloc(slotRawObject(headerSlot)->size);
1619 #else
1620 char headerFormat[slotRawString(headerSlot)->size];
1621 #endif
1622 memcpy(headerFormat, slotRawString(headerSlot)->s, slotRawObject(headerSlot)->size);
1623 headerFormat[slotRawString(headerSlot)->size] = 0;
1625 #ifdef SC_WIN32
1626 char* sampleFormat = (char *)malloc(slotRawString(formatSlot)->size);
1627 #else
1628 char sampleFormat[slotRawString(formatSlot)->size];
1629 #endif
1630 memcpy(sampleFormat, slotRawString(formatSlot)->s, slotRawObject(formatSlot)->size);
1631 sampleFormat[slotRawString(formatSlot)->size] = 0;
1633 error = sndfileFormatInfoFromStrings(&info, headerFormat, sampleFormat);
1634 if(error) {
1635 #ifdef SC_WIN32
1636 free(sampleFormat);
1637 free(headerFormat);
1638 #endif
1639 return errFailed;
1642 if(error) return errFailed;
1643 //slotIntVal(slotRawObject(a)->slots + 3, &info.frames);
1644 slotIntVal(slotRawObject(a)->slots + 4, &info.channels);
1645 slotIntVal(slotRawObject(a)->slots + 5, &info.samplerate);
1647 file = sf_open(filename, SFM_WRITE, &info);
1648 if (file) {
1649 SetPtr(slotRawObject(a)->slots+0, file);
1650 SetTrue(a);
1651 } else {
1652 SetNil(a);
1653 SetFalse(a);
1656 return errNone;
1659 int prSFClose(struct VMGlobals *g, int numArgsPushed);
1660 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1662 PyrSlot *a;
1664 a = g->sp;
1666 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1667 if (file) {
1668 sf_close(file);
1669 SetNil(slotRawObject(a)->slots + 0);
1672 return errNone;
1675 int prSFRead(struct VMGlobals *g, int numArgsPushed);
1676 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1678 PyrSlot *a, *b;
1680 a = g->sp - 1;
1681 b = g->sp;
1683 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1685 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1687 switch (slotRawObject(b)->obj_format) {
1688 case obj_int16 :
1689 slotRawObject(b)->size = sf_read_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1690 break;
1691 case obj_int32 :
1692 slotRawObject(b)->size = sf_read_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1693 break;
1694 case obj_float :
1695 slotRawObject(b)->size = sf_read_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1696 break;
1697 case obj_double :
1698 slotRawObject(b)->size = sf_read_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1699 break;
1700 default:
1701 error("sample format not supported.\n");
1702 return errFailed;
1705 return errNone;
1708 int prSFWrite(struct VMGlobals *g, int numArgsPushed);
1709 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1711 PyrSlot *a, *b;
1713 a = g->sp - 1;
1714 b = g->sp;
1716 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1718 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1720 switch (slotRawObject(b)->obj_format) {
1721 case obj_int16 :
1722 sf_write_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1723 break;
1724 case obj_int32 :
1725 sf_write_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1726 break;
1727 case obj_float :
1728 sf_write_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1729 break;
1730 case obj_double :
1731 sf_write_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1732 break;
1733 default:
1734 error("sample format not supported.\n");
1735 return errFailed;
1738 return errNone;
1741 int prSFSeek(struct VMGlobals *g, int numArgsPushed);
1742 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1744 PyrSlot *a, *b, *c;
1746 a = g->sp - 2;
1747 b = g->sp - 1;
1748 c = g->sp;
1750 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1752 int origin, offset;
1753 int err = slotIntVal(b, &offset);
1754 if (err) return err;
1756 err = slotIntVal(c, &origin);
1757 if (err) return err;
1759 sf_seek(file, offset, origin);
1761 return errNone;
1764 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed);
1765 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1768 PyrSlot *a;
1769 a = g->sp;
1770 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1771 if(file){
1772 static char strbuffer [(1 << 16)] ;
1773 sf_command (file, SFC_GET_LOG_INFO, strbuffer, (1 << 16)) ;
1774 PyrString *pstring = newPyrString(g->gc, strbuffer, 0, true);
1775 // post(strbuffer);
1776 SetObject(a, pstring);
1777 return errNone;
1779 return errFailed;
1782 #else // !NO_LIBSNDFILE
1784 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1786 return errFailed;
1789 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1791 return errFailed;
1794 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1796 return errFailed;
1799 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1801 return errFailed;
1804 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1806 return errFailed;
1809 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1811 return errFailed;
1814 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1816 return errFailed;
1819 #endif // !NO_LIBSNDFILE
1822 //////////
1823 #ifdef NOCLASSIC
1825 int dir_Lookup(char *pathString, int pathStringLength, int index,
1826 /* outputs: */
1827 char *name, int *nameLength, int *creationDate, int *modificationDate,
1828 int *isDirectory, int *isVisible, int *sizeIfFile);
1830 int prDirectory_At(struct VMGlobals *g, int numArgsPushed);
1831 int prDirectory_At(struct VMGlobals *g, int numArgsPushed)
1833 PyrSlot *a = g->sp - 2;
1834 PyrSlot *b = g->sp - 1;
1835 PyrSlot *c = g->sp;
1837 PyrSlot *dirPathSlot = slotRawObject(a)->slots + 0;
1838 int err, index;
1839 err = slotIntVal(c, &index);
1840 if (err) {
1841 SetNil(a);
1842 return err;
1845 char name[256], fullPathName[256];
1846 int nameLength, creationDate, modificationDate, isDirectory, isVisible, sizeIfFile;
1847 int dirPathLength = slotRawObject(dirPathSlot)->size;
1849 err = dir_Lookup(slotRawObject(dirPathSlot)s->s, dirPathLength, index+1,
1850 name, &nameLength, &creationDate, &modificationDate, &isDirectory, &isVisible, &sizeIfFile);
1851 if (err == 1) {
1852 SetNil(a);
1853 return errNone;
1855 if (err) {
1856 error("Invalid path\n");
1857 SetNil(a);
1858 return errFailed;
1861 if (dirPathLength + nameLength + 1 > 255) {
1862 error("Full path name too long.\n");
1863 SetNil(a);
1864 return errFailed;
1867 PyrSlot *entryName = slotRawObject(b)->slots + 0;
1868 PyrSlot *entryPath = slotRawObject(b)->slots + 1;
1869 PyrSlot *entryIsDir = slotRawObject(b)->slots + 2;
1870 PyrSlot *entryIsVisible = slotRawObject(b)->slots + 3;
1872 PyrString *nameString = newPyrString(g->gc, name, 0, true);
1873 SetObject(entryName, nameString);
1874 g->gc->GCWrite(slotRawObject(b), (PyrObject*)nameString);
1876 memcpy(fullPathName, slotRawObject(dirPathSlot)s->s, dirPathLength);
1877 fullPathName[dirPathLength] = DELIMITOR;
1878 strcpy(fullPathName + dirPathLength + 1, name);
1880 PyrString *pathString = newPyrString(g->gc, fullPathName, 0, true);
1881 SetObject(entryPath, pathString);
1882 g->gc->GCWrite(slotRawObject(b), (PyrObject*)pathString);
1884 if (isDirectory) { SetTrue(entryIsDir); } else { SetFalse(entryIsDir); }
1885 if (isVisible) { SetTrue(entryIsVisible); } else { SetFalse(entryIsVisible); }
1887 slotCopy(a,b);
1889 return errNone;
1892 Boolean GetFullPathname(const FSSpec* aSpec, Str255 pathname);
1893 void pstrncpy(unsigned char *s1, unsigned char *s2, int n);
1895 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed);
1896 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed)
1899 PyrSlot *a = g->sp - 1;
1900 PyrSlot *b = g->sp;
1902 NavDialogOptions options;
1904 int err = NavGetDefaultDialogOptions(&options);
1905 if (err) return errFailed;
1907 options.dialogOptionFlags |= kNavNoTypePopup;
1908 options.dialogOptionFlags |= kNavDontAutoTranslate;
1909 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1910 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1911 options.dialogOptionFlags &= ~kNavAllowPreviews;
1912 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1914 if (isKindOfSlot(b, class_string)) {
1915 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1918 NavReplyRecord reply;
1919 err = NavGetFile(0, &reply, &options, 0, 0, 0, 0, 0);
1921 if (err == noErr && reply.validRecord) {
1922 AEKeyword keyword;
1923 DescType actualType;
1924 Size actualSize;
1925 FSSpec fsspec;
1927 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1928 &fsspec, sizeof(FSSpec), &actualSize);
1930 if (err == noErr) {
1931 Str255 pathname;
1932 GetFullPathname(&fsspec, pathname);
1933 p2cstr(pathname);
1934 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1935 SetObject(a, string);
1936 } else {
1937 SetNil(a);
1939 err = NavDisposeReply(&reply);
1940 } else {
1941 SetNil(a);
1943 return errNone;
1948 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed);
1949 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed)
1952 PyrSlot *a = g->sp - 2;
1953 PyrSlot *b = g->sp - 1;
1954 PyrSlot *c = g->sp;
1956 NavDialogOptions options;
1958 int err = NavGetDefaultDialogOptions(&options);
1959 if (err) return errFailed;
1961 options.dialogOptionFlags |= kNavNoTypePopup;
1962 options.dialogOptionFlags |= kNavDontAutoTranslate;
1963 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1964 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1965 options.dialogOptionFlags &= ~kNavAllowPreviews;
1966 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1968 if (isKindOfSlot(b, class_string)) {
1969 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1972 if (isKindOfSlot(c, class_string)) {
1973 pstringFromPyrString((PyrString*)slotRawObject(c), options.savedFileName, 256);
1974 } else {
1975 //pstrncpy(options.savedFileName, "\pUntitled", 255);
1978 NavReplyRecord reply;
1979 err = NavPutFile(0, &reply, &options, 0, 'TEXT', 'SCjm', 0);
1981 if (err == noErr && reply.validRecord) {
1982 AEKeyword keyword;
1983 DescType actualType;
1984 Size actualSize;
1985 FSSpec fsspec;
1987 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1988 &fsspec, sizeof(FSSpec), &actualSize);
1990 if (err == noErr) {
1991 Str255 pathname;
1992 GetFullPathname(&fsspec, pathname);
1993 p2cstr(pathname);
1994 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1995 SetObject(a, string);
1997 err = NavCompleteSave(&reply, kNavTranslateInPlace);
1998 } else {
1999 SetNil(a);
2001 err = NavDisposeReply(&reply);
2002 } else {
2003 SetNil(a);
2005 return errNone;
2008 #endif
2010 /////////////
2012 void initFilePrimitives()
2014 int base, index;
2016 base = nextPrimitiveIndex();
2017 index = 0;
2019 definePrimitive(base, index++, "_SFOpenRead", prSFOpenRead, 2, 0);
2020 definePrimitive(base, index++, "_SFOpenWrite", prSFOpenWrite, 2, 0);
2021 definePrimitive(base, index++, "_SFClose", prSFClose, 1, 0);
2022 definePrimitive(base, index++, "_SFWrite", prSFWrite, 2, 0);
2023 definePrimitive(base, index++, "_SFRead", prSFRead, 2, 0);
2024 definePrimitive(base, index++, "_SFSeek", prSFSeek, 3, 0);
2025 definePrimitive(base, index++, "_SFHeaderInfoString", prSFHeaderInfoString, 1, 0);
2027 #ifndef SC_WIN32
2028 definePrimitive(base, index++, "_PipeOpen", prPipeOpen, 3, 0);
2029 definePrimitive(base, index++, "_PipeClose", prPipeClose, 1, 0);
2030 #endif
2032 definePrimitive(base, index++, "_FileDelete", prFileDelete, 2, 0);
2033 definePrimitive(base, index++, "_FileMTime", prFileMTime, 2, 0);
2034 definePrimitive(base, index++, "_FileExists", prFileExists, 2, 0);
2035 definePrimitive(base, index++, "_FileRealPath", prFileRealPath, 2, 0);
2036 definePrimitive(base, index++, "_FileMkDir", prFileMkDir, 2, 0);
2037 definePrimitive(base, index++, "_FileCopy", prFileCopy, 3, 0);
2038 definePrimitive(base, index++, "_FileType", prFileType, 2, 0);
2039 definePrimitive(base, index++, "_FileSize", prFileSize, 2, 0);
2041 definePrimitive(base, index++, "_FileOpen", prFileOpen, 3, 0);
2042 definePrimitive(base, index++, "_FileClose", prFileClose, 1, 0);
2043 definePrimitive(base, index++, "_FileFlush", prFileFlush, 1, 0);
2044 definePrimitive(base, index++, "_FileSeek", prFileSeek, 3, 0);
2045 definePrimitive(base, index++, "_FilePos", prFilePos, 1, 0);
2046 definePrimitive(base, index++, "_FileLength", prFileLength, 1, 0);
2047 definePrimitive(base, index++, "_FileWrite", prFileWrite, 2, 0);
2048 definePrimitive(base, index++, "_FileWriteLE", prFileWriteLE, 2, 0);
2049 definePrimitive(base, index++, "_FileReadLine", prFileReadLine, 2, 0);
2050 definePrimitive(base, index++, "_File_getcwd", prFileGetcwd, 2, 0);
2052 definePrimitive(base, index++, "_FilePutChar", prFilePutChar, 2, 0);
2053 definePrimitive(base, index++, "_FilePutInt8", prFilePutInt8, 2, 0);
2054 definePrimitive(base, index++, "_FilePutInt16", prFilePutInt16, 2, 0);
2055 definePrimitive(base, index++, "_FilePutInt32", prFilePutInt32, 2, 0);
2056 definePrimitive(base, index++, "_FilePutFloat", prFilePutFloat, 2, 0);
2057 definePrimitive(base, index++, "_FilePutDouble", prFilePutDouble, 2, 0);
2058 definePrimitive(base, index++, "_FilePutInt16LE", prFilePutInt16LE, 2, 0);
2059 definePrimitive(base, index++, "_FilePutInt32LE", prFilePutInt32LE, 2, 0);
2060 definePrimitive(base, index++, "_FilePutFloatLE", prFilePutFloatLE, 2, 0);
2061 definePrimitive(base, index++, "_FilePutDoubleLE", prFilePutDoubleLE, 2, 0);
2063 definePrimitive(base, index++, "_FileGetChar", prFileGetChar, 1, 0);
2064 definePrimitive(base, index++, "_FileGetInt8", prFileGetInt8, 1, 0);
2065 definePrimitive(base, index++, "_FileGetInt16", prFileGetInt16, 1, 0);
2066 definePrimitive(base, index++, "_FileGetInt32", prFileGetInt32, 1, 0);
2067 definePrimitive(base, index++, "_FileGetFloat", prFileGetFloat, 1, 0);
2068 definePrimitive(base, index++, "_FileGetDouble", prFileGetDouble, 1, 0);
2069 definePrimitive(base, index++, "_FileGetInt16LE", prFileGetInt16LE, 1, 0);
2070 definePrimitive(base, index++, "_FileGetInt32LE", prFileGetInt32LE, 1, 0);
2071 definePrimitive(base, index++, "_FileGetFloatLE", prFileGetFloatLE, 1, 0);
2072 definePrimitive(base, index++, "_FileGetDoubleLE", prFileGetDoubleLE, 1, 0);
2074 definePrimitive(base, index++, "_FilePutString", prFilePutString, 2, 0);
2076 definePrimitive(base, index++, "_FileReadRaw", prFileReadRaw, 2, 0);
2077 definePrimitive(base, index++, "_FileReadRawLE", prFileReadRawLE, 2, 0);
2079 #ifdef NOCLASSIC
2080 definePrimitive(base, index++, "_Directory_At", prDirectory_At, 3, 0);
2081 definePrimitive(base, index++, "_File_GetFile", prFile_GetFile, 2, 0);
2082 definePrimitive(base, index++, "_File_PutFile", prFile_PutFile, 3, 0);
2083 #endif