Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / lang / LangPrimSource / PyrFilePrim.cpp
blob719ae642e01a2d51fded1f03057319f9dea0699e
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 "ReadWriteMacros.h"
33 #include "SCBase.h"
34 #include "SC_DirUtils.h"
35 #include "sc_popen.h"
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <cerrno>
42 #include "../../common/SC_SndFileHelpers.hpp"
44 #ifdef NOCLASSIC
45 #include <TextUtils.h>
46 #include <Navigation.h>
47 #endif
49 #ifndef _WIN32
50 # include <unistd.h>
51 #else
52 # include <direct.h>
53 # include <malloc.h>
54 #endif
56 #ifdef _WIN32
57 #include <stdio.h>
58 #include "SC_Win32Utils.h"
59 #include "SC_DirUtils.h"
60 #endif
62 #include <fcntl.h>
63 #include <math.h>
65 #include <boost/filesystem.hpp>
67 #if defined(__APPLE__) || defined(SC_IPHONE)
68 #ifndef _SC_StandAloneInfo_
69 # include "SC_StandAloneInfo_Darwin.h"
70 #endif
71 # include <CoreFoundation/CFString.h>
72 # include <CoreFoundation/CFBundle.h>
73 #ifndef SC_IPHONE
74 # include <CoreServices/CoreServices.h>
75 #endif
76 #endif
78 #define DELIMITOR ':'
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 *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 *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::filesystem::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 __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 = g->sp;
349 PyrFile *pfile = (PyrFile*)slotRawObject(a);
350 FILE *file = (FILE*)slotRawPtr(&pfile->fileptr);
352 if (file == NULL) return errFailed;
354 // preserve file position
355 fpos_t pos;
356 if (fgetpos(file, &pos)) return errFailed;
357 if (fseek(file, 0, SEEK_END)) return errFailed;
358 size_t length;
359 length = ftell(file);
360 if (fsetpos(file, &pos)) return errFailed;
362 SetInt(a, length);
363 return errNone;
366 int prFileSeek(struct VMGlobals *g, int numArgsPushed)
368 PyrSlot *a, *b, *c;
369 PyrFile *pfile;
370 FILE *file;
371 size_t offset;
372 int origin;
373 static int originTable[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
375 a = g->sp - 2;
376 b = g->sp - 1;
377 c = g->sp;
378 if (NotInt(b)) return errWrongType;
379 if (NotInt(c)) return errWrongType;
380 pfile = (PyrFile*)slotRawObject(a);
381 file = (FILE*)slotRawPtr(&pfile->fileptr);
382 if (file == NULL) return errFailed;
383 offset = slotRawInt(b);
384 origin = slotRawInt(c);
385 if (origin < 0 || origin > 2) return errIndexOutOfRange;
386 origin = originTable[origin]; // translate in case ANSI constants ever change..
387 if (fseek(file, offset, origin)) return errFailed;
388 return errNone;
392 int prFileWrite(struct VMGlobals *g, int numArgsPushed)
394 PyrSlot *a, *b, *ptr;
395 PyrFile *pfile;
396 FILE *file;
397 PyrObject *obj;
398 char chr;
400 a = g->sp - 1;
401 b = g->sp;
402 pfile = (PyrFile*)slotRawObject(a);
403 file = (FILE*)slotRawPtr(&pfile->fileptr);
404 if (file == NULL) return errFailed;
405 switch (GetTag(b)) {
406 case tagInt :
408 SC_IOStream<FILE*> scio(file);
409 scio.writeInt32_be(slotRawInt(b));
410 break;
412 case tagSym :
413 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
414 break;
415 case tagChar :
416 chr = slotRawChar(b);
417 fwrite(&chr, sizeof(char), 1, file);
418 break;
419 case tagNil :
420 case tagFalse :
421 case tagTrue :
422 case tagPtr :
423 return errWrongType;
424 case tagObj :
426 // writes the indexable part of any non obj_slot format object
427 obj = slotRawObject(b);
428 if (!isKindOf(obj, class_rawarray)
429 || isKindOf(obj, class_symbolarray)) return errWrongType;
430 if (obj->size) {
431 ptr = obj->slots;
432 int elemSize = gFormatElemSize[obj->obj_format];
433 int numElems = obj->size;
434 #if BYTE_ORDER != BIG_ENDIAN
435 switch (elemSize) {
436 case 1:
437 fwrite(ptr, elemSize, numElems, file);
438 break;
439 case 2:
441 char *ptr = slotRawString(b)->s;
442 char *ptrend = ptr + numElems*2;
443 for (; ptr < ptrend; ptr+=2) {
444 fputc(ptr[1], file);
445 fputc(ptr[0], file);
447 break;
449 case 4:
451 char *ptr = slotRawString(b)->s;
452 char *ptrend = ptr + numElems*4;
453 for (; ptr < ptrend; ptr+=4) {
454 fputc(ptr[3], file);
455 fputc(ptr[2], file);
456 fputc(ptr[1], file);
457 fputc(ptr[0], file);
459 break;
461 case 8:
463 char *ptr = slotRawString(b)->s;
464 char *ptrend = ptr + numElems*8;
465 for (; ptr < ptrend; ptr+=8) {
466 fputc(ptr[7], file);
467 fputc(ptr[6], file);
468 fputc(ptr[5], file);
469 fputc(ptr[4], file);
470 fputc(ptr[3], file);
471 fputc(ptr[2], file);
472 fputc(ptr[1], file);
473 fputc(ptr[0], file);
475 break;
478 #else
479 fwrite(ptr, elemSize, numElems, file);
480 #endif
482 break;
484 default : // double
486 SC_IOStream<FILE*> scio(file);
487 scio.writeDouble_be(slotRawFloat(b));
488 break;
491 return errNone;
495 int prFileWriteLE(struct VMGlobals *g, int numArgsPushed)
497 PyrSlot *a, *b, *ptr;
498 PyrFile *pfile;
499 FILE *file;
500 PyrObject *obj;
501 char chr;
503 a = g->sp - 1;
504 b = g->sp;
505 pfile = (PyrFile*)slotRawObject(a);
506 file = (FILE*)slotRawPtr(&pfile->fileptr);
507 if (file == NULL) return errFailed;
508 switch (GetTag(b)) {
509 case tagInt :
511 SC_IOStream<FILE*> scio(file);
512 scio.writeInt32_le(slotRawInt(b));
513 break;
515 case tagSym :
516 fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file);
517 break;
518 case tagChar :
519 chr = slotRawInt(b);
520 fwrite(&chr, sizeof(char), 1, file);
521 break;
522 case tagNil :
523 case tagFalse :
524 case tagTrue :
525 case tagPtr :
526 return errWrongType;
527 case tagObj :
529 // writes the indexable part of any non obj_slot format object
530 obj = slotRawObject(b);
531 if (!isKindOf(obj, class_rawarray)
532 || isKindOf(obj, class_symbolarray)) return errWrongType;
533 if (obj->size) {
534 ptr = obj->slots;
535 int elemSize = gFormatElemSize[obj->obj_format];
536 int numElems = obj->size;
537 #if BYTE_ORDER == BIG_ENDIAN
538 switch (elemSize) {
539 case 1:
540 fwrite(ptr, elemSize, numElems, file);
541 break;
542 case 2:
544 char *ptr = slotRawString(b)->s;
545 char *ptrend = ptr + numElems*2;
546 for (; ptr < ptrend; ptr+=2) {
547 fputc(ptr[1], file);
548 fputc(ptr[0], file);
550 break;
552 case 4:
554 char *ptr = slotRawString(b)->s;
555 char *ptrend = ptr + numElems*4;
556 for (; ptr < ptrend; ptr+=4) {
557 fputc(ptr[3], file);
558 fputc(ptr[2], file);
559 fputc(ptr[1], file);
560 fputc(ptr[0], file);
562 break;
564 case 8:
566 char *ptr = slotRawString(b)->s;
567 char *ptrend = ptr + numElems*8;
568 for (; ptr < ptrend; ptr+=8) {
569 fputc(ptr[7], file);
570 fputc(ptr[6], file);
571 fputc(ptr[5], file);
572 fputc(ptr[4], file);
573 fputc(ptr[3], file);
574 fputc(ptr[2], file);
575 fputc(ptr[1], file);
576 fputc(ptr[0], file);
578 break;
581 #else
582 fwrite(ptr, elemSize, numElems, file);
583 #endif
585 break;
587 default : // double
589 SC_IOStream<FILE*> scio(file);
590 scio.writeDouble_le(slotRawFloat(b));
591 break;
594 return errNone;
597 int prFileReadLine(struct VMGlobals *g, int numArgsPushed)
599 PyrSlot *a, *b; // receiver(a File), string
600 PyrFile *pfile;
601 FILE *file;
603 a = g->sp - 1;
604 b = g->sp;
606 pfile = (PyrFile*)slotRawObject(a);
607 file = (FILE*)slotRawPtr(&pfile->fileptr);
608 if (file == NULL) return errFailed;
610 char* result = fgets(slotRawString(b)->s, MAXINDEXSIZE(slotRawObject(b)) - 1, file);
611 if (!result) {
612 SetNil(a);
613 } else {
614 slotRawString(b)->size = strlen(slotRawString(b)->s);
615 if (slotRawString(b)->s[slotRawString(b)->size-1] == '\n') slotRawString(b)->size--;
616 slotCopy(a,b);
618 return errNone;
621 int prFilePutInt32(struct VMGlobals *g, int numArgsPushed)
623 PyrSlot *a, *b;
624 PyrFile *pfile;
625 FILE *file;
627 a = g->sp - 1;
628 b = g->sp;
630 pfile = (PyrFile*)slotRawObject(a);
631 file = (FILE*)slotRawPtr(&pfile->fileptr);
632 if (file == NULL) return errFailed;
634 int val;
635 int err = slotIntVal(b, &val);
636 if (err) return err;
638 SC_IOStream<FILE*> scio(file);
639 scio.writeInt32_be(val);
641 return errNone;
644 int prFilePutInt16(struct VMGlobals *g, int numArgsPushed)
646 PyrSlot *a, *b;
647 PyrFile *pfile;
648 FILE *file;
650 a = g->sp - 1;
651 b = g->sp;
653 pfile = (PyrFile*)slotRawObject(a);
654 file = (FILE*)slotRawPtr(&pfile->fileptr);
655 if (file == NULL) return errFailed;
657 int val;
658 int err = slotIntVal(b, &val);
659 if (err) return err;
662 SC_IOStream<FILE*> scio(file);
663 scio.writeInt16_be(val);
665 return errNone;
669 int prFilePutInt32LE(struct VMGlobals *g, int numArgsPushed)
671 PyrSlot *a, *b;
672 PyrFile *pfile;
673 FILE *file;
675 a = g->sp - 1;
676 b = g->sp;
678 pfile = (PyrFile*)slotRawObject(a);
679 file = (FILE*)slotRawPtr(&pfile->fileptr);
680 if (file == NULL) return errFailed;
682 int val;
683 int err = slotIntVal(b, &val);
684 if (err) return err;
686 SC_IOStream<FILE*> scio(file);
687 scio.writeInt32_le(val);
689 return errNone;
692 int prFilePutInt16LE(struct VMGlobals *g, int numArgsPushed)
694 PyrSlot *a, *b;
695 PyrFile *pfile;
696 FILE *file;
698 a = g->sp - 1;
699 b = g->sp;
701 pfile = (PyrFile*)slotRawObject(a);
702 file = (FILE*)slotRawPtr(&pfile->fileptr);
703 if (file == NULL) return errFailed;
705 int val;
706 int err = slotIntVal(b, &val);
707 if (err) return err;
710 SC_IOStream<FILE*> scio(file);
711 scio.writeInt16_le(val);
713 return errNone;
716 int prFilePutInt8(struct VMGlobals *g, int numArgsPushed)
718 PyrSlot *a, *b;
719 PyrFile *pfile;
720 FILE *file;
722 a = g->sp - 1;
723 b = g->sp;
725 pfile = (PyrFile*)slotRawObject(a);
726 file = (FILE*)slotRawPtr(&pfile->fileptr);
727 if (file == NULL) return errFailed;
729 int val;
730 int err = slotIntVal(b, &val);
731 if (err) return err;
734 SC_IOStream<FILE*> scio(file);
735 scio.writeInt8(val);
737 return errNone;
740 int prFilePutChar(struct VMGlobals *g, int numArgsPushed)
742 PyrSlot *a, *b;
743 PyrFile *pfile;
744 FILE *file;
745 char z;
747 a = g->sp - 1;
748 b = g->sp;
750 pfile = (PyrFile*)slotRawObject(a);
751 file = (FILE*)slotRawPtr(&pfile->fileptr);
752 if (file == NULL) return errFailed;
753 if (NotChar(b)) return errWrongType;
755 z = slotRawChar(b);
757 SC_IOStream<FILE*> scio(file);
758 scio.writeInt8(z);
760 return errNone;
763 int prFilePutFloat(struct VMGlobals *g, int numArgsPushed)
765 PyrSlot *a, *b;
766 PyrFile *pfile;
767 FILE *file;
769 a = g->sp - 1;
770 b = g->sp;
772 pfile = (PyrFile*)slotRawObject(a);
773 file = (FILE*)slotRawPtr(&pfile->fileptr);
774 if (file == NULL) {
775 dumpObjectSlot(a);
776 return errFailed;
779 float val;
780 int err = slotFloatVal(b, &val);
781 if (err) return err;
783 SC_IOStream<FILE*> scio(file);
784 scio.writeFloat_be(val);
786 return errNone;
789 int prFilePutDouble(struct VMGlobals *g, int numArgsPushed)
791 PyrSlot *a, *b;
792 PyrFile *pfile;
793 FILE *file;
795 a = g->sp - 1;
796 b = g->sp;
798 pfile = (PyrFile*)slotRawObject(a);
799 file = (FILE*)slotRawPtr(&pfile->fileptr);
800 if (file == NULL) return errFailed;
803 double val;
804 int err = slotDoubleVal(b, &val);
805 if (err) return err;
807 SC_IOStream<FILE*> scio(file);
808 scio.writeDouble_be(val);
810 return errNone;
814 int prFilePutFloatLE(struct VMGlobals *g, int numArgsPushed)
816 PyrSlot *a, *b;
817 PyrFile *pfile;
818 FILE *file;
820 a = g->sp - 1;
821 b = g->sp;
823 pfile = (PyrFile*)slotRawObject(a);
824 file = (FILE*)slotRawPtr(&pfile->fileptr);
825 if (file == NULL) {
826 dumpObjectSlot(a);
827 return errFailed;
830 float val;
831 int err = slotFloatVal(b, &val);
832 if (err) return err;
834 SC_IOStream<FILE*> scio(file);
835 scio.writeFloat_le(val);
837 return errNone;
840 int prFilePutDoubleLE(struct VMGlobals *g, int numArgsPushed)
842 PyrSlot *a, *b;
843 PyrFile *pfile;
844 FILE *file;
846 a = g->sp - 1;
847 b = g->sp;
849 pfile = (PyrFile*)slotRawObject(a);
850 file = (FILE*)slotRawPtr(&pfile->fileptr);
851 if (file == NULL) return errFailed;
854 double val;
855 int err = slotDoubleVal(b, &val);
856 if (err) return err;
858 SC_IOStream<FILE*> scio(file);
859 scio.writeDouble_le(val);
861 return errNone;
864 int prFilePutString(struct VMGlobals *g, int numArgsPushed)
866 PyrSlot *a, *b;
867 PyrFile *pfile;
868 FILE *file;
869 PyrString *string;
871 a = g->sp - 1;
872 b = g->sp;
873 pfile = (PyrFile*)slotRawObject(a);
874 file = (FILE*)slotRawPtr(&pfile->fileptr);
875 if (file == NULL) return errFailed;
876 if (NotObj(b) || slotRawObject(b)->classptr != class_string) return errWrongType;
877 string = slotRawString(b);
878 if (string->size) {
879 fwrite(string->s, 1, string->size, file);
881 return errNone;
885 int prFileGetDouble(struct VMGlobals *g, int numArgsPushed)
887 PyrSlot *a;
888 PyrFile *pfile;
889 FILE *file;
891 a = g->sp;
893 pfile = (PyrFile*)slotRawObject(a);
894 file = (FILE*)slotRawPtr(&pfile->fileptr);
895 if (file == NULL) return errFailed;
897 if (feof(file)) SetNil(a);
898 else {
899 SC_IOStream<FILE*> scio(file);
900 SetFloat(a, scio.readDouble_be());
902 return errNone;
905 int prFileGetFloat(struct VMGlobals *g, int numArgsPushed)
907 PyrSlot *a;
908 PyrFile *pfile;
909 FILE *file;
911 a = g->sp;
913 pfile = (PyrFile*)slotRawObject(a);
914 file = (FILE*)slotRawPtr(&pfile->fileptr);
915 if (file == NULL) return errFailed;
917 if (feof(file)) SetNil(a);
918 else {
919 SC_IOStream<FILE*> scio(file);
920 SetFloat(a, scio.readFloat_be());
922 return errNone;
926 int prFileGetDoubleLE(struct VMGlobals *g, int numArgsPushed)
928 PyrSlot *a;
929 PyrFile *pfile;
930 FILE *file;
932 a = g->sp;
934 pfile = (PyrFile*)slotRawObject(a);
935 file = (FILE*)slotRawPtr(&pfile->fileptr);
936 if (file == NULL) return errFailed;
938 if (feof(file)) SetNil(a);
939 else {
940 SC_IOStream<FILE*> scio(file);
941 SetFloat(a, scio.readDouble_le());
943 return errNone;
946 int prFileGetFloatLE(struct VMGlobals *g, int numArgsPushed)
948 PyrSlot *a;
949 PyrFile *pfile;
950 FILE *file;
952 a = g->sp;
954 pfile = (PyrFile*)slotRawObject(a);
955 file = (FILE*)slotRawPtr(&pfile->fileptr);
956 if (file == NULL) return errFailed;
958 if (feof(file)) SetNil(a);
959 else {
960 SC_IOStream<FILE*> scio(file);
961 SetFloat(a, scio.readFloat_le());
963 return errNone;
966 int prFileGetChar(struct VMGlobals *g, int numArgsPushed)
968 PyrSlot *a;
969 PyrFile *pfile;
970 FILE *file;
971 char z;
973 a = g->sp;
975 pfile = (PyrFile*)slotRawObject(a);
976 file = (FILE*)slotRawPtr(&pfile->fileptr);
977 if (file == NULL) return errFailed;
979 int count = fread(&z, sizeof(char), 1, file);
980 if (count==0) SetNil(a);
981 else SetChar(a, z);
982 return errNone;
985 int prFileGetInt8(struct VMGlobals *g, int numArgsPushed)
987 PyrSlot *a;
988 PyrFile *pfile;
989 FILE *file;
990 int8 z;
992 a = g->sp;
994 pfile = (PyrFile*)slotRawObject(a);
995 file = (FILE*)slotRawPtr(&pfile->fileptr);
996 if (file == NULL) return errFailed;
998 int count = fread(&z, sizeof(int8), 1, file);
999 if (count==0) SetNil(a);
1000 else SetInt(a, z);
1001 return errNone;
1004 int prFileGetInt16(struct VMGlobals *g, int numArgsPushed)
1006 PyrSlot *a;
1007 PyrFile *pfile;
1008 FILE *file;
1010 a = g->sp;
1012 pfile = (PyrFile*)slotRawObject(a);
1013 file = (FILE*)slotRawPtr(&pfile->fileptr);
1014 if (file == NULL) return errFailed;
1016 if (feof(file)) SetNil(a);
1017 else {
1018 SC_IOStream<FILE*> scio(file);
1019 SetInt(a, scio.readInt16_be());
1021 return errNone;
1024 int prFileGetInt32(struct VMGlobals *g, int numArgsPushed)
1026 PyrSlot *a;
1027 PyrFile *pfile;
1028 FILE *file;
1030 a = g->sp;
1032 pfile = (PyrFile*)slotRawObject(a);
1033 file = (FILE*)slotRawPtr(&pfile->fileptr);
1034 if (file == NULL)
1035 return errFailed;
1037 if (feof(file)) SetNil(a);
1038 else {
1039 SC_IOStream<FILE*> scio(file);
1040 SetInt(a, scio.readInt32_be());
1042 return errNone;
1046 int prFileGetInt16LE(struct VMGlobals *g, int numArgsPushed)
1048 PyrSlot *a;
1049 PyrFile *pfile;
1050 FILE *file;
1052 a = g->sp;
1054 pfile = (PyrFile*)slotRawObject(a);
1055 file = (FILE*)slotRawPtr(&pfile->fileptr);
1056 if (file == NULL) return errFailed;
1058 if (feof(file)) SetNil(a);
1059 else {
1060 SC_IOStream<FILE*> scio(file);
1061 SetInt(a, scio.readInt16_le());
1063 return errNone;
1066 int prFileGetInt32LE(struct VMGlobals *g, int numArgsPushed)
1068 PyrSlot *a;
1069 PyrFile *pfile;
1070 FILE *file;
1072 a = g->sp;
1074 pfile = (PyrFile*)slotRawObject(a);
1075 file = (FILE*)slotRawPtr(&pfile->fileptr);
1076 if (file == NULL) return errFailed;
1078 if (feof(file)) SetNil(a);
1079 else {
1080 SC_IOStream<FILE*> scio(file);
1081 SetInt(a, scio.readInt32_le());
1083 return errNone;
1086 int prFileReadRaw(struct VMGlobals *g, int numArgsPushed)
1088 PyrFile *pfile;
1089 FILE *file;
1091 PyrSlot* a = g->sp - 1;
1092 PyrSlot* b = g->sp;
1094 if (!isKindOfSlot(b, class_rawarray)
1095 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1097 pfile = (PyrFile*)slotRawObject(a);
1098 file = (FILE*)slotRawPtr(&pfile->fileptr);
1099 if (file == NULL) return errFailed;
1101 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1102 int numElems = slotRawObject(b)->size;
1103 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1104 slotRawObject(b)->size = numElems;
1106 #if BYTE_ORDER != BIG_ENDIAN
1107 switch (elemSize) {
1108 case 1:
1109 break;
1110 case 2:
1112 char *ptr = slotRawString(b)->s;
1113 char *ptrend = ptr + numElems*2;
1114 for (; ptr < ptrend; ptr+=2) {
1115 char temp = ptr[0];
1116 ptr[0] = ptr[1];
1117 ptr[1] = temp;
1119 break;
1121 case 4:
1123 char *ptr = slotRawString(b)->s;
1124 char *ptrend = ptr + numElems*4;
1125 for (; ptr < ptrend; ptr+=4) {
1126 char temp = ptr[0];
1127 ptr[0] = ptr[3];
1128 ptr[3] = temp;
1130 temp = ptr[1];
1131 ptr[1] = ptr[2];
1132 ptr[2] = temp;
1134 break;
1136 case 8:
1138 char *ptr = slotRawString(b)->s;
1139 char *ptrend = ptr + numElems*8;
1140 for (; ptr < ptrend; ptr+=8) {
1141 char temp = ptr[0];
1142 ptr[0] = ptr[7];
1143 ptr[7] = temp;
1145 temp = ptr[1];
1146 ptr[1] = ptr[6];
1147 ptr[6] = temp;
1149 temp = ptr[2];
1150 ptr[2] = ptr[5];
1151 ptr[5] = temp;
1153 temp = ptr[3];
1154 ptr[3] = ptr[4];
1155 ptr[4] = temp;
1157 break;
1160 #endif
1162 if (slotRawObject(b)->size==0) SetNil(a);
1163 else slotCopy(a,b);
1164 return errNone;
1167 int prFileReadRawLE(struct VMGlobals *g, int numArgsPushed)
1169 PyrFile *pfile;
1170 FILE *file;
1172 PyrSlot* a = g->sp - 1;
1173 PyrSlot* b = g->sp;
1175 if (!isKindOfSlot(b, class_rawarray)
1176 || isKindOfSlot(b, class_symbolarray)) return errWrongType;
1178 pfile = (PyrFile*)slotRawObject(a);
1179 file = (FILE*)slotRawPtr(&pfile->fileptr);
1180 if (file == NULL) return errFailed;
1182 int elemSize = gFormatElemSize[slotRawObject(b)->obj_format];
1183 int numElems = slotRawObject(b)->size;
1184 numElems = fread(slotRawString(b)->s, elemSize, numElems, file);
1185 slotRawObject(b)->size = numElems;
1187 #if BYTE_ORDER == BIG_ENDIAN
1188 switch (elemSize) {
1189 case 1:
1190 break;
1191 case 2:
1193 char *ptr = slotRawString(b)->s;
1194 char *ptrend = ptr + numElems*2;
1195 for (; ptr < ptrend; ptr+=2) {
1196 char temp = ptr[0];
1197 ptr[0] = ptr[1];
1198 ptr[1] = temp;
1200 break;
1202 case 4:
1204 char *ptr = slotRawString(b)->s;
1205 char *ptrend = ptr + numElems*4;
1206 for (; ptr < ptrend; ptr+=4) {
1207 char temp = ptr[0];
1208 ptr[0] = ptr[3];
1209 ptr[3] = temp;
1211 temp = ptr[1];
1212 ptr[1] = ptr[2];
1213 ptr[2] = temp;
1215 break;
1217 case 8:
1219 char *ptr = slotRawString(b)->s;
1220 char *ptrend = ptr + numElems*8;
1221 for (; ptr < ptrend; ptr+=8) {
1222 char temp = ptr[0];
1223 ptr[0] = ptr[7];
1224 ptr[7] = temp;
1226 temp = ptr[1];
1227 ptr[1] = ptr[6];
1228 ptr[6] = temp;
1230 temp = ptr[2];
1231 ptr[2] = ptr[5];
1232 ptr[5] = temp;
1234 temp = ptr[3];
1235 ptr[3] = ptr[4];
1236 ptr[4] = temp;
1238 break;
1241 #endif
1243 if (slotRawObject(b)->size==0) SetNil(a);
1244 else slotCopy(a,b);
1245 return errNone;
1248 int prFileGetcwd(struct VMGlobals *g, int numArgsPushed)
1250 //PyrSlot* a = g->sp - 1; // File
1251 PyrSlot* string = g->sp;
1253 if (!isKindOfSlot(string, class_string)) return errWrongType;
1255 char * cwd = getcwd(slotRawString(string)->s,255);
1256 if (cwd == NULL) {
1257 error(strerror(errno));
1258 return errFailed;
1260 slotRawString(string)->size = strlen(slotRawString(string)->s);
1262 return errNone;
1265 ////////
1267 int prPipeOpen(struct VMGlobals *g, int numArgsPushed)
1269 PyrSlot *a, *b, *c;
1270 char mode[12];
1271 PyrFile *pfile;
1272 FILE *file;
1274 a = g->sp - 2;
1275 b = g->sp - 1;
1276 c = g->sp;
1278 if (NotObj(c) || !isKindOf(slotRawObject(c), class_string)
1279 || NotObj(b) || !isKindOf(slotRawObject(b), class_string))
1280 return errWrongType;
1281 if (slotRawObject(c)->size > 11) return errFailed;
1282 pfile = (PyrFile*)slotRawObject(a);
1284 char *commandLine = (char*)malloc(slotRawObject(b)->size + 1);
1285 memcpy(commandLine, slotRawString(b)->s, slotRawObject(b)->size);
1286 commandLine[slotRawString(b)->size] = 0;
1288 memcpy(mode, slotRawString(c)->s, slotRawObject(c)->size);
1289 mode[slotRawString(c)->size] = 0;
1291 pid_t pid;
1292 file = sc_popen(commandLine, &pid, mode);
1293 free(commandLine);
1294 if (file) {
1295 SetPtr(&pfile->fileptr, file);
1296 SetInt(a, pid);
1297 } else {
1298 SetNil(a);
1300 return errNone;
1303 int prPipeClose(struct VMGlobals *g, int numArgsPushed)
1305 PyrSlot *a;
1306 PyrSlot *b;
1307 PyrFile *pfile;
1308 FILE *file;
1309 pid_t pid;
1311 a = g->sp - 1;
1312 b = g->sp;
1313 pfile = (PyrFile*)slotRawObject(a);
1314 file = (FILE*)slotRawPtr(&pfile->fileptr);
1315 if (file == NULL) return errNone;
1316 pid = (pid_t) slotRawInt(b);
1318 SetPtr(&pfile->fileptr, NULL);
1319 int perr = sc_pclose(file, pid);
1320 SetInt(a, perr);
1321 if (perr == -1)
1322 return errFailed;
1323 return errNone;
1326 ////////
1328 #ifndef NO_LIBSNDFILE
1330 #ifdef SC_WIN32
1331 #include <sndfile-win.h>
1332 #else
1333 #include <sndfile.h>
1334 #endif
1337 int sampleFormatToString(struct SF_INFO *info, const char **string);
1338 int sampleFormatToString(struct SF_INFO *info, const char **string)
1340 unsigned int format = info->format & SF_FORMAT_SUBMASK;
1341 switch (format)
1343 case SF_FORMAT_DPCM_8:
1344 case SF_FORMAT_PCM_S8:
1345 *string = "int16";
1346 break;
1347 case SF_FORMAT_DPCM_16:
1348 case SF_FORMAT_PCM_16:
1349 case SF_FORMAT_DWVW_16:
1350 *string = "int16";
1351 break;
1352 case SF_FORMAT_PCM_24:
1353 case SF_FORMAT_DWVW_24:
1354 *string = "int24";
1355 break;
1356 case SF_FORMAT_PCM_32:
1357 *string = "int32";
1358 break;
1359 case SF_FORMAT_FLOAT:
1360 *string = "float";
1361 break;
1362 case SF_FORMAT_DOUBLE:
1363 *string = "double";
1364 break;
1365 case SF_FORMAT_ULAW:
1366 *string = "ulaw";
1367 break;
1368 case SF_FORMAT_ALAW:
1369 *string = "alaw";
1370 break;
1371 default:
1372 *string = "float";
1373 break;
1375 return errNone;
1379 int headerFormatToString(struct SF_INFO *info, const char **string);
1380 int headerFormatToString(struct SF_INFO *info, const char **string){
1381 switch (info->format & SF_FORMAT_TYPEMASK)
1383 case SF_FORMAT_WAV :
1384 *string = "WAV";
1385 break;
1386 case SF_FORMAT_AIFF :
1387 *string = "AIFF";
1388 break ;
1389 case SF_FORMAT_AU :
1390 *string = "SUN";
1391 break ;
1392 case SF_FORMAT_IRCAM :
1393 *string = "IRCAM";
1394 break ;
1395 case SF_FORMAT_RAW :
1396 *string = "raw";
1397 break ;
1398 case SF_FORMAT_W64 :
1399 *string = "WAV";
1400 break ;
1401 case SF_FORMAT_FLAC :
1402 *string = "FLAC";
1403 break ;
1404 // TODO allow other platforms to know vorbis once libsndfile 1.0.18 is established
1405 #if SC_DARWIN || SC_WIN32 || LIBSNDFILE_1018
1406 case SF_FORMAT_VORBIS :
1407 *string = "vorbis";
1408 break ;
1409 #endif
1411 case SF_FORMAT_PAF :
1413 break ;
1415 case SF_FORMAT_SVX :
1417 break ;
1419 case SF_FORMAT_NIST :
1421 break ;
1423 case SF_FORMAT_VOC :
1425 break ;
1427 case SF_FORMAT_MAT4 :
1429 break ;
1431 case SF_FORMAT_MAT5 :
1433 break ;
1435 case SF_FORMAT_PVF :
1437 break ;
1439 case SF_FORMAT_XI :
1441 break ;
1443 case SF_FORMAT_HTK :
1445 break ;
1447 case SF_FORMAT_SDS :
1449 break ;
1451 default :
1452 *string = " ";
1453 break ;
1455 return errNone;
1458 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample);
1459 int sndfileFormatInfoToStrings(struct SF_INFO *info, const char **stringHead, const char **stringSample)
1461 int error = 0;
1462 error = headerFormatToString(info, stringHead);
1463 error = sampleFormatToString(info, stringSample);
1464 return error;
1467 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed);
1468 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1470 PyrSlot *a, *b;
1471 char filename[PATH_MAX];
1472 SNDFILE *file;
1473 SF_INFO info;
1474 const char *headerstr;
1475 const char *sampleformatstr;
1477 a = g->sp - 1;
1478 b = g->sp;
1480 if (!isKindOfSlot(b, class_string)) return errWrongType;
1481 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1483 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1484 filename[slotRawString(b)->size] = 0;
1486 info.format = 0;
1487 file = sf_open(filename, SFM_READ, &info);
1490 if (file) {
1491 SetPtr(slotRawObject(a)->slots + 0, file);
1492 sndfileFormatInfoToStrings(&info, &headerstr, &sampleformatstr);
1493 //headerFormatToString(&info, &headerstr);
1494 PyrString *hpstr = newPyrString(g->gc, headerstr, 0, true);
1495 SetObject(slotRawObject(a)->slots+1, hpstr);
1496 PyrString *smpstr = newPyrString(g->gc, sampleformatstr, 0, true);
1497 SetObject(slotRawObject(a)->slots+2, smpstr);
1498 SetInt(slotRawObject(a)->slots + 3, info.frames);
1499 SetInt(slotRawObject(a)->slots + 4, info.channels);
1500 SetInt(slotRawObject(a)->slots + 5, info.samplerate);
1502 SetTrue(a);
1503 } else {
1504 SetNil(a);
1505 SetFalse(a);
1507 return errNone;
1510 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed);
1511 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1513 PyrSlot *a, *b;
1514 char filename[PATH_MAX];
1515 SNDFILE *file;
1516 SF_INFO info;
1517 PyrSlot *headerSlot;
1518 PyrSlot *formatSlot;
1519 int error;
1522 a = g->sp - 1;
1523 b = g->sp;
1525 headerSlot = (slotRawObject(a)->slots + 1);
1526 formatSlot = (slotRawObject(a)->slots + 2);
1529 if (!isKindOfSlot(headerSlot, class_string)) return errWrongType;
1530 if (!isKindOfSlot(formatSlot, class_string)) return errWrongType;
1532 if (!isKindOfSlot(b, class_string)) return errWrongType;
1533 if (slotRawObject(b)->size > PATH_MAX - 1) return errFailed;
1535 memcpy(filename, slotRawString(b)->s, slotRawObject(b)->size);
1536 filename[slotRawString(b)->size] = 0;
1538 #ifdef SC_WIN32
1539 char* headerFormat = (char *)malloc(slotRawObject(headerSlot)->size);
1540 #else
1541 char headerFormat[slotRawString(headerSlot)->size];
1542 #endif
1543 memcpy(headerFormat, slotRawString(headerSlot)->s, slotRawObject(headerSlot)->size);
1544 headerFormat[slotRawString(headerSlot)->size] = 0;
1546 #ifdef SC_WIN32
1547 char* sampleFormat = (char *)malloc(slotRawString(formatSlot)->size);
1548 #else
1549 char sampleFormat[slotRawString(formatSlot)->size];
1550 #endif
1551 memcpy(sampleFormat, slotRawString(formatSlot)->s, slotRawObject(formatSlot)->size);
1552 sampleFormat[slotRawString(formatSlot)->size] = 0;
1554 error = sndfileFormatInfoFromStrings(&info, headerFormat, sampleFormat);
1555 if(error) {
1556 #ifdef SC_WIN32
1557 free(sampleFormat);
1558 free(headerFormat);
1559 #endif
1560 return errFailed;
1563 if(error) return errFailed;
1564 //slotIntVal(slotRawObject(a)->slots + 3, &info.frames);
1565 slotIntVal(slotRawObject(a)->slots + 4, &info.channels);
1566 slotIntVal(slotRawObject(a)->slots + 5, &info.samplerate);
1568 file = sf_open(filename, SFM_WRITE, &info);
1569 sf_command(file, SFC_SET_CLIPPING, NULL, SF_TRUE);
1571 if (file) {
1572 SetPtr(slotRawObject(a)->slots+0, file);
1573 SetTrue(a);
1574 } else {
1575 SetNil(a);
1576 SetFalse(a);
1579 return errNone;
1582 int prSFClose(struct VMGlobals *g, int numArgsPushed);
1583 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1585 PyrSlot *a;
1587 a = g->sp;
1589 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1590 if (file) {
1591 sf_close(file);
1592 SetNil(slotRawObject(a)->slots + 0);
1595 return errNone;
1598 int prSFRead(struct VMGlobals *g, int numArgsPushed);
1599 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1601 PyrSlot *a, *b;
1603 a = g->sp - 1;
1604 b = g->sp;
1606 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1608 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1610 switch (slotRawObject(b)->obj_format) {
1611 case obj_int16 :
1612 slotRawObject(b)->size = sf_read_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1613 break;
1614 case obj_int32 :
1615 slotRawObject(b)->size = sf_read_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1616 break;
1617 case obj_float :
1618 slotRawObject(b)->size = sf_read_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1619 break;
1620 case obj_double :
1621 slotRawObject(b)->size = sf_read_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1622 break;
1623 default:
1624 error("sample format not supported.\n");
1625 return errFailed;
1628 return errNone;
1631 int prSFWrite(struct VMGlobals *g, int numArgsPushed);
1632 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1634 PyrSlot *a, *b;
1636 a = g->sp - 1;
1637 b = g->sp;
1639 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1641 if (!isKindOfSlot(b, class_rawarray)) return errWrongType;
1643 switch (slotRawObject(b)->obj_format) {
1644 case obj_int16 :
1645 sf_write_short(file, (short*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1646 break;
1647 case obj_int32 :
1648 sf_write_int(file, (int*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1649 break;
1650 case obj_float :
1651 sf_write_float(file, (float*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1652 break;
1653 case obj_double :
1654 sf_write_double(file, (double*)slotRawInt8Array(b)->b, slotRawObject(b)->size);
1655 break;
1656 default:
1657 error("sample format not supported.\n");
1658 return errFailed;
1661 return errNone;
1664 int prSFSeek(struct VMGlobals *g, int numArgsPushed);
1665 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1667 PyrSlot *a, *b, *c;
1669 a = g->sp - 2;
1670 b = g->sp - 1;
1671 c = g->sp;
1673 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1675 int origin, offset;
1676 int err = slotIntVal(b, &offset);
1677 if (err) return err;
1679 err = slotIntVal(c, &origin);
1680 if (err) return err;
1682 sf_seek(file, offset, origin);
1684 return errNone;
1687 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed);
1688 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1691 PyrSlot *a;
1692 a = g->sp;
1693 SNDFILE *file = (SNDFILE*)slotRawPtr(&slotRawObject(a)->slots[0]);
1694 if(file){
1695 static char strbuffer [(1 << 16)] ;
1696 sf_command (file, SFC_GET_LOG_INFO, strbuffer, (1 << 16)) ;
1697 PyrString *pstring = newPyrString(g->gc, strbuffer, 0, true);
1698 // post(strbuffer);
1699 SetObject(a, pstring);
1700 return errNone;
1702 return errFailed;
1705 #else // !NO_LIBSNDFILE
1707 int prSFOpenRead(struct VMGlobals *g, int numArgsPushed)
1709 return errFailed;
1712 int prSFOpenWrite(struct VMGlobals *g, int numArgsPushed)
1714 return errFailed;
1717 int prSFClose(struct VMGlobals *g, int numArgsPushed)
1719 return errFailed;
1722 int prSFWrite(struct VMGlobals *g, int numArgsPushed)
1724 return errFailed;
1727 int prSFRead(struct VMGlobals *g, int numArgsPushed)
1729 return errFailed;
1732 int prSFSeek(struct VMGlobals *g, int numArgsPushed)
1734 return errFailed;
1737 int prSFHeaderInfoString(struct VMGlobals *g, int numArgsPushed)
1739 return errFailed;
1742 #endif // !NO_LIBSNDFILE
1745 //////////
1746 #ifdef NOCLASSIC
1748 int dir_Lookup(char *pathString, int pathStringLength, int index,
1749 /* outputs: */
1750 char *name, int *nameLength, int *creationDate, int *modificationDate,
1751 int *isDirectory, int *isVisible, int *sizeIfFile);
1753 int prDirectory_At(struct VMGlobals *g, int numArgsPushed);
1754 int prDirectory_At(struct VMGlobals *g, int numArgsPushed)
1756 PyrSlot *a = g->sp - 2;
1757 PyrSlot *b = g->sp - 1;
1758 PyrSlot *c = g->sp;
1760 PyrSlot *dirPathSlot = slotRawObject(a)->slots + 0;
1761 int err, index;
1762 err = slotIntVal(c, &index);
1763 if (err) {
1764 SetNil(a);
1765 return err;
1768 char name[256], fullPathName[256];
1769 int nameLength, creationDate, modificationDate, isDirectory, isVisible, sizeIfFile;
1770 int dirPathLength = slotRawObject(dirPathSlot)->size;
1772 err = dir_Lookup(slotRawObject(dirPathSlot)s->s, dirPathLength, index+1,
1773 name, &nameLength, &creationDate, &modificationDate, &isDirectory, &isVisible, &sizeIfFile);
1774 if (err == 1) {
1775 SetNil(a);
1776 return errNone;
1778 if (err) {
1779 error("Invalid path\n");
1780 SetNil(a);
1781 return errFailed;
1784 if (dirPathLength + nameLength + 1 > 255) {
1785 error("Full path name too long.\n");
1786 SetNil(a);
1787 return errFailed;
1790 PyrSlot *entryName = slotRawObject(b)->slots + 0;
1791 PyrSlot *entryPath = slotRawObject(b)->slots + 1;
1792 PyrSlot *entryIsDir = slotRawObject(b)->slots + 2;
1793 PyrSlot *entryIsVisible = slotRawObject(b)->slots + 3;
1795 PyrString *nameString = newPyrString(g->gc, name, 0, true);
1796 SetObject(entryName, nameString);
1797 g->gc->GCWrite(slotRawObject(b), (PyrObject*)nameString);
1799 memcpy(fullPathName, slotRawObject(dirPathSlot)s->s, dirPathLength);
1800 fullPathName[dirPathLength] = DELIMITOR;
1801 strcpy(fullPathName + dirPathLength + 1, name);
1803 PyrString *pathString = newPyrString(g->gc, fullPathName, 0, true);
1804 SetObject(entryPath, pathString);
1805 g->gc->GCWrite(slotRawObject(b), (PyrObject*)pathString);
1807 if (isDirectory) { SetTrue(entryIsDir); } else { SetFalse(entryIsDir); }
1808 if (isVisible) { SetTrue(entryIsVisible); } else { SetFalse(entryIsVisible); }
1810 slotCopy(a,b);
1812 return errNone;
1815 Boolean GetFullPathname(const FSSpec* aSpec, Str255 pathname);
1816 void pstrncpy(unsigned char *s1, unsigned char *s2, int n);
1818 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed);
1819 int prFile_GetFile(struct VMGlobals *g, int numArgsPushed)
1822 PyrSlot *a = g->sp - 1;
1823 PyrSlot *b = g->sp;
1825 NavDialogOptions options;
1827 int err = NavGetDefaultDialogOptions(&options);
1828 if (err) return errFailed;
1830 options.dialogOptionFlags |= kNavNoTypePopup;
1831 options.dialogOptionFlags |= kNavDontAutoTranslate;
1832 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1833 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1834 options.dialogOptionFlags &= ~kNavAllowPreviews;
1835 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1837 if (isKindOfSlot(b, class_string)) {
1838 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1841 NavReplyRecord reply;
1842 err = NavGetFile(0, &reply, &options, 0, 0, 0, 0, 0);
1844 if (err == noErr && reply.validRecord) {
1845 AEKeyword keyword;
1846 DescType actualType;
1847 Size actualSize;
1848 FSSpec fsspec;
1850 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1851 &fsspec, sizeof(FSSpec), &actualSize);
1853 if (err == noErr) {
1854 Str255 pathname;
1855 GetFullPathname(&fsspec, pathname);
1856 p2cstr(pathname);
1857 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1858 SetObject(a, string);
1859 } else {
1860 SetNil(a);
1862 err = NavDisposeReply(&reply);
1863 } else {
1864 SetNil(a);
1866 return errNone;
1871 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed);
1872 int prFile_PutFile(struct VMGlobals *g, int numArgsPushed)
1875 PyrSlot *a = g->sp - 2;
1876 PyrSlot *b = g->sp - 1;
1877 PyrSlot *c = g->sp;
1879 NavDialogOptions options;
1881 int err = NavGetDefaultDialogOptions(&options);
1882 if (err) return errFailed;
1884 options.dialogOptionFlags |= kNavNoTypePopup;
1885 options.dialogOptionFlags |= kNavDontAutoTranslate;
1886 options.dialogOptionFlags |= kNavDontAddTranslateItems;
1887 options.dialogOptionFlags |= kNavSelectDefaultLocation;
1888 options.dialogOptionFlags &= ~kNavAllowPreviews;
1889 options.dialogOptionFlags &= ~kNavAllowMultipleFiles;
1891 if (isKindOfSlot(b, class_string)) {
1892 pstringFromPyrString((PyrString*)slotRawObject(b), options.message, 256);
1895 if (isKindOfSlot(c, class_string)) {
1896 pstringFromPyrString((PyrString*)slotRawObject(c), options.savedFileName, 256);
1897 } else {
1898 //pstrncpy(options.savedFileName, "\pUntitled", 255);
1901 NavReplyRecord reply;
1902 err = NavPutFile(0, &reply, &options, 0, 'TEXT', 'SCjm', 0);
1904 if (err == noErr && reply.validRecord) {
1905 AEKeyword keyword;
1906 DescType actualType;
1907 Size actualSize;
1908 FSSpec fsspec;
1910 err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType,
1911 &fsspec, sizeof(FSSpec), &actualSize);
1913 if (err == noErr) {
1914 Str255 pathname;
1915 GetFullPathname(&fsspec, pathname);
1916 p2cstr(pathname);
1917 PyrString *string = newPyrString(g->gc, (char*)pathname, 0, true);
1918 SetObject(a, string);
1920 err = NavCompleteSave(&reply, kNavTranslateInPlace);
1921 } else {
1922 SetNil(a);
1924 err = NavDisposeReply(&reply);
1925 } else {
1926 SetNil(a);
1928 return errNone;
1931 #endif
1933 /////////////
1935 void initFilePrimitives()
1937 int base, index;
1939 base = nextPrimitiveIndex();
1940 index = 0;
1942 definePrimitive(base, index++, "_SFOpenRead", prSFOpenRead, 2, 0);
1943 definePrimitive(base, index++, "_SFOpenWrite", prSFOpenWrite, 2, 0);
1944 definePrimitive(base, index++, "_SFClose", prSFClose, 1, 0);
1945 definePrimitive(base, index++, "_SFWrite", prSFWrite, 2, 0);
1946 definePrimitive(base, index++, "_SFRead", prSFRead, 2, 0);
1947 definePrimitive(base, index++, "_SFSeek", prSFSeek, 3, 0);
1948 definePrimitive(base, index++, "_SFHeaderInfoString", prSFHeaderInfoString, 1, 0);
1950 definePrimitive(base, index++, "_PipeOpen", prPipeOpen, 3, 0);
1951 definePrimitive(base, index++, "_PipeClose", prPipeClose, 2, 0);
1953 definePrimitive(base, index++, "_FileDelete", prFileDelete, 2, 0);
1954 definePrimitive(base, index++, "_FileMTime", prFileMTime, 2, 0);
1955 definePrimitive(base, index++, "_FileExists", prFileExists, 2, 0);
1956 definePrimitive(base, index++, "_FileRealPath", prFileRealPath, 2, 0);
1957 definePrimitive(base, index++, "_FileMkDir", prFileMkDir, 2, 0);
1958 definePrimitive(base, index++, "_FileCopy", prFileCopy, 3, 0);
1959 definePrimitive(base, index++, "_FileType", prFileType, 2, 0);
1960 definePrimitive(base, index++, "_FileSize", prFileSize, 2, 0);
1962 definePrimitive(base, index++, "_FileOpen", prFileOpen, 3, 0);
1963 definePrimitive(base, index++, "_FileClose", prFileClose, 1, 0);
1964 definePrimitive(base, index++, "_FileFlush", prFileFlush, 1, 0);
1965 definePrimitive(base, index++, "_FileSeek", prFileSeek, 3, 0);
1966 definePrimitive(base, index++, "_FilePos", prFilePos, 1, 0);
1967 definePrimitive(base, index++, "_FileLength", prFileLength, 1, 0);
1968 definePrimitive(base, index++, "_FileWrite", prFileWrite, 2, 0);
1969 definePrimitive(base, index++, "_FileWriteLE", prFileWriteLE, 2, 0);
1970 definePrimitive(base, index++, "_FileReadLine", prFileReadLine, 2, 0);
1971 definePrimitive(base, index++, "_File_getcwd", prFileGetcwd, 2, 0);
1973 definePrimitive(base, index++, "_FilePutChar", prFilePutChar, 2, 0);
1974 definePrimitive(base, index++, "_FilePutInt8", prFilePutInt8, 2, 0);
1975 definePrimitive(base, index++, "_FilePutInt16", prFilePutInt16, 2, 0);
1976 definePrimitive(base, index++, "_FilePutInt32", prFilePutInt32, 2, 0);
1977 definePrimitive(base, index++, "_FilePutFloat", prFilePutFloat, 2, 0);
1978 definePrimitive(base, index++, "_FilePutDouble", prFilePutDouble, 2, 0);
1979 definePrimitive(base, index++, "_FilePutInt16LE", prFilePutInt16LE, 2, 0);
1980 definePrimitive(base, index++, "_FilePutInt32LE", prFilePutInt32LE, 2, 0);
1981 definePrimitive(base, index++, "_FilePutFloatLE", prFilePutFloatLE, 2, 0);
1982 definePrimitive(base, index++, "_FilePutDoubleLE", prFilePutDoubleLE, 2, 0);
1984 definePrimitive(base, index++, "_FileGetChar", prFileGetChar, 1, 0);
1985 definePrimitive(base, index++, "_FileGetInt8", prFileGetInt8, 1, 0);
1986 definePrimitive(base, index++, "_FileGetInt16", prFileGetInt16, 1, 0);
1987 definePrimitive(base, index++, "_FileGetInt32", prFileGetInt32, 1, 0);
1988 definePrimitive(base, index++, "_FileGetFloat", prFileGetFloat, 1, 0);
1989 definePrimitive(base, index++, "_FileGetDouble", prFileGetDouble, 1, 0);
1990 definePrimitive(base, index++, "_FileGetInt16LE", prFileGetInt16LE, 1, 0);
1991 definePrimitive(base, index++, "_FileGetInt32LE", prFileGetInt32LE, 1, 0);
1992 definePrimitive(base, index++, "_FileGetFloatLE", prFileGetFloatLE, 1, 0);
1993 definePrimitive(base, index++, "_FileGetDoubleLE", prFileGetDoubleLE, 1, 0);
1995 definePrimitive(base, index++, "_FilePutString", prFilePutString, 2, 0);
1997 definePrimitive(base, index++, "_FileReadRaw", prFileReadRaw, 2, 0);
1998 definePrimitive(base, index++, "_FileReadRawLE", prFileReadRawLE, 2, 0);
2000 #ifdef NOCLASSIC
2001 definePrimitive(base, index++, "_Directory_At", prDirectory_At, 3, 0);
2002 definePrimitive(base, index++, "_File_GetFile", prFile_GetFile, 2, 0);
2003 definePrimitive(base, index++, "_File_PutFile", prFile_PutFile, 3, 0);
2004 #endif