Line data Source code
1 0 : /*
2 :
3 : OOJSSound.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "OOJSSound.h"
26 : #import "OOJavaScriptEngine.h"
27 : #import "OOSound.h"
28 : #import "OOMusicController.h"
29 : #import "ResourceManager.h"
30 : #import "Universe.h"
31 :
32 :
33 0 : static JSObject *sSoundPrototype;
34 :
35 :
36 : static OOSound *GetNamedSound(NSString *name);
37 :
38 :
39 : static JSBool SoundGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
40 :
41 : // Static methods
42 : static JSBool SoundStaticLoad(JSContext *context, uintN argc, jsval *vp);
43 : static JSBool SoundStaticMusicSoundSource(JSContext *context, uintN argc, jsval *vp);
44 : static JSBool SoundStaticPlayMusic(JSContext *context, uintN argc, jsval *vp);
45 : static JSBool SoundStaticStopMusic(JSContext *context, uintN argc, jsval *vp);
46 :
47 :
48 0 : static JSClass sSoundClass =
49 : {
50 : "Sound",
51 : JSCLASS_HAS_PRIVATE,
52 :
53 : JS_PropertyStub, // addProperty
54 : JS_PropertyStub, // delProperty
55 : SoundGetProperty, // getProperty
56 : JS_StrictPropertyStub, // setProperty
57 : JS_EnumerateStub, // enumerate
58 : JS_ResolveStub, // resolve
59 : JS_ConvertStub, // convert
60 : OOJSObjectWrapperFinalize, // finalize
61 : JSCLASS_NO_OPTIONAL_MEMBERS
62 : };
63 :
64 :
65 0 : enum
66 : {
67 : // Property IDs
68 : kSound_name
69 : };
70 :
71 :
72 0 : static JSPropertySpec sSoundProperties[] =
73 : {
74 : // JS name ID flags
75 : { "name", kSound_name, OOJS_PROP_READONLY_CB },
76 : { 0 }
77 : };
78 :
79 :
80 0 : static JSFunctionSpec sSoundMethods[] =
81 : {
82 : // JS name Function min args
83 : { "toString", OOJSObjectWrapperToString, 0, },
84 : { 0 }
85 : };
86 :
87 :
88 0 : static JSFunctionSpec sSoundStaticMethods[] =
89 : {
90 : // JS name Function min args
91 : { "load", SoundStaticLoad, 1, },
92 : { "musicSoundSource", SoundStaticMusicSoundSource,0, },
93 : { "playMusic", SoundStaticPlayMusic, 1, },
94 : { "stopMusic", SoundStaticStopMusic, 0, },
95 : { 0 }
96 : };
97 :
98 :
99 : DEFINE_JS_OBJECT_GETTER(JSSoundGetSound, &sSoundClass, sSoundPrototype, OOSound)
100 :
101 :
102 : // *** Public ***
103 :
104 0 : void InitOOJSSound(JSContext *context, JSObject *global)
105 : {
106 : sSoundPrototype = JS_InitClass(context, global, NULL, &sSoundClass, OOJSUnconstructableConstruct, 0, sSoundProperties, sSoundMethods, NULL, sSoundStaticMethods);
107 : OOJSRegisterObjectConverter(&sSoundClass, OOJSBasicPrivateObjectConverter);
108 : }
109 :
110 :
111 0 : OOSound *SoundFromJSValue(JSContext *context, jsval value)
112 : {
113 : OOJS_PROFILE_ENTER
114 :
115 : OOJSPauseTimeLimiter();
116 : if ([PLAYER status] != STATUS_START_GAME && JSVAL_IS_STRING(value))
117 : {
118 : return GetNamedSound(OOStringFromJSValue(context, value));
119 : }
120 : else
121 : {
122 : return OOJSNativeObjectOfClassFromJSValue(context, value, [OOSound class]);
123 : }
124 : OOJSResumeTimeLimiter();
125 :
126 : OOJS_PROFILE_EXIT
127 : }
128 :
129 :
130 : // *** Implementation stuff ***
131 :
132 0 : static JSBool SoundGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
133 : {
134 : if (!JSID_IS_INT(propID)) return YES;
135 :
136 : OOJS_NATIVE_ENTER(context)
137 :
138 : OOSound *sound = nil;
139 :
140 : if (EXPECT_NOT(!JSSoundGetSound(context, this, &sound))) return NO;
141 :
142 : switch (JSID_TO_INT(propID))
143 : {
144 : case kSound_name:
145 : *value = OOJSValueFromNativeObject(context, [sound name]);
146 : return YES;
147 :
148 : default:
149 : OOJSReportBadPropertySelector(context, this, propID, sSoundProperties);
150 : return NO;
151 : }
152 :
153 : OOJS_NATIVE_EXIT
154 : }
155 :
156 :
157 0 : static OOSound *GetNamedSound(NSString *name)
158 : {
159 : OOSound *sound = nil;
160 :
161 : if ([name hasPrefix:@"["] && [name hasSuffix:@"]"])
162 : {
163 : sound = [OOSound soundWithCustomSoundKey:name];
164 : }
165 : else
166 : {
167 : sound = [ResourceManager ooSoundNamed:name inFolder:@"Sounds"];
168 : }
169 :
170 : return sound;
171 : }
172 :
173 :
174 : // *** Static methods ***
175 :
176 : // load(name : String) : Sound
177 0 : static JSBool SoundStaticLoad(JSContext *context, uintN argc, jsval *vp)
178 : {
179 : OOJS_NATIVE_ENTER(context)
180 :
181 : NSString *name = nil;
182 : OOSound *sound = nil;
183 :
184 : if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
185 : if (name == nil)
186 : {
187 : OOJSReportBadArguments(context, @"Sound", @"load", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
188 : return NO;
189 : }
190 :
191 : OOJS_BEGIN_FULL_NATIVE(context)
192 : sound = GetNamedSound(name);
193 : OOJS_END_FULL_NATIVE
194 :
195 : OOJS_RETURN_OBJECT(sound);
196 :
197 : OOJS_NATIVE_EXIT
198 : }
199 :
200 :
201 0 : static JSBool SoundStaticMusicSoundSource(JSContext *context, uintN argc, jsval *vp)
202 : {
203 : OOJS_NATIVE_ENTER(context)
204 : OOSoundSource *musicSource = nil;
205 : OOJS_BEGIN_FULL_NATIVE(context)
206 : musicSource = [[OOMusicController sharedController] soundSource];
207 : OOJS_END_FULL_NATIVE
208 : OOJS_RETURN_OBJECT(musicSource);
209 : OOJS_NATIVE_EXIT
210 : }
211 :
212 :
213 : // playMusic(name : String [, loop : Boolean] [, gain : float])
214 0 : static JSBool SoundStaticPlayMusic(JSContext *context, uintN argc, jsval *vp)
215 : {
216 : OOJS_NATIVE_ENTER(context)
217 :
218 : NSString *name = nil;
219 : JSBool loop = NO;
220 : double gain = OO_DEFAULT_SOUNDSOURCE_GAIN;
221 :
222 : if (argc > 0) name = OOStringFromJSValue(context, OOJS_ARGV[0]);
223 : if (name == nil)
224 : {
225 : OOJSReportBadArguments(context, @"Sound", @"playMusic", MIN(argc, 1U), OOJS_ARGV, nil, @"string");
226 : return NO;
227 : }
228 : if (argc > 1)
229 : {
230 : if (!JS_ValueToBoolean(context, OOJS_ARGV[1], &loop))
231 : {
232 : OOJSReportBadArguments(context, @"Sound", @"playMusic", 1, OOJS_ARGV + 1, nil, @"boolean");
233 : return NO;
234 : }
235 : }
236 :
237 : if (argc > 2)
238 : {
239 : if (!OOJSArgumentListGetNumber(context, @"Sound", @"playMusic", 2, OOJS_ARGV + 2, &gain, NULL))
240 : {
241 : OOJSReportBadArguments(context, @"Sound", @"playMusic", 1, OOJS_ARGV + 2, nil, @"float");
242 : return NO;
243 : }
244 : }
245 :
246 : OOJS_BEGIN_FULL_NATIVE(context)
247 : [[OOMusicController sharedController] playMusicNamed:name loop:loop gain:(float)gain];
248 : OOJS_END_FULL_NATIVE
249 :
250 : OOJS_RETURN_VOID;
251 :
252 : OOJS_NATIVE_EXIT
253 : }
254 :
255 :
256 : // Sound.stopMusic([name : String])
257 0 : static JSBool SoundStaticStopMusic(JSContext *context, uintN argc, jsval *vp)
258 : {
259 : OOJS_NATIVE_ENTER(context)
260 :
261 : NSString *name = nil;
262 :
263 : if (argc > 0)
264 : {
265 : name = OOStringFromJSValue(context, OOJS_ARGV[0]);
266 : if (EXPECT_NOT(name == nil))
267 : {
268 : OOJSReportBadArguments(context, @"Sound", @"stopMusic", argc, OOJS_ARGV, nil, @"string or no argument");
269 : return NO;
270 : }
271 : }
272 :
273 : OOJS_BEGIN_FULL_NATIVE(context)
274 : OOMusicController *controller = [OOMusicController sharedController];
275 : if (name == nil || [name isEqualToString:[controller playingMusic]])
276 : {
277 : [[OOMusicController sharedController] stop];
278 : }
279 : OOJS_END_FULL_NATIVE
280 :
281 : OOJS_RETURN_VOID;
282 :
283 : OOJS_NATIVE_EXIT
284 : }
285 :
286 :
287 : @implementation OOSound (OOJavaScriptExtentions)
288 :
289 0 : - (jsval) oo_jsValueInContext:(JSContext *)context
290 : {
291 : JSObject *jsSelf = NULL;
292 : jsval result = JSVAL_NULL;
293 :
294 : jsSelf = JS_NewObject(context, &sSoundClass, sSoundPrototype, NULL);
295 : if (jsSelf != NULL)
296 : {
297 : if (!JS_SetPrivate(context, jsSelf, [self retain])) jsSelf = NULL;
298 : }
299 : if (jsSelf != NULL) result = OBJECT_TO_JSVAL(jsSelf);
300 :
301 : return result;
302 : }
303 :
304 :
305 0 : - (NSString *) oo_jsDescription
306 : {
307 : return [NSString stringWithFormat:@"[Sound \"%@\"]", [self name]];
308 : }
309 :
310 :
311 0 : - (NSString *) oo_jsClassName
312 : {
313 : return @"Sound";
314 : }
315 :
316 : @end
|