1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
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.
10 
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.
15 
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
19 */
20 /*
21 
22 An object archiving system for SuperCollider.
23 
24 */
25 
26 #include "PyrArchiverT.h"
27 #include "PyrKernel.h"
28 #include "PyrPrimitive.h"
29 #include "VMGlobals.h"
30 #include "GC.h"
31 #include "ReadWriteMacros.h"
32 
33 int prAsArchive(struct VMGlobals* g, int numArgsPushed);
prAsArchive(struct VMGlobals * g,int numArgsPushed)34 int prAsArchive(struct VMGlobals* g, int numArgsPushed) {
35     PyrSlot* a = g->sp;
36 
37     PyrArchiver<char*> arch(g);
38 
39     int err = arch.prepareToWriteArchive(a);
40     if (err)
41         return err;
42 
43     int32 size = arch.calcArchiveSize();
44 
45     PyrInt8Array* obj = newPyrInt8Array(g->gc, size, 0, true);
46     obj->size = size;
47     arch.setStream((char*)obj->b);
48     err = arch.writeArchive();
49 
50     if (err == errNone)
51         SetObject(a, obj);
52     else
53         SetNil(a);
54 
55     return err;
56 }
57 
58 int prUnarchive(struct VMGlobals* g, int numArgsPushed);
prUnarchive(struct VMGlobals * g,int numArgsPushed)59 int prUnarchive(struct VMGlobals* g, int numArgsPushed) {
60     PyrSlot* a = g->sp;
61 
62     if (!isKindOfSlot(a, class_int8array))
63         return errWrongType;
64 
65     PyrArchiver<char*> arch(g);
66 
67     arch.setStream((char*)slotRawObject(a)->slots);
68     int err = arch.readArchive(a);
69     return err;
70 }
71 
72 int prWriteArchive(struct VMGlobals* g, int numArgsPushed);
prWriteArchive(struct VMGlobals * g,int numArgsPushed)73 int prWriteArchive(struct VMGlobals* g, int numArgsPushed) {
74     PyrSlot* a = g->sp - 1;
75     PyrSlot* b = g->sp;
76 
77     if (!isKindOfSlot(b, class_string))
78         return errWrongType;
79 
80     char pathname[PATH_MAX];
81     memcpy(pathname, slotRawString(b)->s, slotRawObject(b)->size);
82     pathname[slotRawString(b)->size] = 0;
83 
84     PyrArchiver<FILE*> arch(g);
85     FILE* file = fopen(pathname, "wb");
86     int err = errNone;
87     if (file) {
88         err = arch.prepareToWriteArchive(a);
89         if (!err) {
90             arch.setStream(file);
91             err = arch.writeArchive();
92         }
93         fclose(file);
94     } else {
95         error("file open failed\n");
96         err = errFailed;
97     }
98     return err;
99 }
100 
101 int prReadArchive(struct VMGlobals* g, int numArgsPushed);
prReadArchive(struct VMGlobals * g,int numArgsPushed)102 int prReadArchive(struct VMGlobals* g, int numArgsPushed) {
103     PyrSlot* a = g->sp - 1;
104     PyrSlot* b = g->sp;
105 
106     if (!isKindOfSlot(b, class_string))
107         return errWrongType;
108 
109     char pathname[PATH_MAX];
110     memcpy(pathname, slotRawString(b)->s, slotRawObject(b)->size);
111     pathname[slotRawString(b)->size] = 0;
112 
113     PyrArchiver<FILE*> arch(g);
114     FILE* file = fopen(pathname, "rb");
115 
116     int err;
117     if (file) {
118         arch.setStream(file);
119         err = arch.readArchive(a);
120         fclose(file);
121     } else {
122         error("file open failed\n");
123         err = errFailed;
124     }
125     return err;
126 }
127 
128 void initArchiverPrimitives();
initArchiverPrimitives()129 void initArchiverPrimitives() {
130     int base, index;
131 
132     base = nextPrimitiveIndex();
133     index = 0;
134 
135     definePrimitive(base, index++, "_AsArchive", prAsArchive, 1, 0);
136     definePrimitive(base, index++, "_Unarchive", prUnarchive, 1, 0);
137     definePrimitive(base, index++, "_WriteArchive", prWriteArchive, 2, 0);
138     definePrimitive(base, index++, "_ReadArchive", prReadArchive, 2, 0);
139 }
140 
141 
142 #if _SC_PLUGINS_
143 
144 #    include "SCPlugin.h"
145 
146 // export the function that SC will call to load the plug in.
147 #    pragma export on
148 extern "C" {
149 SCPlugIn* loadPlugIn(void);
150 }
151 #    pragma export off
152 
153 
154 // define plug in object
155 class APlugIn : public SCPlugIn {
156 public:
157     APlugIn();
158     virtual ~APlugIn();
159 
160     virtual void AboutToCompile();
161 };
162 
APlugIn()163 APlugIn::APlugIn() {
164     // constructor for plug in
165 }
166 
~APlugIn()167 APlugIn::~APlugIn() {
168     // destructor for plug in
169 }
170 
AboutToCompile()171 void APlugIn::AboutToCompile() {
172     // this is called each time the class library is compiled.
173     initArchiverPrimitives();
174 }
175 
176 // This function is called when the plug in is loaded into SC.
177 // It returns an instance of APlugIn.
loadPlugIn()178 SCPlugIn* loadPlugIn() { return new APlugIn(); }
179 
180 #endif
181