tizen 2.3.1 release
[framework/web/wearable/wrt-plugins-tizen.git] / src / Sound / JSSoundManager.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include "plugin_config.h"
19
20 #include "JSSoundManager.h"
21 #include "JSSoundDeviceInfo.h"
22 #include "SoundUtil.h"
23 #include "VolumeChangeCallback.h"
24 #include "SoundDeviceStateChangeCallback.h"
25
26 #include <SecurityExceptions.h>
27
28 #include <JSUtil.h>
29 #include <JSWebAPIError.h>
30 #include <ArgumentValidator.h>
31 #include <JSStringRefWrapper.h>
32 #include <GlobalContextManager.h>
33 #include <MultiCallbackUserData.h>
34 #include <PlatformException.h>
35 #include <Logger.h>
36
37 using namespace WrtDeviceApis::Commons;
38 using namespace DeviceAPI::Common;
39
40 namespace DeviceAPI {
41 namespace Sound {
42
43
44 JSClassDefinition JSSoundManager::m_classInfo = {
45     0,
46     kJSClassAttributeNone,
47     "SoundManager",
48     NULL, //ParentClass
49     NULL, //StaticValues
50     m_function, //StaticFunctions
51     initialize, //Initialize
52     finalize, //Finalize
53     NULL, //HasProperty,
54     NULL, //GetProperty,
55     NULL, //SetProperty,
56     NULL, //DeleteProperty,
57     NULL, //GetPropertyNames,
58     NULL, //CallAsFunction,
59     NULL, //CallAsConstructor,
60     NULL, //HasInstance,
61     NULL //ConvertToType
62 };
63
64 JSStaticFunction JSSoundManager::m_function[] = {
65     {
66         SOUND_MANAGER_API_GET_SOUND_MODE,
67         getSoundMode,
68         kJSPropertyAttributeNone
69     },
70     {
71         SOUND_MANAGER_API_SET_SOUND_MODE_LISTENER,
72         setSoundModeChangeListener,
73         kJSPropertyAttributeNone
74     },
75     {
76         SOUND_MANAGER_API_UNSET_SOUND_MODE_LISTENER,
77         unsetSoundModeChangeListener,
78         kJSPropertyAttributeNone
79     },
80     {
81         SOUND_MANAGER_API_SET_VOLUME,
82         setVolume,
83         kJSPropertyAttributeNone
84     },
85     {
86         SOUND_MANAGER_API_GET_VOLUME,
87         getVolume,
88         kJSPropertyAttributeNone
89     },
90     {
91         SOUND_MANAGER_API_SET_VOLUME_CHANGE_LISTENER,
92         setVolumeChangeListener,
93         kJSPropertyAttributeNone
94     },
95     {
96         SOUND_MANAGER_API_UNSET_VOLUME_CHANGE_LISTENER,
97         unsetVolumeChangeListener,
98         kJSPropertyAttributeNone
99     },
100     {
101         SOUND_MANAGER_API_GET_CONNECTED_DEVICE_LIST,
102         getConnectedDeviceList,
103         kJSPropertyAttributeNone
104     },
105     {
106         SOUND_MANAGER_API_GET_ACTIVATED_DEVICE_LIST,
107         getActivatedDeviceList,
108         kJSPropertyAttributeNone
109     },
110     {
111         SOUND_MANAGER_API_ADD_DEVICE_STATE_CHANGE_LISTENER,
112         addDeviceStateChangeListener,
113         kJSPropertyAttributeNone
114     },
115     {
116         SOUND_MANAGER_API_REMOVE_DEVICE_STATE_CHANGE_LISTENER,
117         removeDeviceStateChangeListener,
118         kJSPropertyAttributeNone
119     },
120     { 0, 0, 0 }
121 };
122
123 JSClassRef JSSoundManager::m_jsClassRef = JSClassCreate(JSSoundManager::getClassInfo());
124
125 const JSClassRef JSSoundManager::getClassRef()
126 {
127     LOGD("Entered");
128
129     if (!m_jsClassRef) {
130         m_jsClassRef = JSClassCreate(&m_classInfo);
131     }
132     return m_jsClassRef;
133 }
134
135 const JSClassDefinition* JSSoundManager::getClassInfo()
136 {
137     LOGD("Entered");
138
139     return &m_classInfo;
140 }
141
142 void JSSoundManager::initialize(JSContextRef context, JSObjectRef object)
143 {
144     LOGD("Entered");
145
146     JSObjectSetPrivate(object, static_cast<void *>(SoundManager::getInstance()));
147 }
148
149 void JSSoundManager::finalize(JSObjectRef object)
150 {
151     LOGD("Entered");
152 }
153
154 JSValueRef JSSoundManager::getSoundMode(JSContextRef context,
155         JSObjectRef object,
156         JSObjectRef thisObject,
157         size_t argumentCount,
158         const JSValueRef arguments[],
159         JSValueRef* exception)
160 {
161     LOGD("Entered");
162
163     try {
164         SoundModeType mode = SoundManager::getInstance()->getSoundMode();
165         return JSUtil::toJSValueRef(context, SoundUtil::soundModeToString(mode));
166     } catch (const BasePlatformException &err) {
167         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
168         return JSWebAPIErrorFactory::postException(context, exception, err);
169     } catch (...) {
170         DeviceAPI::Common::UnknownException
171             err("Unknown Error in SoundManager.getSoundMode().");
172         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
173         return JSWebAPIErrorFactory::postException(context, exception, err);
174     }
175 }
176
177 JSValueRef JSSoundManager::setSoundModeChangeListener(JSContextRef context,
178         JSObjectRef object,
179         JSObjectRef thisObject,
180         size_t argumentCount,
181         const JSValueRef arguments[],
182         JSValueRef* exception)
183 {
184     LOGD("Entered");
185
186     try {
187         ArgumentValidator validator(context, argumentCount, arguments);
188         JSObjectRef functionObject = validator.toFunction(0, false);
189
190         SoundModeChangeListenerPtr eventListener(new SoundModeChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context), thisObject, functionObject));
191         SoundManager::getInstance()->setSoundModeChangeListener(eventListener);
192     } catch (const BasePlatformException &err) {
193         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
194         return JSWebAPIErrorFactory::postException(context, exception, err);
195     } catch (...) {
196         DeviceAPI::Common::UnknownException
197             err("Unknown Error in SoundManager.setSoundModeChangeListener().");
198         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
199         return JSWebAPIErrorFactory::postException(context, exception, err);
200     }
201
202     return JSValueMakeUndefined(context);
203 }
204
205 JSValueRef JSSoundManager::unsetSoundModeChangeListener(JSContextRef context,
206         JSObjectRef object,
207         JSObjectRef thisObject,
208         size_t argumentCount,
209         const JSValueRef arguments[],
210         JSValueRef* exception)
211 {
212    LOGD("Entered");
213
214    try {
215         SoundManager::getInstance()->unsetSoundModeChangeListener();
216     } catch (const BasePlatformException &err) {
217         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
218         return JSWebAPIErrorFactory::postException(context, exception, err);
219     } catch (...) {
220         DeviceAPI::Common::UnknownException
221             err("Unknown Error in SoundManager.unsetSoundModeChangeListener().");
222         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
223         return JSWebAPIErrorFactory::postException(context, exception, err);
224     }
225    return JSValueMakeUndefined(context);
226
227 }
228
229 JSValueRef JSSoundManager::setVolume(JSContextRef context,
230         JSObjectRef object,
231         JSObjectRef thisObject,
232         size_t argumentCount,
233         const JSValueRef arguments[],
234         JSValueRef* exception)
235 {
236    LOGD("Entered");
237
238    try {
239         TIZEN_CHECK_ACCESS(context, exception, SoundManager::getInstance(), SOUND_MANAGER_API_SET_VOLUME);
240
241         // Private Object
242         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
243         if (!priv) {
244             throw TypeMismatchException("Private object is NULL.");
245         }
246
247         ArgumentValidator validator(context, argumentCount, arguments);
248
249         // type
250         std::string type = validator.toString(0);
251
252         // volume
253         double volume = validator.toDouble(1);
254
255         // perform
256         priv->setVolume(SoundUtil::stringToSoundType(type), volume);
257
258         return JSValueMakeUndefined(context);
259     } catch (const BasePlatformException &err) {
260         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
261         return JSWebAPIErrorFactory::postException(context, exception, err);
262     } catch (...) {
263         DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.setVolume().");
264         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
265         return JSWebAPIErrorFactory::postException(context, exception, err);
266     }
267 }
268
269 JSValueRef JSSoundManager::getVolume(JSContextRef context,
270         JSObjectRef object,
271         JSObjectRef thisObject,
272         size_t argumentCount,
273         const JSValueRef arguments[],
274         JSValueRef* exception)
275 {
276     LOGD("Entered");
277
278     try {
279         // Private Object
280         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
281         if (!priv) {
282             throw TypeMismatchException("Private object is NULL.");
283         }
284
285         ArgumentValidator validator(context, argumentCount, arguments);
286
287         // type
288         std::string type = validator.toString(0);
289
290         // perform
291         double ret = priv->getVolume(SoundUtil::stringToSoundType(type));
292
293         return JSUtil::toJSValueRef(context, ret);
294     } catch (const BasePlatformException &err) {
295         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
296         return JSWebAPIErrorFactory::postException(context, exception, err);
297     } catch (...) {
298         DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.getVolume().");
299         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
300         return JSWebAPIErrorFactory::postException(context, exception, err);
301     }
302 }
303
304 JSValueRef JSSoundManager::setVolumeChangeListener(JSContextRef context,
305         JSObjectRef object,
306         JSObjectRef thisObject,
307         size_t argumentCount,
308         const JSValueRef arguments[],
309         JSValueRef* exception)
310 {
311     LOGD("Entered");
312
313     try {
314         // Private Object
315         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
316         if (!priv) {
317             throw TypeMismatchException("Private object is NULL.");
318         }
319
320         ArgumentValidator validator(context, argumentCount, arguments);
321
322         // callback
323         JSObjectRef successCallback = validator.toFunction(0);
324         VolumeChangeCallback* volumeChangeCallback =
325             new VolumeChangeCallback(
326                 GlobalContextManager::getInstance()->getGlobalContext(context));
327
328         volumeChangeCallback->setCallback("onsuccess", successCallback);
329
330         // perform
331         priv->setVolumeChangeListener(volumeChangeCallback);
332
333         return JSValueMakeUndefined(context);
334     } catch (const BasePlatformException &err) {
335         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
336         return JSWebAPIErrorFactory::postException(context, exception, err);
337     } catch (...) {
338         DeviceAPI::Common::UnknownException err(
339             "Unknown Error in SoundManager.setVolumeChangeListener().");
340         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
341         return JSWebAPIErrorFactory::postException(context, exception, err);
342     }
343 }
344
345 JSValueRef JSSoundManager::unsetVolumeChangeListener(JSContextRef context,
346         JSObjectRef object,
347         JSObjectRef thisObject,
348         size_t argumentCount,
349         const JSValueRef arguments[],
350         JSValueRef* exception)
351 {
352     LOGD("Entered");
353
354     try {
355         // Private Object
356         SoundManager *priv =
357             static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
358         if (!priv) {
359             throw TypeMismatchException("Private object is NULL.");
360         }
361
362         // perform
363         priv->unsetVolumeChangeListener();
364
365         return JSValueMakeUndefined(context);
366     } catch (const BasePlatformException &err) {
367         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
368         return JSWebAPIErrorFactory::postException(context, exception, err);
369     } catch (...) {
370         DeviceAPI::Common::UnknownException err(
371             "Unknown Error in SoundManager.unsetVolumeChangeListener().");
372         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
373         return JSWebAPIErrorFactory::postException(context, exception, err);
374     }
375 }
376
377 //newly added API on 2.3.1
378 JSValueRef JSSoundManager::getConnectedDeviceList(JSContextRef context,
379         JSObjectRef object,
380         JSObjectRef thisObject,
381         size_t argumentCount,
382         const JSValueRef arguments[],
383         JSValueRef* exception)
384 {
385     LOGD("Entered");
386
387     try {
388         // Private Object
389         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
390         if (!priv) {
391             SoundUtil::throwSoundException<TypeMismatchException>("Private object is NULL.");
392         }
393
394         // perform
395         std::vector<SoundDeviceInfoPtr> list = priv->getConnectedDeviceList();
396
397         LOGD("The length of the list: (%d)", list.size());
398
399         JSObjectRef objArr[list.size()];
400         for (int i = 0; i < list.size(); i++) {
401             objArr[i] = JSSoundDeviceInfo::makeJSObject(context, list[i]);
402         }
403
404         JSValueRef exception = NULL;
405         JSObjectRef JSResult = JSObjectMakeArray(context, list.size(), objArr, &exception);
406         if (exception != NULL) {
407             LOGD("exception is not null");
408             SoundUtil::throwSoundException("exception is not null");
409         }
410
411         return JSResult;
412     } catch (const BasePlatformException &err) {
413         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
414         return JSWebAPIErrorFactory::postException(context, exception, err);
415     } catch (...) {
416         DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.getConnectedDeviceList().");
417         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
418         return JSWebAPIErrorFactory::postException(context, exception, err);
419     }
420 }
421
422 JSValueRef JSSoundManager::getActivatedDeviceList(JSContextRef context,
423         JSObjectRef object,
424         JSObjectRef thisObject,
425         size_t argumentCount,
426         const JSValueRef arguments[],
427         JSValueRef* exception)
428 {
429     LOGD("Entered");
430
431     try {
432         // Private Object
433         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
434         if (!priv) {
435             SoundUtil::throwSoundException<TypeMismatchException>("Private object is NULL.");
436         }
437
438         // perform
439         std::vector<SoundDeviceInfoPtr> list = priv->getActivatedDeviceList();
440
441         LOGD("The length of the list: (%d)", list.size());
442
443         JSObjectRef objArr[list.size()];
444         for (int i = 0; i < list.size(); i++) {
445             objArr[i] = JSSoundDeviceInfo::makeJSObject(context, list[i]);
446         }
447
448         JSValueRef exception = NULL;
449         JSObjectRef JSResult = JSObjectMakeArray(context, list.size(), objArr, &exception);
450         if (exception != NULL) {
451             LOGD("exception is not null");
452             SoundUtil::throwSoundException("exception is not null");
453         }
454
455         return JSResult;
456     } catch (const BasePlatformException &err) {
457         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
458         return JSWebAPIErrorFactory::postException(context, exception, err);
459     } catch (...) {
460         DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.getActivatedDeviceList().");
461         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
462         return JSWebAPIErrorFactory::postException(context, exception, err);
463     }
464 }
465
466 JSValueRef JSSoundManager::addDeviceStateChangeListener(JSContextRef context,
467         JSObjectRef object,
468         JSObjectRef thisObject,
469         size_t argumentCount,
470         const JSValueRef arguments[],
471         JSValueRef* exception)
472 {
473     LOGD("Entered");
474
475     try {
476         // Private Object
477         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
478         if (!priv) {
479             SoundUtil::throwSoundException<TypeMismatchException>("Private object is NULL.");
480         }
481
482         ArgumentValidator validator(context, argumentCount, arguments);
483
484         // callback
485         JSContextRef g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
486         SoundDeviceStateChangeCallbackPtr callback = SoundDeviceStateChangeCallbackPtr(new SoundDeviceStateChangeCallback(g_ctx));
487
488         JSObjectRef Listener = validator.toFunction(0);
489         if (Listener) {
490             callback->setCallback("onchanged", Listener);
491         }
492
493         // perform
494         const long id = priv->addDeviceStateChangeListener(callback);
495         LOGD("id: (%d)", id);
496
497         return JSUtil::toJSValueRef(context, id);
498     } catch (const BasePlatformException &err) {
499         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
500         return JSWebAPIErrorFactory::postException(context, exception, err);
501     } catch (...) {
502         DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.addDeviceStateChangeListener().");
503         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
504         return JSWebAPIErrorFactory::postException(context, exception, err);
505     }
506 }
507
508 JSValueRef JSSoundManager::removeDeviceStateChangeListener(JSContextRef context,
509         JSObjectRef object,
510         JSObjectRef thisObject,
511         size_t argumentCount,
512         const JSValueRef arguments[],
513         JSValueRef* exception)
514 {
515     LOGD("Entered");
516
517     try {
518         // Private Object
519         SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
520         if (!priv) {
521             SoundUtil::throwSoundException<TypeMismatchException>("Private object is NULL.");
522         }
523
524         ArgumentValidator validator(context, argumentCount, arguments);
525
526         // id
527         const long id = validator.toLong(0);
528         LOGD("id: (%d)", id);
529
530         // perform
531         priv->removeDeviceStateChangeListener(id);
532
533         return JSValueMakeUndefined(context);
534     } catch (const BasePlatformException &err) {
535         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
536         return JSWebAPIErrorFactory::postException(context, exception, err);
537     } catch (...) {
538         DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.removeDeviceStateChangeListener().");
539         LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
540         return JSWebAPIErrorFactory::postException(context, exception, err);
541     }
542 }
543
544 } // Sound
545 } // DeviceAPI