Update change log and spec for wrt-plugins-tizen_0.4.15
[platform/framework/web/wrt-plugins-tizen.git] / src / Content / JSAudio.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 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
19 #include <dpl/log/log.h>
20 #include <CommonsJavaScript/PrivateObject.h>
21 #include <CommonsJavaScript/Converter.h>
22 #include <CommonsJavaScript/JSUtils.h>
23 #include <JSTizenException.h>
24 #include <JSTizenExceptionFactory.h>
25
26 #include "JSAudio.h"
27 #include "JSAudioLyrics.h"
28 #include "ContentConverter.h"
29 #include "AudioLyricsUtil.h"
30 #include "ContentUtility.h"
31
32
33 #define TIZEN_CONTENT_AUDIO_ATTRIBUTENAME       "AudioContent"
34 #define TIZEN_CONTENT_AUDIO_ALBUM                       "album"
35 #define TIZEN_CONTENT_AUDIO_GENRE                       "genres"
36 #define TIZEN_CONTENT_AUDIO_ARTIST                      "artists"
37 #define TIZEN_CONTENT_AUDIO_COMPOSER            "composers"
38 #define TIZEN_CONTENT_AUDIO_LYIRICS                     "lyrics"
39 #define TIZEN_CONTENT_AUDIO_COPYRIGHT           "copyright"
40 #define TIZEN_CONTENT_AUDIO_BITRATE                     "bitrate"
41 #define TIZEN_CONTENT_AUDIO_TRACKNUM            "trackNumber"
42 #define TIZEN_CONTENT_AUDIO_DURATION            "duration"
43 #define TIZEN_CONTENT_AUDIO_SIZE                        "size"
44
45 using namespace WrtDeviceApis::Commons;
46 using namespace WrtDeviceApis::CommonsJavaScript;
47
48 namespace DeviceAPI {
49 namespace Content {
50
51 JSClassDefinition JSAudio::m_classInfo =
52 {
53         0,
54         kJSClassAttributeNone,
55         TIZEN_CONTENT_AUDIO_ATTRIBUTENAME,
56         JSMedia::getClassRef(),
57         m_property,
58         NULL, //    m_function,
59         initialize,
60         finalize,
61         NULL, //hasProperty,
62         NULL, //getProperty,
63         NULL, //setProperty,
64         NULL, //DeleteProperty,
65         NULL, //GetPropertyNames,
66         NULL, //CallAsFunction,
67         NULL, //CallAsConstructor,
68         NULL, //HasInstance,
69         NULL  //ConvertToType
70 };
71
72 JSStaticValue JSAudio::m_property[] =
73 {
74         { TIZEN_CONTENT_AUDIO_ALBUM, getPropertyAlbum, NULL, kJSPropertyAttributeReadOnly},
75         { TIZEN_CONTENT_AUDIO_ARTIST, getPropertyArtist, NULL, kJSPropertyAttributeReadOnly},
76         { TIZEN_CONTENT_AUDIO_GENRE, getPropertyGenre, NULL, kJSPropertyAttributeReadOnly},
77         { TIZEN_CONTENT_AUDIO_COMPOSER , getPropertyComposer, NULL, kJSPropertyAttributeReadOnly},
78         { TIZEN_CONTENT_AUDIO_COPYRIGHT, getPropertyCopyright, NULL, kJSPropertyAttributeReadOnly},
79         { TIZEN_CONTENT_AUDIO_LYIRICS, getPropertyLyrics, NULL, kJSPropertyAttributeReadOnly},
80         { TIZEN_CONTENT_AUDIO_BITRATE, getPropertyBitrate, NULL, kJSPropertyAttributeReadOnly},
81         { TIZEN_CONTENT_AUDIO_TRACKNUM, getPropertyTrackNum, NULL, kJSPropertyAttributeReadOnly},
82         { TIZEN_CONTENT_AUDIO_DURATION, getPropertyDuration, NULL, kJSPropertyAttributeReadOnly},
83         { TIZEN_CONTENT_AUDIO_SIZE, getPropertySize, NULL, kJSPropertyAttributeReadOnly},
84         { 0, 0, 0, 0 }
85 };
86
87 JSClassRef JSAudio::m_jsClassRef = JSClassCreate(JSAudio::getClassInfo());
88
89 void JSAudio::initialize(JSContextRef context, JSObjectRef object)
90 {
91     LogDebug( "entered" );
92     AudioPrivObject *priv = static_cast<AudioPrivObject*>( JSObjectGetPrivate( object ) );
93     if (!priv)
94     {
95         MediacontentAudioPtr privateData(new MediacontentAudio());
96         priv = new AudioPrivObject(context, privateData);
97         JSObjectSetPrivate(object, static_cast<void*>(priv));
98         LogDebug("new Private Object is created" );
99     }
100     else {
101         LogDebug("private object already exists");
102     }
103 }
104
105 void JSAudio::finalize(JSObjectRef object)
106 {
107     LogDebug( "entered" );
108         AudioPrivObject *priv =  static_cast<AudioPrivObject*>( JSObjectGetPrivate( object ) ) ;
109         if (priv != NULL)
110         {
111                 delete (priv);
112                 priv = NULL;
113                 JSObjectSetPrivate(object, NULL);               
114         }
115 }
116
117 const JSClassRef JSAudio::getClassRef()
118 {
119         LogDebug("JSAudio::getClassRef()");
120
121     if (!m_jsClassRef) 
122     {
123             m_jsClassRef = JSClassCreate(&m_classInfo);
124     }
125     return m_jsClassRef;
126 }
127
128 const JSClassDefinition* JSAudio::getClassInfo()
129 {
130     return &m_classInfo;
131 }
132
133
134 MediacontentAudioPtr JSAudio::getAudioObject(JSObjectRef object)
135 {
136     LogDebug("entered");
137     AudioPrivObject *priv = static_cast<AudioPrivObject*>(JSObjectGetPrivate(object));
138     if(!priv) 
139     {
140         ThrowMsg(NullPointerException, "Private object is null");
141     }
142     MediacontentAudioPtr result = priv->getObject();
143     if (!result) 
144     {
145         ThrowMsg(NullPointerException, "Private object is null");
146     }
147     return result;
148 }
149
150 JSValueRef JSAudio::getPropertyAlbum(
151                                 JSContextRef context,
152                         JSObjectRef object,
153                         JSStringRef propertyName,
154                         JSValueRef* exception)
155 {
156     LogDebug("entered");
157     Try
158     {
159         Converter converter(context);
160         MediacontentAudioPtr audio = getAudioObject(object);
161         if(!audio->getAudioAlbum().empty()){
162             return converter.toJSValueRef(audio->getAudioAlbum());
163         }
164     }
165     Catch(Exception)
166     {
167         LogWarning("trying to get incorrect value");
168     }
169     return JSValueMakeNull(context);
170 }
171
172 JSValueRef JSAudio::getPropertyArtist(
173                                 JSContextRef context,
174                                 JSObjectRef object,
175                                 JSStringRef propertyName,
176                                 JSValueRef* exception)
177 {
178     LogDebug("getPropertyArtist::entered");
179     Try
180     {   
181         Converter converter(context);
182         MediacontentAudioPtr audio = getAudioObject(object);
183         if(audio->getAudioArtist().size() != 0){
184             JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
185             if (NULL == jsResult){
186                 ThrowMsg(NullPointerException, "Could not create js array object");
187             }
188             for( unsigned int i=0; i < audio->getAudioArtist().size(); i++){
189                 string artist = audio->getAudioArtist().at(i);
190                 LogDebug("artist : "  << artist);
191                 JSValueRef val = converter.toJSValueRef(artist);
192                 if(!JSSetArrayElement(context, jsResult, i, val)){
193                     ThrowMsg(UnknownException, "Could not insert value into js array");
194                 }
195             }
196             return jsResult;
197         }
198     }
199     Catch(Exception)
200     {
201         LogWarning("trying to get incorrect value");
202     }
203     return JSValueMakeNull(context);
204 }
205
206
207
208 JSValueRef JSAudio::getPropertyGenre(
209                                 JSContextRef context,
210                         JSObjectRef object, 
211                         JSStringRef propertyName, 
212                         JSValueRef* exception)
213 {
214     LogDebug("getPropertyGenre::entered");
215     Try
216     {
217         Converter converter(context);
218         MediacontentAudioPtr audio = getAudioObject(object);
219         if(audio->getAudioGenre().size() != 0){
220             JSObjectRef jsResult = JSCreateArrayObject(context, 0 , NULL);
221             if (NULL == jsResult)
222             {
223                 ThrowMsg(NullPointerException, "Could not create js array object");
224             }
225
226             for( unsigned int i=0; i < audio->getAudioGenre().size(); i++){
227                 string genre = audio->getAudioGenre().at(i);
228                 JSValueRef val = converter.toJSValueRef(genre);
229                 if(!JSSetArrayElement(context, jsResult, i, val)){
230                    ThrowMsg(UnknownException, "Could not insert value into js array");
231                 }
232             }
233             return jsResult;
234         }
235     }
236     Catch(Exception)
237     {
238         LogWarning("trying to get incorrect value");
239     }
240     return JSValueMakeNull(context);
241 }
242
243
244 JSValueRef JSAudio::getPropertyComposer(
245                                 JSContextRef context,
246                         JSObjectRef object, 
247                         JSStringRef propertyName, 
248                         JSValueRef* exception)
249 {
250     LogDebug("getPropertyComposer::entered");
251     Try
252     {   
253         Converter converter(context);
254         MediacontentAudioPtr audio = getAudioObject(object);
255         if(audio->getAudioComposer().size() != 0){
256             JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
257             if (NULL == jsResult){
258                 ThrowMsg(NullPointerException, "Could not create js array object");
259             }
260             for( unsigned int i=0; i < audio->getAudioComposer().size(); i++){
261                 string composer = audio->getAudioComposer().at(i);
262                 JSValueRef val = converter.toJSValueRef(composer);
263                 if(!JSSetArrayElement(context, jsResult, i, val)){
264                     ThrowMsg(UnknownException, "Could not insert value into js array");
265                 }
266             }
267             return jsResult;
268         }
269     }
270     Catch(Exception)
271     {
272         LogWarning("trying to get incorrect value");
273     }
274     return JSValueMakeNull(context);
275 }
276
277 JSValueRef JSAudio::getPropertyCopyright(
278                                 JSContextRef context,
279                         JSObjectRef object, 
280                         JSStringRef propertyName, 
281                         JSValueRef* exception)
282 {
283     LogDebug("entered");
284     Try
285     {
286         Converter converter(context);
287         MediacontentAudioPtr audio = getAudioObject(object);
288         if(!audio->getAudioCopyright().empty()){
289             return converter.toJSValueRef(audio->getAudioCopyright());
290         }
291     }
292     Catch(Exception)
293     {
294         LogWarning("trying to get incorrect value");
295     }
296     return JSValueMakeNull(context);
297 }
298
299 JSValueRef JSAudio::getPropertyLyrics(
300                                 JSContextRef context,
301                         JSObjectRef object,
302                         JSStringRef propertyName,
303                         JSValueRef* exception)
304 {
305     LogDebug("entered");
306     Try
307     {
308                 MediaConverterFactory::ConverterType converter = MediaConverterFactory::getConverter(context);
309
310         AudioPrivObject *priv = static_cast<AudioPrivObject*>(JSObjectGetPrivate(object));
311         if(!priv) 
312         {
313                 ThrowMsg(NullPointerException, "Private object is null");
314         }
315         MediacontentAudioPtr audio = priv->getObject();
316         if (!audio) 
317         {
318                 ThrowMsg(NullPointerException, "Private object is null");
319         }
320         
321         JSContextRef globalContext = priv->getContext();
322
323         //check lyrics state
324         LogDebug("lyrics state : " << audio->getLyricsState());
325
326         if ( CONTENT_LYRIC_UNKNOWN == audio->getLyricsState()  ||
327                 CONTENT_LYRIC_EXISTENT == audio->getLyricsState() )
328         {
329                 
330                 MediacontentLyricsPtr mediaContent;
331
332                 if ( audio->getLyricsState() == CONTENT_LYRIC_UNKNOWN )
333                 {
334                         mediaContent = MediaLyricsUtilSingleton::Instance().fetchLyrics(ContentUtility::convertUriToPath(audio->getFilePath()));
335                         if ( mediaContent )
336                                 audio->setAudioLyrics(mediaContent);
337                         else
338                                 audio->setAudioLyricNonExistent();
339                 }
340                 else
341                 {
342                         mediaContent = audio->getAudioLyrics();
343                 }
344                 
345                 if (mediaContent && (audio->getLyricsState() != CONTENT_LYRIC_NON_EXISTENT))
346                 {
347                         LogDebug(" lyrics success ");
348                         JSObjectRef jsobject;
349                         jsobject = JSMediaLyrics::createJSObject(globalContext, mediaContent);
350                         return jsobject;        
351                 }
352                 else
353                 {
354                         LogDebug(" lyrics success ");
355                         audio->setAudioLyricNonExistent();
356                 }
357         }
358         
359     }
360     Catch(Exception)
361     {
362         LogWarning("trying to get incorrect value");
363     }
364
365     return JSValueMakeNull(context);
366 }
367
368 JSValueRef JSAudio::getPropertyBitrate(
369                                 JSContextRef context,
370                         JSObjectRef object,
371                         JSStringRef propertyName,
372                         JSValueRef* exception)
373 {
374     LogDebug("entered");
375     Try
376     {
377         Converter converter(context);
378         MediacontentAudioPtr audio = getAudioObject(object);
379         return converter.toJSValueRef(audio->getAudioBitrate());
380     }
381     Catch(Exception)
382     {
383         LogWarning("trying to get incorrect value");
384     }
385     return JSValueMakeNull(context);
386 }
387
388 JSValueRef JSAudio::getPropertyTrackNum(
389                                 JSContextRef context,
390                         JSObjectRef object,
391                         JSStringRef propertyName,
392                         JSValueRef* exception)
393 {
394     LogDebug("entered");
395     Try
396     {
397         Converter converter(context);
398         MediacontentAudioPtr audio = getAudioObject(object);
399         return converter.toJSValueRef(audio->getAudioTrackNum());
400     }
401     Catch(Exception)
402     {
403         LogWarning("trying to get incorrect value");
404     }
405     return JSValueMakeNull(context);
406 }
407
408 JSValueRef JSAudio::getPropertyDuration(
409                                 JSContextRef context,
410                         JSObjectRef object,
411                         JSStringRef propertyName,
412                         JSValueRef* exception)
413 {
414     LogDebug("entered");
415     Try
416     {
417         Converter converter(context);
418         MediacontentAudioPtr audio = getAudioObject(object);
419         return converter.toJSValueRef(audio->getAudioDuration());
420     }
421     Catch(Exception)
422     {
423         LogWarning("trying to get incorrect value");
424     }
425     return JSValueMakeNull(context);
426 }
427
428 JSValueRef JSAudio::getPropertySize(
429                                 JSContextRef context,
430                         JSObjectRef object,
431                         JSStringRef propertyName,
432                         JSValueRef* exception)
433 {
434     LogDebug("entered");
435     Try
436     {
437         Converter converter(context);
438         MediacontentAudioPtr audio = getAudioObject(object);
439         double audioSize = (double)audio->getAudioSize();
440         return converter.toJSValueRef(audioSize);
441     }
442     Catch(Exception)
443     {
444         LogWarning("trying to get incorrect value");
445     }
446     return JSValueMakeUndefined(context);
447 }
448
449 bool JSAudio::setPropertyAlbum(
450                    JSContextRef context,
451                    JSObjectRef object,
452                    JSStringRef propertyName,
453                    JSValueRef value,
454                    JSValueRef* exception)
455 {
456     LogDebug("entered");
457     Try
458     {
459         Converter converter(context);
460
461         MediacontentAudioPtr audio = getAudioObject(object);
462         string album = converter.toString(value);
463         audio->setAudioAlbum(album, true);
464         return true;
465     }
466     Catch(Exception)
467     {
468         LogWarning("trying to set incorrect value");
469         DeviceAPI::Common::JSTizenExceptionFactory::postException(context, exception, DeviceAPI::Common::JSTizenException::TYPE_MISMATCH_ERROR);
470     }
471
472         return false;
473
474 }
475
476 bool  JSAudio::setPropertyArtist(
477                    JSContextRef context,
478                    JSObjectRef object,
479                    JSStringRef propertyName,
480                    JSValueRef value,
481                    JSValueRef* exception)
482 {
483     LogDebug("entered");
484     Try
485     {
486         Converter converter(context);
487         MediacontentAudioPtr audio = getAudioObject(object);
488
489         vector<std::string> artists;
490         if (!JSValueIsNull(context, value)) {
491                 if (JSIsArrayValue(context, value))
492                 {
493                 JSObjectRef jsObject = converter.toJSObjectRef(value);
494
495                 for (std::size_t i = 0; i < JSGetArrayLength(context, jsObject); ++i) {
496                         JSValueRef element = JSGetArrayElement(context, jsObject, i);
497                         artists.push_back(converter.toString(element));
498                 }
499         }
500                 else
501                 {
502                         DeviceAPI::Common::JSTizenExceptionFactory::postException(context, exception, DeviceAPI::Common::JSTizenException::TYPE_MISMATCH_ERROR);
503                         return false;
504                 }
505         }
506         else
507         {
508                 artists.push_back(converter.toString(value));
509         }
510         
511         audio->setAudioArtist(artists, true);
512         return true;
513     }
514     Catch(Exception)
515     {
516         LogWarning("trying to set incorrect value");
517         return DeviceAPI::Common::JSTizenExceptionFactory::postException(context, exception, DeviceAPI::Common::JSTizenException::TYPE_MISMATCH_ERROR);
518     }
519         
520         return false;
521 }
522
523
524 bool JSAudio::setPropertyComposer(
525                    JSContextRef context,
526                    JSObjectRef object,
527                    JSStringRef propertyName,
528                    JSValueRef value,
529                    JSValueRef* exception)
530 {
531     LogDebug("entered");
532     Try
533     {
534         Converter converter(context);
535         MediacontentAudioPtr audio = getAudioObject(object);
536
537         vector<std::string> composers;
538         if (!JSValueIsNull(context, value) ) 
539         {
540                 if (JSIsArrayValue(context, value))
541                 {
542                 JSObjectRef jsObject = converter.toJSObjectRef(value);
543                 
544                 for (std::size_t i = 0; i < JSGetArrayLength(context, jsObject); ++i) {
545                         JSValueRef element = JSGetArrayElement(context, jsObject, i);
546                         composers.push_back(converter.toString(element));
547                 }
548         }
549         }
550         else
551         {
552                 composers.push_back(converter.toString(value));
553         }
554
555         audio->setAudioComposer(composers, true);
556         return true;
557     }
558     Catch(Exception)
559     {
560         LogWarning("trying to set incorrect value");
561         return DeviceAPI::Common::JSTizenExceptionFactory::postException(context, exception, DeviceAPI::Common::JSTizenException::TYPE_MISMATCH_ERROR);
562     }
563         
564         return false;
565 }
566
567 bool    JSAudio::setPropertyGenre(
568                 JSContextRef context,
569                 JSObjectRef object,
570                 JSStringRef propertyName,
571                 JSValueRef value,
572                 JSValueRef* exception) 
573 {
574     LogDebug("entered");
575     Try
576     {
577         Converter converter(context);
578         MediacontentAudioPtr audio = getAudioObject(object);
579
580         vector<std::string> genres;
581         if (!JSValueIsNull(context, value) ) 
582         {
583                 if (JSIsArrayValue(context, value))
584                 {
585                 JSObjectRef jsObject = converter.toJSObjectRef(value);
586                 
587                 for (std::size_t i = 0; i < JSGetArrayLength(context, jsObject); ++i) {
588                         JSValueRef element = JSGetArrayElement(context, jsObject, i);
589                         genres.push_back(converter.toString(element));
590                 }
591
592                 }
593         }
594         else
595         {
596                 genres.push_back(converter.toString(value));
597         }
598
599         audio->setAudioGenre(genres, true);
600         return true;
601     }
602     Catch(Exception)
603     {
604         LogWarning("trying to set incorrect value");
605         return DeviceAPI::Common::JSTizenExceptionFactory::postException(context, exception, DeviceAPI::Common::JSTizenException::TYPE_MISMATCH_ERROR);
606     }
607
608         return false;
609 }
610
611 bool JSAudio::setPropertyTrackNumber(
612         JSContextRef context,
613         JSObjectRef object,
614         JSStringRef propertyName,
615         JSValueRef value,
616         JSValueRef* exception)
617 {
618     LogDebug("entered");
619     Try
620     {
621         Converter converter(context);
622                         
623         MediacontentAudioPtr audio = getAudioObject(object);
624         int trackNum = converter.toInt(value);
625         audio->setAudioTrackNum(trackNum, true);
626         return true;
627     }
628     Catch(Exception)
629     {
630         LogWarning("trying to set incorrect value");
631         DeviceAPI::Common::JSTizenExceptionFactory::postException(context, exception, DeviceAPI::Common::JSTizenException::TYPE_MISMATCH_ERROR);
632     }
633
634         return false;
635 }
636
637 }
638 }
639