00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #ifdef HAVE_JS
00037
00038 #include "script.h"
00039 #include "tools.h"
00040 #include "metadata_handler.h"
00041 #include "js_functions.h"
00042 #include "config_manager.h"
00043 #ifdef ONLINE_SERVICES
00044 #include "online_service.h"
00045 #endif
00046
00047 #ifdef YOUTUBE
00048 #include "youtube_service.h"
00049 #include "youtube_content_handler.h"
00050 #endif
00051
00052 #ifdef WEBORAMA
00053 #include "weborama_content_handler.h"
00054 #endif
00055
00056 #ifdef ATRAILERS
00057 #include "atrailers_content_handler.h"
00058 #endif
00059
00060 #ifdef HAVE_LIBDVDNAV
00061 #include "metadata/dvd_handler.h"
00062 #endif
00063
00064 using namespace zmm;
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 String Script::getProperty(JSObject *obj, String name)
00080 {
00081 jsval val;
00082 JSString *str;
00083 if (!JS_GetProperty(cx, obj, name.c_str(), &val))
00084 return nil;
00085 if (val == JSVAL_VOID)
00086 return nil;
00087 str = JS_ValueToString(cx, val);
00088 if (! str)
00089 return nil;
00090 return JS_GetStringBytes(str);
00091 }
00092
00093 int Script::getBoolProperty(JSObject *obj, String name)
00094 {
00095 jsval val;
00096 JSBool boolVal;
00097
00098 if (!JS_GetProperty(cx, obj, name.c_str(), &val))
00099 return -1;
00100 if (val == JSVAL_VOID)
00101 return -1;
00102 if (!JS_ValueToBoolean(cx, val, &boolVal))
00103 return -1;
00104 return (boolVal ? 1 : 0);
00105 }
00106
00107 int Script::getIntProperty(JSObject *obj, String name, int def)
00108 {
00109 jsval val;
00110 int intVal;
00111
00112 if (!JS_GetProperty(cx, obj, name.c_str(), &val))
00113 return def;
00114 if (val == JSVAL_VOID)
00115 return def;
00116 if (!JS_ValueToInt32(cx, val, &intVal))
00117 return def;
00118 return intVal;
00119 }
00120
00121 JSObject *Script::getObjectProperty(JSObject *obj, String name)
00122 {
00123 jsval val;
00124 JSObject *js_obj;
00125
00126 if (!JS_GetProperty(cx, obj, name.c_str(), &val))
00127 return NULL;
00128 if (val == JSVAL_VOID)
00129 return NULL;
00130 if (!JS_ValueToObject(cx, val, &js_obj))
00131 return NULL;
00132 return js_obj;
00133 }
00134
00135 void Script::setProperty(JSObject *obj, String name, String value)
00136 {
00137 jsval val;
00138 JSString *str = JS_NewStringCopyN(cx, value.c_str(), value.length());
00139 if (!str)
00140 return;
00141 val = STRING_TO_JSVAL(str);
00142 if (!JS_SetProperty(cx, obj, name.c_str(), &val))
00143 return;
00144 }
00145
00146 void Script::setIntProperty(JSObject *obj, String name, int value)
00147 {
00148 jsval val;
00149 if (!JS_NewNumberValue(cx, (jsdouble)value, &val))
00150 return;
00151 if (!JS_SetProperty(cx, obj, name.c_str(), &val))
00152 return;
00153 }
00154
00155 void Script::setObjectProperty(JSObject *parent, String name, JSObject *obj)
00156 {
00157 jsval val;
00158 val = OBJECT_TO_JSVAL(obj);
00159 if (!JS_SetProperty(cx, parent, name.c_str(), &val))
00160 return;
00161 }
00162
00163 void Script::deleteProperty(JSObject *obj, String name)
00164 {
00165 JS_DeleteProperty(cx, obj, name.c_str());
00166 }
00167
00168 static void
00169 js_error_reporter(JSContext *cx, const char *message, JSErrorReport *report)
00170 {
00171 int n;
00172 const char *ctmp;
00173
00174 int reportWarnings = 1;
00175
00176 Ref<StringBuffer> buf(new StringBuffer());
00177
00178 do
00179 {
00180 if (!report)
00181 {
00182 *buf << (char *)message;
00183 break;
00184 }
00185
00186
00187 if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
00188 return;
00189
00190 String prefix;
00191 Ref<StringBuffer> prefix_buf(new StringBuffer());
00192
00193 if (report->filename)
00194 *prefix_buf << (char *)report->filename << ":";
00195
00196 if (report->lineno)
00197 {
00198 *prefix_buf << (int)report->lineno << ": ";
00199 }
00200 if (JSREPORT_IS_WARNING(report->flags))
00201 {
00202 if (JSREPORT_IS_STRICT(report->flags))
00203 *prefix_buf << "(STRICT WARN)";
00204 else
00205 *prefix_buf << "(WARN)";
00206 }
00207
00208 prefix = prefix_buf->toString();
00209
00210
00211 while ((ctmp = strchr(message, '\n')) != 0)
00212 {
00213 ctmp++;
00214 if (prefix.length())
00215 *buf << prefix;
00216 *buf << String((char *)message, ctmp - message);
00217 message = ctmp;
00218 }
00219
00220
00221 if (prefix.length())
00222 *buf << prefix;
00223 *buf << (char *)message << "\n";
00224
00225 if (report->linebuf)
00226 {
00227
00228 n = strlen(report->linebuf);
00229 *buf << prefix << (char *)report->linebuf;
00230 *buf << (char *)((n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n");
00231 *buf << prefix;
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 }
00250 }
00251 while (0);
00252
00253 String err = buf->toString();
00254 log_js("%s\n", err.c_str());
00255 }
00256
00257
00258
00259 Script::Script(Ref<Runtime> runtime) : Object()
00260 {
00261 gc_counter = 0;
00262
00263 this->runtime = runtime;
00264 rt = runtime->getRT();
00265
00266
00267 cx = JS_NewContext(rt, 8192);
00268 if (! cx)
00269 throw _Exception(_("Scripting: could not initialize js context"));
00270
00271 #ifdef JS_THREADSAFE
00272 JS_SetContextThread(cx);
00273 JS_BeginRequest(cx);
00274 #endif
00275
00276
00277 glob = NULL;
00278 script = NULL;
00279
00280 _p2i = StringConverter::p2i();
00281 _j2i = StringConverter::j2i();
00282 _m2i = StringConverter::m2i();
00283 _f2i = StringConverter::f2i();
00284 _i2i = StringConverter::i2i();
00285
00286 JS_SetErrorReporter(cx, js_error_reporter);
00287 initGlobalObject();
00288
00289 JS_SetPrivate(cx, glob, this);
00290
00291
00292 setIntProperty(glob, _("OBJECT_TYPE_CONTAINER"),
00293 OBJECT_TYPE_CONTAINER);
00294 setIntProperty(glob, _("OBJECT_TYPE_ITEM"),
00295 OBJECT_TYPE_ITEM);
00296 setIntProperty(glob, _("OBJECT_TYPE_ACTIVE_ITEM"),
00297 OBJECT_TYPE_ACTIVE_ITEM);
00298 setIntProperty(glob, _("OBJECT_TYPE_ITEM_EXTERNAL_URL"),
00299 OBJECT_TYPE_ITEM_EXTERNAL_URL);
00300 setIntProperty(glob, _("OBJECT_TYPE_ITEM_INTERNAL_URL"),
00301 OBJECT_TYPE_ITEM_INTERNAL_URL);
00302 #ifdef ONLINE_SERVICES
00303 setIntProperty(glob, _("ONLINE_SERVICE_NONE"), (int)OS_None);
00304 #ifdef YOUTUBE
00305 setIntProperty(glob, _("ONLINE_SERVICE_YOUTUBE"), (int)OS_YouTube);
00306
00307 setProperty(glob, _("YOUTUBE_AUXDATA_KEYWORDS"),
00308 _(YOUTUBE_AUXDATA_KEYWORDS));
00309 setProperty(glob, _("YOUTUBE_AUXDATA_AVG_RATING"),
00310 _(YOUTUBE_AUXDATA_AVG_RATING));
00311 setProperty(glob, _("YOUTUBE_AUXDATA_AUTHOR"),
00312 _(YOUTUBE_AUXDATA_AUTHOR));
00313 setProperty(glob, _("YOUTUBE_AUXDATA_FEED"),
00314 _(YOUTUBE_AUXDATA_FEED));
00315 setProperty(glob, _("YOUTUBE_AUXDATA_VIEW_COUNT"),
00316 _(YOUTUBE_AUXDATA_VIEW_COUNT));
00317 setProperty(glob, _("YOUTUBE_AUXDATA_FAVORITE_COUNT"),
00318 _(YOUTUBE_AUXDATA_FAVORITE_COUNT));
00319 setProperty(glob, _("YOUTUBE_AUXDATA_RATING_COUNT"),
00320 _(YOUTUBE_AUXDATA_RATING_COUNT));
00321 setProperty(glob, _("YOUTUBE_AUXDATA_CATEGORY"),
00322 _(YOUTUBE_AUXDATA_CATEGORY));
00323 setProperty(glob, _("YOUTUBE_AUXDATA_SUBREQUEST_NAME"),
00324 _(YOUTUBE_AUXDATA_SUBREQUEST_NAME));
00325 setProperty(glob, _("YOUTUBE_AUXDATA_REQUEST"),
00326 _(YOUTUBE_AUXDATA_REQUEST));
00327 setProperty(glob, _("YOUTUBE_AUXDATA_REGION"),
00328 _(YOUTUBE_AUXDATA_REGION));
00329
00330 setIntProperty(glob, _("YOUTUBE_REQUEST_NONE"), (int)YT_request_none);
00331 setIntProperty(glob, _("YOUTUBE_REQUEST_VIDEO_SEARCH"),
00332 (int)YT_request_video_search);
00333 setIntProperty(glob, _("YOUTUBE_REQUEST_STANDARD_FEED"),
00334 (int)YT_request_stdfeed);
00335 setIntProperty(glob, _("YOUTUBE_REQUEST_USER_FAVORITES"),
00336 (int)YT_request_user_favorites);
00337 setIntProperty(glob, _("YOUTUBE_REQUEST_USER_PLAYLISTS"),
00338 (int)YT_request_user_playlists);
00339 setIntProperty(glob, _("YOUTUBE_REQUEST_USER_SUBSCRIPTIONS"),
00340 (int)YT_request_user_subscriptions);
00341 setIntProperty(glob, _("YOUTUBE_REQUEST_USER_UPLOADS"),
00342 (int)YT_request_user_uploads);
00343 #else
00344 setIntProperty(glob, _("ONLINE_SERVICE_YOUTUBE"), -1);
00345 #endif//YOUTUBE
00346
00347 #ifdef WEBORAMA
00348 setIntProperty(glob, _("ONLINE_SERVICE_WEBORAMA"), (int)OS_Weborama);
00349 setProperty(glob, _("WEBORAMA_AUXDATA_REQUEST_NAME"),
00350 _(WEBORAMA_AUXDATA_REQUEST_NAME));
00351 #else
00352 setIntProperty(glob, _("ONLINE_SERVICE_WEBORAMA"), -1);
00353 #endif//WEBORAMAa
00354
00355 #ifdef ATRAILERS
00356 setIntProperty(glob, _("ONLINE_SERVICE_APPLE_TRAILERS"), (int)OS_ATrailers);
00357 setProperty(glob, _("APPLE_TRAILERS_AUXDATA_POST_DATE"),
00358 _(ATRAILERS_AUXDATA_POST_DATE));
00359 #else
00360 setIntProperty(glob, _("ONLINE_SERVICE_APPLE_TRAILERS"), -1);
00361 #endif//ATRAILERS
00362
00363 #ifdef SOPCAST
00364 setIntProperty(glob, _("ONLINE_SERVICE_SOPCAST"), (int)OS_SopCast);
00365 #else
00366 setIntProperty(glob, _("ONLINE_SERVICE_SOPCAST"), -1);
00367 #endif//SOPCAST
00368
00369 #else // ONLINE SERVICES
00370 setIntProperty(glob, _("ONLINE_SERVICE_NONE"), 0);
00371 setIntProperty(glob, _("ONLINE_SERVICE_YOUTUBE"), -1);
00372 setIntProperty(glob, _("ONLINE_SERVICE_WEBORAMA"), -1);
00373 setIntProperty(glob, _("ONLINE_SERVICE_SOPCAST"), -1);
00374 setIntProperty(glob, _("ONLINE_SERVICE_APPLE_TRAILERS"), -1);
00375 #endif//ONLINE_SERVICES
00376
00377 for (int i = 0; i < M_MAX; i++)
00378 {
00379 setProperty(glob, _(MT_KEYS[i].sym), _(MT_KEYS[i].upnp));
00380 }
00381
00382 setProperty(glob, _("UPNP_CLASS_CONTAINER_MUSIC_ALBUM"),
00383 _(UPNP_DEFAULT_CLASS_MUSIC_ALBUM));
00384 setProperty(glob, _("UPNP_CLASS_CONTAINER_MUSIC_ARTIST"),
00385 _(UPNP_DEFAULT_CLASS_MUSIC_ARTIST));
00386 setProperty(glob, _("UPNP_CLASS_CONTAINER_MUSIC_GENRE"),
00387 _(UPNP_DEFAULT_CLASS_MUSIC_GENRE));
00388 setProperty(glob, _("UPNP_CLASS_CONTAINER"),
00389 _(UPNP_DEFAULT_CLASS_CONTAINER));
00390 setProperty(glob, _("UPNP_CLASS_ITEM"), _(UPNP_DEFAULT_CLASS_ITEM));
00391 setProperty(glob, _("UPNP_CLASS_ITEM_MUSIC_TRACK"),
00392 _(UPNP_DEFAULT_CLASS_MUSIC_TRACK));
00393 setProperty(glob, _("UPNP_CLASS_ITEM_VIDEO"),
00394 _(UPNP_DEFAULT_CLASS_VIDEO_ITEM));
00395 setProperty(glob, _("UPNP_CLASS_ITEM_IMAGE"),
00396 _(UPNP_DEFAULT_CLASS_IMAGE_ITEM));
00397 setProperty(glob, _("UPNP_CLASS_PLAYLIST_CONTAINER"),
00398 _(UPNP_DEFAULT_CLASS_PLAYLIST_CONTAINER));
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 defineFunction(_("print"), js_print, 0);
00414 defineFunction(_("addCdsObject"), js_addCdsObject, 3);
00415 defineFunction(_("copyObject"), js_copyObject, 2);
00416 defineFunction(_("f2i"), js_f2i, 1);
00417 defineFunction(_("m2i"), js_m2i, 1);
00418 defineFunction(_("p2i"), js_p2i, 1);
00419 defineFunction(_("j2i"), js_j2i, 1);
00420
00421 String common_scr_path = ConfigManager::getInstance()->getOption(CFG_IMPORT_SCRIPTING_COMMON_SCRIPT);
00422
00423 if (!string_ok(common_scr_path))
00424 log_js("Common script disabled in configuration\n");
00425 else
00426 {
00427 try
00428 {
00429 common_script = _load(common_scr_path);
00430 common_root = JS_NewScriptObject(cx, common_script);
00431 JS_AddNamedRoot(cx, &common_root, "common-script");
00432 _execute(common_script);
00433 }
00434 catch (Exception e)
00435 {
00436 if (common_root)
00437 JS_RemoveRoot(cx, &common_root);
00438
00439 log_js("Unable to load %s: %s\n", common_scr_path.c_str(),
00440 e.getMessage().c_str());
00441 }
00442 }
00443 #ifdef JS_THREADSAFE
00444 JS_EndRequest(cx);
00445 JS_ClearContextThread(cx);
00446 #endif
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456 Script::~Script()
00457 {
00458 #ifdef JS_THREADSAFE
00459 JS_SetContextThread(cx);
00460 JS_BeginRequest(cx);
00461 #endif
00462 if (common_root)
00463 JS_RemoveRoot(cx, &common_root);
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 #ifdef JS_THREADSAFE
00475 JS_EndRequest(cx);
00476
00477 #endif
00478 if (cx)
00479 {
00480 JS_DestroyContext(cx);
00481 cx = NULL;
00482 }
00483 }
00484
00485 void Script::setGlobalObject(JSObject *glob)
00486 {
00487 this->glob = glob;
00488 JS_SetGlobalObject(cx, glob);
00489 }
00490
00491 JSObject *Script::getGlobalObject()
00492 {
00493 return glob;
00494 }
00495
00496 JSContext *Script::getContext()
00497 {
00498 return cx;
00499 }
00500
00501 void Script::initGlobalObject()
00502 {
00503
00504 static JSClass global_class =
00505 {
00506 "global",
00507 JSCLASS_HAS_PRIVATE,
00508 JS_PropertyStub,
00509 JS_PropertyStub,
00510 JS_PropertyStub,
00511 JS_PropertyStub,
00512 JS_EnumerateStandardClasses,
00513 JS_ResolveStub,
00514 JS_ConvertStub,
00515 JS_FinalizeStub,
00516 JSCLASS_NO_OPTIONAL_MEMBERS
00517 };
00518
00519
00520 glob = JS_NewObject(cx, &global_class, NULL, NULL);
00521 if (! glob)
00522 throw _Exception(_("Scripting: could not initialize glboal class"));
00523
00524
00525 if (! JS_InitStandardClasses(cx, glob))
00526 throw _Exception(_("Scripting: JS_InitStandardClasses failed"));
00527
00528 }
00529
00530 void Script::defineFunction(String name, JSNative function, int numParams)
00531 {
00532 if (! JS_DefineFunction(cx, glob, name.c_str(), function, numParams, 0))
00533 throw _Exception(_("Scripting: JS_DefineFunction failed"));
00534 }
00535
00536 void Script::defineFunctions(JSFunctionSpec *functions)
00537 {
00538 if (! JS_DefineFunctions(cx, glob, functions))
00539 throw _Exception(_("Scripting: JS_DefineFunctions failed"));
00540 }
00541
00542 JSScript *Script::_load(zmm::String scriptPath)
00543 {
00544 if (glob == NULL)
00545 initGlobalObject();
00546
00547 JSScript *scr;
00548
00549 String scriptText = read_text_file(scriptPath);
00550
00551 if (!string_ok(scriptText))
00552 throw _Exception(_("empty script"));
00553
00554 Ref<StringConverter> j2i = StringConverter::j2i();
00555 try
00556 {
00557 scriptText = j2i->convert(scriptText, true);
00558 }
00559 catch (Exception e)
00560 {
00561 throw _Exception(_("Failed to convert import script:") + e.getMessage().c_str());
00562 }
00563
00564 scr = JS_CompileScript(cx, glob, scriptText.c_str(), scriptText.length(),
00565 scriptPath.c_str(), 1);
00566 if (! scr)
00567 throw _Exception(_("Scripting: failed to compile ") + scriptPath);
00568
00569 return scr;
00570 }
00571
00572 void Script::load(zmm::String scriptPath)
00573 {
00574 if (script)
00575 JS_DestroyScript(cx, script);
00576
00577 script = _load((scriptPath));
00578 }
00579
00580
00581 void Script::_execute(JSScript *scr)
00582 {
00583 jsval ret_val;
00584
00585 if (!JS_ExecuteScript(cx, glob, scr, &ret_val))
00586 throw _Exception(_("Script: failed to execute script"));
00587 }
00588
00589 void Script::execute()
00590 {
00591 _execute(script);
00592 }
00593
00594 Ref<CdsObject> Script::jsObject2cdsObject(JSObject *js, zmm::Ref<CdsObject> pcd)
00595 {
00596 String val;
00597 int objectType;
00598 int b;
00599 int i;
00600 Ref<StringConverter> sc;
00601
00602 if (this->whoami() == S_PLAYLIST)
00603 {
00604 sc = StringConverter::p2i();
00605 }
00606 else
00607 sc = StringConverter::i2i();
00608
00609 objectType = getIntProperty(js, _("objectType"), -1);
00610 if (objectType == -1)
00611 {
00612 log_error("missing objectType property\n");
00613 return nil;
00614 }
00615
00616 Ref<CdsObject> obj = CdsObject::createObject(objectType);
00617 objectType = obj->getObjectType();
00618
00619
00620
00621
00622 obj->setVirtual(1);
00623
00624 i = getIntProperty(js, _("id"), INVALID_OBJECT_ID);
00625 if (i != INVALID_OBJECT_ID)
00626 obj->setID(i);
00627 i = getIntProperty(js, _("refID"), INVALID_OBJECT_ID);
00628 if (i != INVALID_OBJECT_ID)
00629 obj->setRefID(i);
00630 i = getIntProperty(js, _("parentID"), INVALID_OBJECT_ID);
00631 if (i != INVALID_OBJECT_ID)
00632 obj->setParentID(i);
00633
00634 val = getProperty(js, _("title"));
00635 if (val != nil)
00636 {
00637 val = sc->convert(val);
00638 obj->setTitle(val);
00639 }
00640 else
00641 {
00642 if (pcd != nil)
00643 obj->setTitle(pcd->getTitle());
00644 }
00645
00646 val = getProperty(js, _("upnpclass"));
00647 if (val != nil)
00648 {
00649 val = sc->convert(val);
00650 obj->setClass(val);
00651 }
00652 else
00653 {
00654 if (pcd != nil)
00655 obj->setClass(pcd->getClass());
00656 }
00657
00658 b = getBoolProperty(js, _("restricted"));
00659 if (b >= 0)
00660 obj->setRestricted(b);
00661
00662 JSObject *js_meta = getObjectProperty(js, _("meta"));
00663 if (js_meta)
00664 {
00665 JS_AddNamedRoot(cx, &js_meta, "meta");
00667 for (int i = 0; i < M_MAX; i++)
00668 {
00669 val = getProperty(js_meta, _(MT_KEYS[i].upnp));
00670 if (val != nil)
00671 {
00672 if (i == M_TRACKNUMBER)
00673 {
00674 int j = val.toInt();
00675 if (j > 0)
00676 {
00677 obj->setMetadata(MT_KEYS[i].upnp, val);
00678 RefCast(obj, CdsItem)->setTrackNumber(j);
00679 }
00680 else
00681 RefCast(obj, CdsItem)->setTrackNumber(0);
00682 }
00683 else
00684 {
00685 val = sc->convert(val);
00686 obj->setMetadata(MT_KEYS[i].upnp, val);
00687 }
00688 }
00689 }
00690 JS_RemoveRoot(cx, &js_meta);
00691 }
00692
00693
00694 if (pcd != nil)
00695 {
00696 obj->setFlags(pcd->getFlags());
00697 obj->setResources(pcd->getResources());
00698 obj->setAuxData(pcd->getAuxData());
00699 }
00700
00701
00702 if (IS_CDS_ITEM(objectType))
00703 {
00704 Ref<CdsItem> item = RefCast(obj, CdsItem);
00705 Ref<CdsItem> pcd_item;
00706
00707 if (pcd != nil)
00708 pcd_item = RefCast(pcd, CdsItem);
00709
00710 val = getProperty(js, _("mimetype"));
00711 if (val != nil)
00712 {
00713 val = sc->convert(val);
00714 item->setMimeType(val);
00715 }
00716 else
00717 {
00718 if (pcd != nil)
00719 item->setMimeType(pcd_item->getMimeType());
00720 }
00721
00722 val = getProperty(js, _("serviceID"));
00723 if (val != nil)
00724 {
00725 val = sc->convert(val);
00726 item->setServiceID(val);
00727 }
00728
00731 val = getProperty(js, _("description"));
00732 if (val != nil)
00733 {
00734 val = sc->convert(val);
00735 item->setMetadata(MetadataHandler::getMetaFieldName(M_DESCRIPTION), val);
00736 }
00737 else
00738 {
00739 if (pcd != nil)
00740 item->setMetadata(MetadataHandler::getMetaFieldName(M_DESCRIPTION),
00741 pcd_item->getMetadata(MetadataHandler::getMetaFieldName(M_DESCRIPTION)));
00742 }
00743 if (this->whoami() == S_PLAYLIST)
00744 {
00745 item->setTrackNumber(getIntProperty(js, _("playlistOrder"), 0));
00746 }
00747
00748
00749 val = getProperty(js, _("location"));
00750 if ((val != nil) && (IS_CDS_PURE_ITEM(objectType) || IS_CDS_ACTIVE_ITEM(objectType)))
00751 val = normalizePath(val);
00752
00753 if (string_ok(val))
00754 obj->setLocation(val);
00755 else
00756 {
00757 if (pcd != nil)
00758 obj->setLocation(pcd->getLocation());
00759 }
00760
00761 if (IS_CDS_ACTIVE_ITEM(objectType))
00762 {
00763 Ref<CdsActiveItem> aitem = RefCast(obj, CdsActiveItem);
00764 Ref<CdsActiveItem> pcd_aitem;
00765 if (pcd != nil)
00766 pcd_aitem = RefCast(pcd, CdsActiveItem);
00768 val = getProperty(js, _("action"));
00769 if (val != nil)
00770 aitem->setAction(val);
00771 else
00772 {
00773 if (pcd != nil)
00774 aitem->setAction(pcd_aitem->getAction());
00775 }
00776
00777 val = getProperty(js, _("state"));
00778 if (val != nil)
00779 aitem->setState(val);
00780 else
00781 {
00782 if (pcd != nil)
00783 aitem->setState(pcd_aitem->getState());
00784 }
00785 }
00786
00787 if (IS_CDS_ITEM_EXTERNAL_URL(objectType))
00788 {
00789 String protocolInfo;
00790
00791 obj->setRestricted(true);
00792 Ref<CdsItemExternalURL> item = RefCast(obj, CdsItemExternalURL);
00793 val = getProperty(js, _("protocol"));
00794 if (val != nil)
00795 {
00796 val = sc->convert(val);
00797 protocolInfo = renderProtocolInfo(item->getMimeType(), val);
00798 }
00799 else
00800 {
00801 protocolInfo = renderProtocolInfo(item->getMimeType(), _(PROTOCOL));
00802 }
00803
00804 if (item->getResourceCount() == 0)
00805 {
00806 Ref<CdsResource> resource(new CdsResource(CH_DEFAULT));
00807 resource->addAttribute(MetadataHandler::getResAttrName(
00808 R_PROTOCOLINFO), protocolInfo);
00809
00810 item->addResource(resource);
00811 }
00812 }
00813 }
00814
00815
00816 if (IS_CDS_CONTAINER(objectType))
00817 {
00818 Ref<CdsContainer> cont = RefCast(obj, CdsContainer);
00819 i = getIntProperty(js, _("updateID"), -1);
00820 if (i >= 0)
00821 cont->setUpdateID(i);
00822
00823 b = getBoolProperty(js, _("searchable"));
00824 if (b >= 0)
00825 cont->setSearchable(b);
00826 }
00827
00828 return obj;
00829 }
00830
00831 void Script::cdsObject2jsObject(Ref<CdsObject> obj, JSObject *js)
00832 {
00833 String val;
00834 int i;
00835
00836 int objectType = obj->getObjectType();
00837
00838
00839 setIntProperty(js, _("objectType"), objectType);
00840
00841 i = obj->getID();
00842
00843 if (i != INVALID_OBJECT_ID)
00844 setIntProperty(js, _("id"), i);
00845
00846 i = obj->getParentID();
00847 if (i != INVALID_OBJECT_ID)
00848 setIntProperty(js, _("parentID"), i);
00849
00850 val = obj->getTitle();
00851 if (val != nil)
00852 setProperty(js, _("title"), val);
00853
00854 val = obj->getClass();
00855 if (val != nil)
00856 setProperty(js, _("upnpclass"), val);
00857
00858 val = obj->getLocation();
00859 if (val != nil)
00860 setProperty(js, _("location"), val);
00861
00862
00863
00864 i = obj->isRestricted();
00865 setIntProperty(js, _("restricted"), i);
00866
00867 if (obj->getFlag(OBJECT_FLAG_OGG_THEORA))
00868 setIntProperty(js, _("theora"), 1);
00869 else
00870 setIntProperty(js, _("theora"), 0);
00871
00872 #ifdef ONLINE_SERVICES
00873 if (obj->getFlag(OBJECT_FLAG_ONLINE_SERVICE))
00874 {
00875 service_type_t service = (service_type_t)(obj->getAuxData(_(ONLINE_SERVICE_AUX_ID)).toInt());
00876 setIntProperty(js, _("onlineservice"), (int)service);
00877 }
00878 else
00879 #endif
00880 setIntProperty(js, _("onlineservice"), 0);
00881
00882
00883 {
00884 JSObject *meta_js = JS_NewObject(cx, NULL, NULL, js);
00885 setObjectProperty(js, _("meta"), meta_js);
00886 Ref<Dictionary> meta = obj->getMetadata();
00887 Ref<Array<DictionaryElement> > elements = meta->getElements();
00888 int len = elements->size();
00889 for (int i = 0; i < len; i++)
00890 {
00891 Ref<DictionaryElement> el = elements->get(i);
00892 setProperty(meta_js, el->getKey(), el->getValue());
00893 }
00894
00895 if (RefCast(obj, CdsItem)->getTrackNumber() > 0)
00896 setProperty(meta_js, MetadataHandler::getMetaFieldName(M_TRACKNUMBER), String::from(RefCast(obj, CdsItem)->getTrackNumber()));
00897 }
00898
00899
00900 {
00901 JSObject *aux_js = JS_NewObject(cx, NULL, NULL, js);
00902 setObjectProperty(js, _("aux"), aux_js);
00903 Ref<Dictionary> aux = obj->getAuxData();
00904
00905 #ifdef HAVE_LIBDVDNAV
00906 if (obj->getFlag(OBJECT_FLAG_DVD_IMAGE))
00907 {
00908 JSObject *aux_dvd = JS_NewObject(cx, NULL, NULL, js);
00909 setObjectProperty(aux_js, _("DVD"), aux_dvd);
00910
00911 int title_count = obj->getAuxData(
00912 DVDHandler::renderKey(DVD_TitleCount)).toInt();
00913
00914 JSObject *titles = JS_NewArrayObject(cx, 0, NULL);
00915 setObjectProperty(aux_dvd, _("titles"), titles);
00916
00917 for (int t = 0; t < title_count; t++)
00918 {
00919 JSObject *title = JS_NewObject(cx, NULL, NULL, js);
00920 jsval val = OBJECT_TO_JSVAL(title);
00921 JS_SetElement(cx, titles, t, &val);
00922
00923 setProperty(title, _("duration"),
00924 obj->getAuxData(DVDHandler::renderKey(DVD_TitleDuration,
00925 t)));
00926
00927 JSObject *audio_tracks = JS_NewArrayObject(cx, 0, NULL);
00928 setObjectProperty(title, _("audio_tracks"), audio_tracks);
00929
00930 int audio_track_count = obj->getAuxData(
00931 DVDHandler::renderKey(DVD_AudioTrackCount, t)).toInt();
00932
00933 for (int a = 0; a < audio_track_count; a++)
00934 {
00935 JSObject *track = JS_NewObject(cx, NULL, NULL, js);
00936 jsval val = OBJECT_TO_JSVAL(track);
00937 JS_SetElement(cx, audio_tracks, a, &val);
00938
00939 setProperty(track, _("language"), obj->getAuxData(
00940 DVDHandler::renderKey(DVD_AudioTrackLanguage,
00941 t, 0, a)));
00942
00943 setProperty(track, _("format"), obj->getAuxData(
00944 DVDHandler::renderKey(DVD_AudioTrackFormat,
00945 t, 0, a)));
00946 }
00947
00948 JSObject *chapters = JS_NewArrayObject(cx, 0, NULL);
00949 setObjectProperty(title, _("chapters"), chapters);
00950
00951 int chapter_count = obj->getAuxData(DVDHandler::renderKey(DVD_ChapterCount, t)).toInt();
00952
00953 for (int c = 0; c < chapter_count; c++)
00954 {
00955 JSObject *chapter = JS_NewObject(cx, NULL, NULL, js);
00956 jsval val = OBJECT_TO_JSVAL(chapter);
00957 JS_SetElement(cx, chapters, c, &val);
00958
00959 setProperty(chapter, _("duration"), obj->getAuxData(
00960 DVDHandler::renderKey(DVD_ChapterRestDuration,
00961 t, c)));
00962 }
00963 }
00964 }
00965
00966 #endif
00967 #ifdef YOUTUBE
00968
00969 String tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_AVG_RATING));
00970 if (string_ok(tmp))
00971 aux->put(_(YOUTUBE_AUXDATA_AVG_RATING), tmp);
00972
00973 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_KEYWORDS));
00974 if (string_ok(tmp))
00975 aux->put(_(YOUTUBE_AUXDATA_KEYWORDS), tmp);
00976
00977 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_AUTHOR));
00978 if (string_ok(tmp))
00979 aux->put(_(YOUTUBE_AUXDATA_AUTHOR), tmp);
00980
00981 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_FAVORITE_COUNT));
00982 if (string_ok(tmp))
00983 aux->put(_(YOUTUBE_AUXDATA_FAVORITE_COUNT), tmp);
00984
00985 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_VIEW_COUNT));
00986 if (string_ok(tmp))
00987 aux->put(_(YOUTUBE_AUXDATA_VIEW_COUNT), tmp);
00988
00989 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_RATING_COUNT));
00990 if (string_ok(tmp))
00991 aux->put(_(YOUTUBE_AUXDATA_RATING_COUNT), tmp);
00992
00993 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_FEED));
00994 if (string_ok(tmp))
00995 aux->put(_(YOUTUBE_AUXDATA_FEED), tmp);
00996
00997 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_SUBREQUEST_NAME));
00998 if (string_ok(tmp))
00999 aux->put(_(YOUTUBE_AUXDATA_SUBREQUEST_NAME), tmp);
01000
01001 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_CATEGORY));
01002 if (string_ok(tmp))
01003 aux->put(_(YOUTUBE_AUXDATA_CATEGORY), tmp);
01004
01005 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_REQUEST));
01006 if (string_ok(tmp))
01007 {
01008 yt_requests_t req = (yt_requests_t)tmp.toInt();
01009
01010
01011
01012 if (req == YT_subrequest_playlists)
01013 req = YT_request_user_playlists;
01014 else if (req == YT_subrequest_subscriptions)
01015 req = YT_request_user_subscriptions;
01016
01017 setIntProperty(js, _("yt_request"), (int)req);
01018 tmp = YouTubeService::getRequestName(req);
01019 if (string_ok(tmp))
01020 aux->put(_(YOUTUBE_AUXDATA_REQUEST), tmp);
01021 }
01022
01023 tmp = obj->getAuxData(_(YOUTUBE_AUXDATA_REGION));
01024 if (string_ok(tmp))
01025 {
01026 yt_regions_t reg = (yt_regions_t)tmp.toInt();
01027 if (reg != YT_region_none)
01028 {
01029 tmp = YouTubeService::getRegionName(reg);
01030 if (string_ok(tmp))
01031 aux->put(_(YOUTUBE_AUXDATA_REGION), tmp);
01032 }
01033 }
01034 #endif // YouTube
01035 #ifdef HAVE_ATRAILERSSSS
01036 tmp = obj->getAuxData(_(ATRAILERS_AUXDATA_POST_DATE));
01037 if (string_ok(tmp))
01038 aux->put(_(ATRAILERS_AUXDATA_POST_DATE), tmp);
01039 #endif
01040
01041 Ref<Array<DictionaryElement> > elements = aux->getElements();
01042 int len = elements->size();
01043 for (int i = 0; i < len; i++)
01044 {
01045 Ref<DictionaryElement> el = elements->get(i);
01046 setProperty(aux_js, el->getKey(), el->getValue());
01047 }
01048 }
01049
01050
01052
01053
01054 if (IS_CDS_ITEM(objectType))
01055 {
01056 Ref<CdsItem> item = RefCast(obj, CdsItem);
01057 val = item->getMimeType();
01058 if (val != nil)
01059 setProperty(js, _("mimetype"), val);
01060
01061 val = item->getServiceID();
01062 if (val != nil)
01063 setProperty(js, _("serviceID"), val);
01064
01065 if (IS_CDS_ACTIVE_ITEM(objectType))
01066 {
01067 Ref<CdsActiveItem> aitem = RefCast(obj, CdsActiveItem);
01068 val = aitem->getAction();
01069 if (val != nil)
01070 setProperty(js, _("action"), val);
01071 val = aitem->getState();
01072 if (val != nil)
01073 setProperty(js, _("state"), val);
01074 }
01075 }
01076
01077
01078 if (IS_CDS_CONTAINER(objectType))
01079 {
01080 Ref<CdsContainer> cont = RefCast(obj, CdsContainer);
01081
01082 i = cont->getUpdateID();
01083 setIntProperty(js, _("updateID"), i);
01084
01085 i = cont->isSearchable();
01086 setIntProperty(js, _("searchable"), i);
01087 }
01088 }
01089
01090 String Script::convertToCharset(String str, charset_convert_t chr)
01091 {
01092 switch (chr)
01093 {
01094 case P2I:
01095 return _p2i->convert(str);
01096 case M2I:
01097 return _m2i->convert(str);
01098 case F2I:
01099 return _f2i->convert(str);
01100 case J2I:
01101 return _j2i->convert(str);
01102 default:
01103 return _i2i->convert(str);
01104 }
01105
01106 return nil;
01107 }
01108
01109 Ref<CdsObject> Script::getProcessedObject()
01110 {
01111 return processed;
01112 }
01113
01114 #endif // HAVE_JS