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 "playlist_parser_script.h"
00039 #include "config_manager.h"
00040 #include "js_functions.h"
00041
00042 #define ONE_TEXTLINE_BYTES 1024
00043
00044 using namespace zmm;
00045
00046 extern "C" {
00047
00048 static JSBool
00049 js_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
00050 {
00051 PlaylistParserScript *self = (PlaylistParserScript *)JS_GetPrivate(cx, obj);
00052
00053 String line;
00054
00055 try
00056 {
00057 line = self->readln();
00058 }
00059 catch (ServerShutdownException se)
00060 {
00061 log_warning("Aborting script execution due to server shutdown.\n");
00062 return JS_FALSE;
00063 }
00064 catch (Exception e)
00065 {
00066 e.printStackTrace();
00067 return JS_TRUE;
00068 }
00069
00070 JSString *jsline = JS_NewStringCopyZ(cx, line.c_str());
00071
00072 *rval = STRING_TO_JSVAL(jsline);
00073
00074 return JS_TRUE;
00075 }
00076
00077 }
00078
00079 PlaylistParserScript::PlaylistParserScript(Ref<Runtime> runtime) : Script(runtime)
00080 {
00081 currentHandle = NULL;
00082 currentObjectID = INVALID_OBJECT_ID;
00083 currentLine = NULL;
00084
00085 #ifdef JS_THREADSAFE
00086 JS_SetContextThread(cx);
00087 JS_BeginRequest(cx);
00088 #endif
00089
00090 try
00091 {
00092 defineFunction(_("readln"), js_readln, 0);
00093
00094 String scriptPath = ConfigManager::getInstance()->getOption(CFG_IMPORT_SCRIPTING_PLAYLIST_SCRIPT);
00095 load(scriptPath);
00096 root = JS_NewScriptObject(cx, script);
00097 JS_AddNamedRoot(cx, &root, "PlaylistScript");
00098 }
00099 catch (Exception ex)
00100 {
00101 #ifdef JS_THREADSAFE
00102 JS_EndRequest(cx);
00103 JS_ClearContextThread(cx);
00104 #endif
00105 throw ex;
00106 }
00107
00108 #ifdef JS_THREADSAFE
00109 JS_EndRequest(cx);
00110 JS_ClearContextThread(cx);
00111 #endif
00112 }
00113
00114 String PlaylistParserScript::readln()
00115 {
00116 String ret;
00117 if (!currentHandle)
00118 throw _Exception(_("Readline not yet setup for use"));
00119
00120 if ((currentTask != nil) && (!currentTask->isValid()))
00121 return nil;
00122
00123 while (true)
00124 {
00125 if(fgets(currentLine, ONE_TEXTLINE_BYTES, currentHandle) == NULL)
00126 return nil;
00127
00128 ret = trim_string(currentLine);
00129 if (string_ok(ret))
00130 return ret;
00131 }
00132 }
00133
00134 void PlaylistParserScript::processPlaylistObject(zmm::Ref<CdsObject> obj, Ref<GenericTask> task)
00135 {
00136 #ifdef JS_THREADSAFE
00137 JS_SetContextThread(cx);
00138 JS_BeginRequest(cx);
00139 #endif
00140 if ((currentObjectID != INVALID_OBJECT_ID) || (currentHandle != NULL) ||
00141 (currentLine != NULL))
00142 {
00143 #ifdef JS_THREADSAFE
00144 JS_EndRequest(cx);
00145 JS_ClearContextThread(cx);
00146 #endif
00147 throw _Exception(_("recursion not allowed!"));
00148 }
00149
00150 if (!IS_CDS_PURE_ITEM(obj->getObjectType()))
00151 {
00152 #ifdef JS_THREADSAFE
00153 JS_EndRequest(cx);
00154 JS_ClearContextThread(cx);
00155 #endif
00156 throw _Exception(_("only allowed for pure items"));
00157 }
00158
00159 currentTask = task;
00160 currentObjectID = obj->getID();
00161 currentLine = (char *)MALLOC(ONE_TEXTLINE_BYTES);
00162 if (!currentLine)
00163 {
00164 currentObjectID = INVALID_OBJECT_ID;
00165 currentTask = nil;
00166 #ifdef JS_THREADSAFE
00167 JS_EndRequest(cx);
00168 JS_ClearContextThread(cx);
00169 #endif
00170 throw _Exception(_("failed to allocate memory for playlist parsing!"));
00171 }
00172
00173 currentLine[0] = '\0';
00174
00175 currentHandle = fopen(obj->getLocation().c_str(), "r");
00176 if (!currentHandle)
00177 {
00178 currentObjectID = INVALID_OBJECT_ID;
00179 currentTask = nil;
00180 FREE(currentLine);
00181 #ifdef JS_THREADSAFE
00182 JS_EndRequest(cx);
00183 JS_ClearContextThread(cx);
00184 #endif
00185 throw _Exception(_("failed to open file: ") + obj->getLocation());
00186 }
00187
00188 JSObject *playlist = JS_NewObject(cx, NULL, NULL, glob);
00189
00190 try
00191 {
00192 setObjectProperty(glob, _("playlist"), playlist);
00193 cdsObject2jsObject(obj, playlist);
00194
00195 execute();
00196 }
00197
00198 catch (Exception e)
00199 {
00200 fclose(currentHandle);
00201 currentHandle = NULL;
00202
00203 FREE(currentLine);
00204 currentLine = NULL;
00205
00206 currentObjectID = INVALID_OBJECT_ID;
00207 currentTask = nil;
00208
00209 #ifdef JS_THREADSAFE
00210 JS_EndRequest(cx);
00211 JS_ClearContextThread(cx);
00212 #endif
00213 throw e;
00214 }
00215
00216 fclose(currentHandle);
00217 currentHandle = NULL;
00218
00219 FREE(currentLine);
00220 currentLine = NULL;
00221
00222 currentObjectID = INVALID_OBJECT_ID;
00223 currentTask = nil;
00224
00225 gc_counter++;
00226 if (gc_counter > JS_CALL_GC_AFTER_NUM)
00227 {
00228 JS_MaybeGC(cx);
00229 gc_counter = 0;
00230 }
00231
00232 #ifdef JS_THREADSAFE
00233 JS_EndRequest(cx);
00234 JS_ClearContextThread(cx);
00235 #endif
00236
00237 }
00238
00239
00240 PlaylistParserScript::~PlaylistParserScript()
00241 {
00242 #ifdef JS_THREADSAFE
00243 JS_SetContextThread(cx);
00244 JS_BeginRequest(cx);
00245 #endif
00246
00247 if (root)
00248 JS_RemoveRoot(cx, &root);
00249
00250 #ifdef JS_THREADSAFE
00251 JS_EndRequest(cx);
00252 JS_ClearContextThread(cx);
00253 #endif
00254
00255 }
00256 #endif // HAVE_JS