AVSValueStruct CAsifScriptEnvironment::Invoke(const char* command) { AVSValueStruct ir; ir.arraysize = 0; ir.errors = false; ir.returnvalue.ival = 0; ir.type = 0; std::vector<const char *> tempargnames(args.size()); for (size_t i = 0; i < tempargnames.size(); i++) tempargnames[i] = (argnames[i].c_str() == "" ? nullptr : argnames[i].c_str()); try { AVSValue ret = envse->Invoke(command, AVSValue(args.data(), args.size()), tempargnames.data()); if (ret.IsClip()) { ir.returnvalue.cval = new CAsifClip(ret.AsClip(), envse); ir.type = 1; } else if (ret.IsBool()) { ir.returnvalue.bval = ret.AsBool(); ir.type = 2; } else if (ret.IsInt()) { ir.returnvalue.ival = ret.AsInt(); ir.type = 3; } else if (ret.IsFloat()) { ir.returnvalue.fval = (float)ret.AsFloat(); ir.type = 4; } else if (ret.IsString()) { ir.returnvalue.sval = ret.AsString(); ir.type = 5; } else if (ret.IsArray()) { // ir.returnvalue.aval=ret. ir.arraysize = ret.ArraySize(); ir.type = 6; } } catch (AvisynthError &e) { ir.type = 100; ir.returnvalue.sval = e.msg; ir.errors = 1; } ResetArgs(); return ir; }
PVideoFrame __stdcall ScriptClip::GetFrame(int n, IScriptEnvironment* env) { AVSValue prev_last = env->GetVarDef("last"); // Store previous last AVSValue prev_current_frame = env->GetVarDef("current_frame"); // Store previous current_frame env->SetVar("last",(AVSValue)child); // Set explicit last env->SetVar("current_frame",(AVSValue)n); // Set frame to be tested by the conditional filters. if (show) { PVideoFrame dst = child->GetFrame(n,env); env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, script.AsString(), vi.width/6, 0xa0a0a0, 0, 0); env->SetVar("last",prev_last); // Restore implicit last env->SetVar("current_frame",prev_current_frame); // Restore current_frame return dst; } AVSValue result; PVideoFrame eval_return; // Frame to be returned if script should be evaluated AFTER frame has been fetched. Otherwise not used. if (eval_after) eval_return = child->GetFrame(n,env); try { ScriptParser parser(env, script.AsString(), "[ScriptClip]"); PExpression exp = parser.Parse(); result = exp->Evaluate(env); } catch (AvisynthError error) { const char* error_msg = error.msg; PVideoFrame dst = child->GetFrame(n,env); env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, error_msg, vi.width/W_DIVISOR, 0xa0a0a0, 0, 0); env->SetVar("last",prev_last); // Restore implicit last env->SetVar("current_frame",prev_current_frame); // Restore current_frame return dst; } env->SetVar("last",prev_last); // Restore implicit last env->SetVar("current_frame",prev_current_frame); // Restore current_frame if (eval_after && only_eval) return eval_return; if (only_eval) return child->GetFrame(n,env); const char* error = NULL; VideoInfo vi2 = vi; if (!result.IsClip()) { if (result.IsBool()) error = "ScriptClip: Function did not return a video clip! (Was a bool)"; else if (result.IsInt()) error = "ScriptClip: Function did not return a video clip! (Was an int)"; else if (result.IsFloat()) error = "ScriptClip: Function did not return a video clip! (Was a float)"; else if (result.IsString()) error = "ScriptClip: Function did not return a video clip! (Was a string)"; else if (result.IsArray()) error = "ScriptClip: Function did not return a video clip! (Was an array)"; else if (!result.Defined()) error = "ScriptClip: Function did not return a video clip! (Was the undefined value)"; else error = "ScriptClip: Function did not return a video clip! (type is unknown)"; } else { vi2 = result.AsClip()->GetVideoInfo(); if (!vi.IsSameColorspace(vi2)) { error = "ScriptClip: Function did not return a video clip of the same colorspace as the source clip!"; } else if (vi2.width != vi.width) { error = "ScriptClip: Function did not return a video clip with the same width as the source clip!"; } else if (vi2.height != vi.height) { error = "ScriptClip: Function did not return a video clip with the same height as the source clip!"; } } if (error != NULL) { PVideoFrame dst = child->GetFrame(n,env); env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, error, vi.width/W_DIVISOR, 0xa0a0a0, 0, 0); return dst; } n = min(n,vi2.num_frames-1); // We ignore it if the new clip is not as long as the current one. This can allow the resulting clip to be one frame. return result.AsClip()->GetFrame(n,env); }