AVSValue ExpMult::Evaluate(IScriptEnvironment* env) { AVSValue x = a->Evaluate(env); AVSValue y = b->Evaluate(env); if (x.IsInt() && y.IsInt()) return x.AsInt() * y.AsInt(); else if (x.IsFloat() && y.IsFloat()) return x.AsFloat() * y.AsFloat(); else { env->ThrowError("Evaluate: operands of `*' must be numeric"); return 0; } }
AVSValue ExpMod::Evaluate(IScriptEnvironment* env) { AVSValue x = a->Evaluate(env); AVSValue y = b->Evaluate(env); if (x.IsInt() && y.IsInt()) { if (y.AsInt() == 0) env->ThrowError("Evaluate: division by zero"); return x.AsInt() % y.AsInt(); } else { env->ThrowError("Evaluate: operands of `%%' must be integers"); return 0; } }
AVSValue ExpDiv::Evaluate(IScriptEnvironment* env) { AVSValue x = a->Evaluate(env); AVSValue y = b->Evaluate(env); if (x.IsInt() && y.IsInt()) { if (y.AsInt() == 0) env->ThrowError("Evaluate: division by zero"); return x.AsInt() / y.AsInt(); } else if (x.IsFloat() && y.IsFloat()) return x.AsFloat() / y.AsFloat(); else { env->ThrowError("Evaluate: operands of `/' must be numeric"); return 0; } }
int __stdcall dimzon_avs_getvariable_i(SafeStruct* pstr, const char* name, int* result) { try { pstr->err[0] = 0; try { AVSValue var = pstr->env->GetVar(name); if(var.Defined()) { if(!var.IsInt()) { strncpy_s(pstr->err, ERRMSG_LEN, "AviSynthWrapper: Requested variable is not Integer!", _TRUNCATE); return AVS_VARWRNGTYPE; } *result = var.AsInt(); return 0; } return AVS_VARNDEFINED; } catch(AvisynthError err) { strncpy_s(pstr->err, ERRMSG_LEN, err.msg, _TRUNCATE); return AVS_GERROR; } } catch(IScriptEnvironment::NotFound) { return AVS_VARNFOUND; } }
AVSValue ExpForLoop::Evaluate(IScriptEnvironment* env) { const AVSValue initVal = init->Evaluate(env), limitVal = limit->Evaluate(env), stepVal = step->Evaluate(env); if (!initVal.IsInt()) env->ThrowError("for: initial value must be int"); if (!limitVal.IsInt()) env->ThrowError("for: final value must be int"); if (!stepVal.IsInt()) env->ThrowError("for: step value must be int"); if (stepVal.AsInt() == 0) env->ThrowError("for: step value must be non-zero"); const int iLimit = limitVal.AsInt(), iStep = stepVal.AsInt(); int i = initVal.AsInt(); AVSValue result; IScriptEnvironment2 *env2 = static_cast<IScriptEnvironment2*>(env); env2->GetVar("last", &result); env->SetVar(id, initVal); while (iStep > 0 ? i <= iLimit : i >= iLimit) { if (body) { try { result = body->Evaluate(env); if (result.IsClip()) env->SetVar("last", result); } catch(const BreakStmtException&) { break; } } AVSValue idVal = env->GetVar(id); // may have been updated in body if (!idVal.IsInt()) env->ThrowError("for: loop variable '%s' has been assigned a non-int value", id); i = idVal.AsInt() + iStep; env->SetVar(id, i); } return result; // overall result is that of final body evaluation (if any) }
PVideoFrame __stdcall ConditionalSelect::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 implicit last env->SetVar("current_frame", (AVSValue)n); // Set frame to be tested by the conditional filters. AVSValue result; try { ScriptParser parser(env, expression, "[Conditional Select, Expression]"); PExpression exp = parser.Parse(); result = exp->Evaluate(env); if (!result.IsInt()) env->ThrowError("Conditional Select: Expression must return an integer!"); } catch (AvisynthError error) { env->SetVar("last", prev_last); // Restore implicit last env->SetVar("current_frame", prev_current_frame); // Restore current_frame const int num_frames = child->GetVideoInfo().num_frames; PVideoFrame dst = child->GetFrame(min(num_frames-1, n), env); env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, error.msg, vi.width/W_DIVISOR, 0xa0a0a0, 0, 0); return dst; } env->SetVar("last", prev_last); // Restore implicit last env->SetVar("current_frame", prev_current_frame); // Restore current_frame const int i = result.AsInt(); PVideoFrame dst; if (i < 0 || i >= num_args) { const int num_frames = child->GetVideoInfo().num_frames; dst = child->GetFrame(min(num_frames-1, n), env); } else { const int num_frames = child_array[i]->GetVideoInfo().num_frames; dst = child_array[i]->GetFrame(min(num_frames-1, n), env); } if (show) { char text[32]; _snprintf(text, sizeof(text)-1, "Expression Result:%i\n", result.AsInt()); text[sizeof(text)-1] = '\0'; env->MakeWritable(&dst); env->ApplyMessage(&dst, vi, text, vi.width/4, 0xa0a0a0, 0, 0); } return dst; }
AVSValue ExpPlus::Evaluate(IScriptEnvironment* env) { AVSValue x = a->Evaluate(env); AVSValue y = b->Evaluate(env); if (x.IsClip() && y.IsClip()) return new_Splice(x.AsClip(), y.AsClip(), false, env); // UnalignedSplice else if (x.IsInt() && y.IsInt()) return x.AsInt() + y.AsInt(); else if (x.IsFloat() && y.IsFloat()) return x.AsFloat() + y.AsFloat(); else if (x.IsString() && y.IsString()) return env->Sprintf("%s%s", x.AsString(), y.AsString()); else { env->ThrowError("Evaluate: operands of `+' must both be numbers, strings, or clips"); return 0; } }
AVSValue ExpLess::Evaluate(IScriptEnvironment* env) { AVSValue x = a->Evaluate(env); AVSValue y = b->Evaluate(env); if (x.IsInt() && y.IsInt()) { return x.AsInt() < y.AsInt(); } else if (x.IsFloat() && y.IsFloat()) { return x.AsFloat() < y.AsFloat(); } else if (x.IsString() && y.IsString()) { return _stricmp(x.AsString(),y.AsString()) < 0 ? true : false; } else { env->ThrowError("Evaluate: operands of `<' and friends must be string or numeric"); return 0; } }
AVSValue ExpNegate::Evaluate(IScriptEnvironment* env) { AVSValue x = e->Evaluate(env); if (x.IsInt()) return -x.AsInt(); else if (x.IsFloat()) return -x.AsFloat(); else { env->ThrowError("Evaluate: unary minus can only by used with numbers"); return 0; } }
AVSValue ExpEqual::Evaluate(IScriptEnvironment* env) { AVSValue x = a->Evaluate(env); AVSValue y = b->Evaluate(env); if (x.IsBool() && y.IsBool()) { return x.AsBool() == y.AsBool(); } else if (x.IsInt() && y.IsInt()) { return x.AsInt() == y.AsInt(); } else if (x.IsFloat() && y.IsFloat()) { return x.AsFloat() == y.AsFloat(); } else if (x.IsClip() && y.IsClip()) { return x.AsClip() == y.AsClip(); } else if (x.IsString() && y.IsString()) { return !lstrcmpi(x.AsString(), y.AsString()); } else { env->ThrowError("Evaluate: operands of `==' and `!=' must be comparable"); return 0; } }
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; }
static AVSValue __cdecl create_iscombed(AVSValue args, void*, ise_t* env) { enum { CLIP, CTHRESH, MTHRESH, MI, BLOCKX, BLOCKY, METRIC, OPT }; CombMask* cm = nullptr; try { AVSValue cf = env->GetVar("current_frame"); validate(!cf.IsInt(), "This filter can only be used within ConditionalFilter."); int n = cf.AsInt(); PClip clip = args[CLIP].AsClip(); int metric = args[METRIC].AsInt(0); int cth = args[CTHRESH].AsInt(metric == 0 ? 6 : 10); int mth = args[MTHRESH].AsInt(9); int mi = args[MI].AsInt(80); int blockx = args[BLOCKX].AsInt(16); int blocky = args[BLOCKY].AsInt(16); bool is_avsplus = env->FunctionExists("SetFilterMTMode"); arch_t arch = get_arch(args[OPT].AsInt(-1), is_avsplus); validate(mi < 0 || mi > 128, "MI must be between 0 and 128."); validate(blockx != 8 && blockx != 16 && blockx != 32, "blockx must be set to 8, 16 or 32."); validate(blocky != 8 && blocky != 16 && blocky != 32, "blocky must be set to 8, 16 or 32."); cm = new CombMask(clip, cth, mth, false, arch, false, metric, is_avsplus); bool is_combed = (get_check_combed(arch))( cm->GetFrame(n, env), mi, blockx, blocky, is_avsplus, env); delete cm; return AVSValue(is_combed); } catch (std::runtime_error& e) { if (cm) delete cm; env->ThrowError("IsCombed: %s", e.what()); } return 0; }
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); }
int __stdcall dimzon_avs_invoke(SafeStruct* pstr, char *func, char **arg, int len, AVSDLLVideoInfo *vi, float* func_out) { try { *func_out = -FLT_MAX; pstr->err[0] = 0; const int N = 10; int actual_len = 0; AVSValue args[N] = { }; if (len == 0) args[0] = 0; else if (len > N) len = N; for(int i = 0; i < len; i++) { if (strlen(arg[i]) > 0) { string lower = arg[i]; bool was_letters = false; bool was_digits = false; bool was_spaces = false; //Слишком длинные значения - точно текст for (unsigned int n = 0; n < lower.size() && lower.size() <= 10; n++) { lower[n] = tolower(lower[n]); if (!was_letters && isalpha(lower[n])) was_letters = true; if (!was_digits && isdigit(lower[n])) was_digits = true; if (!was_spaces && isspace(lower[n])) was_spaces = true; } if (i == 0 && was_letters && !was_digits && !was_spaces && lower.compare("last") == 0) { //Clip (last) if(!pstr->clp) throw AvisynthError("AviSynthWrapper: The \"last\" clip was requested, but it doesn't exist!"); args[actual_len] = pstr->clp; //pstr->res->AsClip(); actual_len += 1; //pstr->clp; pstr->res->AsClip(); //С обработкой после прошлых вызовов Invoke //pstr->env->GetVar("last").AsClip(); //"Чистый" выход скрипта } else if (was_letters && !was_digits && !was_spaces && lower.compare("true") == 0) { //Bool (true) args[actual_len] = true; actual_len += 1; } else if (was_letters && !was_digits && !was_spaces && lower.compare("false") == 0) { //Bool (false) args[actual_len] = false; actual_len += 1; } else if (!was_letters && was_digits && !was_spaces && lower.find(".") != string::npos) { //Float (double..) args[actual_len] = atof(arg[i]); actual_len += 1; } else if (!was_letters && was_digits && !was_spaces) { //Integer args[actual_len] = atoi(arg[i]); actual_len += 1; } else { //String args[actual_len] = arg[i]; actual_len += 1; } } } AVSValue res = pstr->env->Invoke(func, AVSValue(args, actual_len)); if (!res.IsClip()) { //Вывод результата if (res.IsBool()) { if(!res.AsBool()) *func_out = 0; else *func_out = FLT_MAX; } else if (res.IsInt()) *func_out = (float)res.AsInt(); else if (res.IsFloat()) *func_out = (float)res.AsFloat(); else if (res.IsString()) { *func_out = FLT_MAX; strncpy_s(pstr->err, ERRMSG_LEN, res.AsString(), _TRUNCATE); } } else { pstr->clp = res.AsClip(); VideoInfo inf = pstr->clp->GetVideoInfo(); if (vi != NULL) { vi->width = inf.width; vi->height = inf.height; vi->raten = inf.fps_numerator; vi->rated = inf.fps_denominator; vi->field_based = (inf.IsFieldBased()) ? 1 : 0; vi->first_field = (inf.IsTFF()) ? 1 : (inf.IsBFF()) ? 2 : 0; vi->num_frames = inf.num_frames; //Или не меняем? if (vi->pixel_type_orig == 0) vi->pixel_type_orig = inf.pixel_type; if (vi->sample_type_orig == 0) vi->sample_type_orig = inf.sample_type; vi->pixel_type = inf.pixel_type; vi->sample_type = inf.sample_type; vi->num_audio_samples = inf.num_audio_samples; vi->audio_samples_per_second = inf.audio_samples_per_second; vi->nchannels = inf.nchannels; } //Нужен ли нам вообще этот res?! if(pstr->res) delete pstr->res; pstr->res = new AVSValue(res); pstr->err[0] = 0; } return 0; } catch(AvisynthError err) { strncpy_s(pstr->err, ERRMSG_LEN, err.msg, _TRUNCATE); return AVS_GERROR; } catch(IScriptEnvironment::NotFound) { strncpy_s(pstr->err, ERRMSG_LEN, "AviSynthWrapper: Wrong function name or invalid parameters was passed to Invoke!", _TRUNCATE); return AVS_VARNFOUND } }