VDStringW VDGetLocalAppDataPath() { int csidl = CSIDL_APPDATA; HMODULE hmodShell32 = VDLoadSystemLibraryW32("shell32"); if (hmodShell32) { typedef HRESULT (CALLBACK *tpDllGetVersion)(DLLVERSIONINFO *); DLLVERSIONINFO dvi = {sizeof(DLLVERSIONINFO)}; tpDllGetVersion pDllGetVersion = (tpDllGetVersion)GetProcAddress(hmodShell32, "DllGetVersion"); if (pDllGetVersion && NOERROR == pDllGetVersion(&dvi)) { if (dvi.dwMajorVersion >= 5) csidl = CSIDL_LOCAL_APPDATA; } FreeLibrary(hmodShell32); } if (VDIsWindowsNT()) { wchar_t pathW[MAX_PATH]; if (!SHGetSpecialFolderPathW(NULL, pathW, csidl, FALSE)) return VDGetProgramPath(); return VDStringW(pathW); } else { char pathA[MAX_PATH]; if (!SHGetSpecialFolderPathA(NULL, pathA, csidl, FALSE)) return VDGetProgramPath(); return VDTextAToW(pathA); } }
void JobAddConfiguration(const DubOptions *opt, const wchar_t *szFileInput, const wchar_t *pszInputDriver, const wchar_t *szFileOutput, bool fCompatibility, List2<InputFilenameNode> *pListAppended, long lSpillThreshold, long lSpillFrameThreshold, bool bIncludeEditList) { JobScriptOutput output; JobAddConfigurationInputs(output, szFileInput, pszInputDriver, pListAppended); JobCreateScript(output, opt, bIncludeEditList); JobAddReloadMarker(output); // Add actual run option if (lSpillThreshold) output.addf("VirtualDub.SaveSegmentedAVI(\"%s\", %d, %d);", strCify(VDTextWToU8(VDStringW(szFileOutput)).c_str()), lSpillThreshold, lSpillFrameThreshold); else output.addf("VirtualDub.Save%sAVI(\"%s\");", fCompatibility ? "Compatible" : "", strCify(VDTextWToU8(VDStringW(szFileOutput)).c_str())); JobAddClose(output); /////////////////// vdautoptr<VDJob> vdj(new VDJob); vdj->SetInputFile(szFileInput); vdj->SetOutputFile(szFileOutput); const JobScriptOutput::Script& script = output.getscript(); vdj->SetScript(script.data(), script.size(), true); g_VDJobQueue.Add(vdj.release(), false); }
void JobAddConfigurationImages(const DubOptions *opt, const wchar_t *szFileInput, const wchar_t *pszInputDriver, const wchar_t *szFilePrefix, const wchar_t *szFileSuffix, int minDigits, int imageFormat, int quality, List2<InputFilenameNode> *pListAppended) { JobScriptOutput output; JobAddConfigurationInputs(output, szFileInput, pszInputDriver, pListAppended); JobCreateScript(output, opt); JobAddReloadMarker(output); // Add actual run option VDStringA s(strCify(VDTextWToU8(VDStringW(szFilePrefix)).c_str())); output.addf("VirtualDub.SaveImageSequence(\"%s\", \"%s\", %d, %d, %d);", s.c_str(), strCify(VDTextWToU8(VDStringW(szFileSuffix)).c_str()), minDigits, imageFormat, quality); JobAddClose(output); /////////////////// vdautoptr<VDJob> vdj(new VDJob); vdj->SetInputFile(szFileInput); VDStringW outputFile; outputFile.sprintf(L"%ls*%ls", szFilePrefix, szFileSuffix); vdj->SetOutputFile(outputFile.c_str()); const JobScriptOutput::Script& script = output.getscript(); vdj->SetScript(script.data(), script.size(), true); g_VDJobQueue.Add(vdj.release(), false); }
void VDRegistryProviderMemory::Value::SetBinary(const void *p, size_t len) { if (mType != kTypeBinary) { mString.swap(VDStringW()); mType = kTypeBinary; } mRawData.assign((char *)p, (char *)p + len); }
VDStringW VDGetSystemPathNT() { wchar_t path[MAX_PATH]; if (!GetSystemDirectoryW(path, MAX_PATH)) throw MyWin32Error("Cannot locate system directory: %%s", GetLastError()); return VDStringW(path); }
void VDRegistryProviderMemory::Value::SetInt(sint32 v) { if (mType != kTypeInt) { mString.swap(VDStringW()); mRawData.swap(vdfastvector<char>()); mType = kTypeInt; } mInt = v; }
VDStringW VDFileGetRelativePath(const wchar_t *basePath, const wchar_t *pathToConvert, bool allowAscent) { VDParsedPath base(basePath); VDParsedPath path(pathToConvert); // Fail if either path is relative. if (base.IsRelative() || path.IsRelative()) return VDStringW(); // Fail if the roots don't match. if (vdwcsicmp(base.GetRoot(), path.GetRoot())) return VDStringW(); // Figure out how many components are in common. size_t n1 = base.GetComponentCount(); size_t n2 = path.GetComponentCount(); size_t nc = 0; while(nc < n1 && nc < n2 && !vdwcsicmp(base.GetComponent(nc), path.GetComponent(nc))) ++nc; // Check how many extra components are in the base; these need to become .. identifiers. VDParsedPath relPath; if (n1 > nc) { if (!allowAscent) return VDStringW(); while(n1 > nc) { relPath.AddComponent(L".."); --n1; } } // Append extra components from path. while(nc < n2) { relPath.AddComponent(path.GetComponent(nc++)); } // Copy stream. relPath.SetStream(path.GetStream()); return relPath.ToString(); }
VDStringW VDGetFullPath(const wchar_t *partialPath) { static tpGetFullPathNameW spGetFullPathNameW = (tpGetFullPathNameW)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFullPathNameW"); union { char a[MAX_PATH]; wchar_t w[MAX_PATH]; } tmpBuf; if (spGetFullPathNameW && !(GetVersion() & 0x80000000)) { LPWSTR p; tmpBuf.w[0] = 0; DWORD count = spGetFullPathNameW(partialPath, MAX_PATH, tmpBuf.w, &p); if (count < MAX_PATH) return VDStringW(tmpBuf.w); VDStringW tmp(count); DWORD newCount = spGetFullPathNameW(partialPath, count, (wchar_t *)tmp.data(), &p); if (newCount < count) return tmp; return VDStringW(partialPath); } else { LPSTR p; VDStringA pathA(VDTextWToA(partialPath)); tmpBuf.a[0] = 0; DWORD count = GetFullPathNameA(pathA.c_str(), MAX_PATH, tmpBuf.a, &p); if (count < MAX_PATH) return VDStringW(VDTextAToW(tmpBuf.a)); VDStringA tmpA(count); DWORD newCount = GetFullPathNameA(pathA.c_str(), count, (char *)tmpA.data(), &p); if (newCount < count) return VDTextAToW(tmpA); return VDStringW(partialPath); } }
void VDShowHelp(HWND hwnd, const wchar_t *filename) { try { VDStringW helpFile(VDGetHelpPath()); if (!VDDoesPathExist(helpFile.c_str())) throw MyError("Cannot find help file: %ls", helpFile.c_str()); // If we're on Windows NT, check for the ADS and/or network drive. if (VDIsWindowsNT()) { VDStringW helpFileADS(helpFile); helpFileADS += L":Zone.Identifier"; if (VDDoesPathExist(helpFileADS.c_str())) { int rv = MessageBox(hwnd, "VirtualDub has detected that its help file, VirtualDub.chm, has an Internet Explorer download location marker on it. This may prevent the help file from being displayed properly, resulting in \"Action canceled\" errors being displayed. Would you like to remove it?", "VirtualDub warning", MB_YESNO|MB_ICONEXCLAMATION); if (rv == IDYES) DeleteFileW(helpFileADS.c_str()); } } if (filename) { helpFile.append(L"::/"); helpFile.append(filename); } VDStringW helpCommand(VDStringW(L"\"hh.exe\" \"") + helpFile + L'"'); PROCESS_INFORMATION pi; BOOL retval; // CreateProcess will actually modify the string that it gets, soo.... if (VDIsWindowsNT()) { STARTUPINFOW si = {sizeof(STARTUPINFOW)}; std::vector<wchar_t> tempbufW(helpCommand.size() + 1, 0); helpCommand.copy(&tempbufW[0], tempbufW.size()); retval = CreateProcessW(NULL, &tempbufW[0], NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi); } else { STARTUPINFOA si = {sizeof(STARTUPINFOA)}; VDStringA strA(VDTextWToA(helpCommand)); std::vector<char> tempbufA(strA.size() + 1, 0); strA.copy(&tempbufA[0], tempbufA.size()); retval = CreateProcessA(NULL, &tempbufA[0], NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi); } if (retval) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } else throw MyWin32Error("Cannot launch HTML Help: %%s", GetLastError()); } catch(const MyError& e) { e.post(hwnd, g_szError); } }
void JobAddConfigurationInputs(JobScriptOutput& output, const wchar_t *szFileInput, const wchar_t *pszInputDriver, List2<InputFilenameNode> *pListAppended) { do { const VDStringA filename(strCify(VDTextWToU8(VDStringW(szFileInput)).c_str())); if (g_pInputOpts) { int req = g_pInputOpts->write(NULL, 0); vdfastvector<char> srcbuf(req); int srcsize = g_pInputOpts->write(srcbuf.data(), req); if (srcsize) { vdfastvector<char> encbuf((srcsize + 2) / 3 * 4 + 1); membase64(encbuf.data(), srcbuf.data(), srcsize); const VDStringA filename(strCify(VDTextWToU8(VDStringW(szFileInput)).c_str())); output.addf("VirtualDub.Open(\"%s\",\"%s\",0,\"%s\");", filename.c_str(), pszInputDriver?strCify(VDTextWToU8(VDStringW(pszInputDriver)).c_str()):"", encbuf.data()); break; } } output.addf("VirtualDub.Open(\"%s\",\"%s\",0);", filename.c_str(), pszInputDriver?strCify(VDTextWToU8(VDStringW(pszInputDriver)).c_str()):""); } while(false); if (pListAppended) { InputFilenameNode *ifn = pListAppended->AtHead(), *ifn_next; if (ifn = ifn->NextFromHead()) while(ifn_next = ifn->NextFromHead()) { output.addf("VirtualDub.Append(\"%s\");", strCify(VDTextWToU8(VDStringW(ifn->name)).c_str())); ifn = ifn_next; } } }
VDStringW VDMakePath(const wchar_t *base, const wchar_t *file) { if (!*base) return VDStringW(file); VDStringW result(base); const wchar_t c = result[result.size() - 1]; if (c != L'/' && c != L'\\' && c != L':') result += L'\\'; result.append(file); return result; }
VDStringW VDFileGetRootPath(const wchar_t *path) { static tpGetVolumePathNameW spGetVolumePathNameW = (tpGetVolumePathNameW)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetVolumePathNameW"); static tpGetFullPathNameW spGetFullPathNameW = (tpGetFullPathNameW)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFullPathNameW"); VDStringW fullPath(VDGetFullPath(path)); // Windows 2000/XP path if (spGetVolumePathNameW) { vdblock<wchar_t> buf(std::max<size_t>(fullPath.size() + 1, MAX_PATH)); if (spGetVolumePathNameW(path, buf.data(), buf.size())) return VDStringW(buf.data()); } // Windows 95/98/ME/NT4 path const wchar_t *s = fullPath.c_str(); VDStringW root(s, VDFileSplitRoot(s) - s); VDFileFixDirPath(root); return root; }
VDStringW VDGetWindowTextW32(HWND hwnd) { union { wchar_t w[256]; char a[512]; } buf; if (VDIsWindowsNT()) { int len = GetWindowTextLengthW(hwnd); if (len > 255) { vdblock<wchar_t> tmp(len + 1); len = GetWindowTextW(hwnd, tmp.data(), tmp.size()); VDStringW text(tmp.data(), len); return text; } else if (len > 0) { len = GetWindowTextW(hwnd, buf.w, 256); VDStringW text(buf.w, len); return text; } } else { int len = GetWindowTextLengthA(hwnd); if (len > 511) { vdblock<char> tmp(len + 1); len = GetWindowTextA(hwnd, tmp.data(), tmp.size()); VDStringW text(VDTextAToW(tmp.data(), len)); return text; } else if (len > 0) { len = GetWindowTextA(hwnd, buf.a, 512); VDStringW text(VDTextAToW(buf.a, len)); return text; } } return VDStringW(); }
void VDRemoveDirectory(const wchar_t *path) { VDStringW::size_type l(wcslen(path)); if (l) { const wchar_t c = path[l-1]; if (c == L'/' || c == L'\\') { VDCreateDirectory(VDStringW(path, l-1).c_str()); return; } } BOOL succeeded; if (!(GetVersion() & 0x80000000)) { succeeded = RemoveDirectoryW(path); } else { succeeded = RemoveDirectoryA(VDTextWToA(path).c_str()); } if (!succeeded) throw MyWin32Error("Cannot remove directory: %%s", GetLastError()); }
void JobAddConfigurationSaveAudio(const DubOptions *opt, const wchar_t *srcFile, const wchar_t *srcInputDriver, List2<InputFilenameNode> *pListAppended, const wchar_t *dstFile, bool raw, bool includeEditList) { JobScriptOutput output; JobAddConfigurationInputs(output, srcFile, srcInputDriver, pListAppended); JobCreateScript(output, opt, includeEditList); JobAddReloadMarker(output); // Add actual run option output.addf("VirtualDub.Save%s(\"%s\");", raw ? "RawAudio" : "WAV", strCify(VDTextWToU8(VDStringW(dstFile)).c_str())); JobAddClose(output); /////////////////// vdautoptr<VDJob> vdj(new VDJob); vdj->SetInputFile(srcFile); vdj->SetOutputFile(dstFile); const JobScriptOutput::Script& script = output.getscript(); vdj->SetScript(script.data(), script.size(), true); g_VDJobQueue.Add(vdj.release(), false); }
VDStringW VDFileResolvePath(const wchar_t *basePath, const wchar_t *pathToResolve) { if (VDFileIsRelativePath(pathToResolve)) return VDFileGetCanonicalPath(VDMakePath(basePath, pathToResolve).c_str()); return VDStringW(pathToResolve); }
void JobCreateScript(JobScriptOutput& output, const DubOptions *opt, bool bIncludeEditList = true, bool bIncludeTextInfo = true) { char *mem= NULL; char buf[4096]; long l; int audioSourceMode = g_project->GetAudioSourceMode(); switch(audioSourceMode) { case kVDAudioSourceMode_External: { const VDStringA& encodedFileName = VDEncodeScriptString(VDStringW(g_szInputWAVFile)); const VDStringA& encodedDriverName = VDEncodeScriptString(VDTextWToU8(g_project->GetAudioSourceDriverName(), -1)); // check if we have options to write out const InputFileOptions *opts = g_project->GetAudioSourceOptions(); if (opts) { int l; char buf[256]; l = opts->write(buf, (sizeof buf)/7*3); if (l) { membase64(buf+l, (char *)buf, l); output.addf("VirtualDub.audio.SetSource(\"%s\", \"%s\", \"%s\");", encodedFileName.c_str(), encodedDriverName.c_str(), buf+l); break; } } // no options output.addf("VirtualDub.audio.SetSource(\"%s\", \"%s\");", encodedFileName.c_str(), encodedDriverName.c_str()); } break; default: if (audioSourceMode >= kVDAudioSourceMode_Source) { int index = audioSourceMode - kVDAudioSourceMode_Source; if (!index) output.addf("VirtualDub.audio.SetSource(1);"); else output.addf("VirtualDub.audio.SetSource(1,%d);", index); break; } // fall through case kVDAudioSourceMode_None: output.addf("VirtualDub.audio.SetSource(0);"); break; } output.addf("VirtualDub.audio.SetMode(%d);", opt->audio.mode); output.addf("VirtualDub.audio.SetInterleave(%d,%d,%d,%d,%d);", opt->audio.enabled, opt->audio.preload, opt->audio.interval, opt->audio.is_ms, opt->audio.offset); output.addf("VirtualDub.audio.SetClipMode(%d,%d);", opt->audio.fStartAudio, opt->audio.fEndAudio); output.addf("VirtualDub.audio.SetConversion(%d,%d,%d,0,%d);", opt->audio.new_rate, opt->audio.newPrecision, opt->audio.newChannels, opt->audio.fHighQuality); if (opt->audio.mVolume >= 0.0f) output.addf("VirtualDub.audio.SetVolume(%d);", VDRoundToInt(256.0f * opt->audio.mVolume)); else output.addf("VirtualDub.audio.SetVolume();"); if (g_ACompressionFormat) { if (g_ACompressionFormat->mExtraSize) { mem = (char *)allocmem(((g_ACompressionFormat->mExtraSize+2)/3)*4 + 1); if (!mem) throw MyMemoryError(); membase64(mem, (char *)(g_ACompressionFormat+1), g_ACompressionFormat->mExtraSize); output.addf("VirtualDub.audio.SetCompressionWithHint(%d,%d,%d,%d,%d,%d,%d,\"%s\",\"%s\");" ,g_ACompressionFormat->mTag ,g_ACompressionFormat->mSamplingRate ,g_ACompressionFormat->mChannels ,g_ACompressionFormat->mSampleBits ,g_ACompressionFormat->mDataRate ,g_ACompressionFormat->mBlockSize ,g_ACompressionFormat->mExtraSize ,mem ,VDEncodeScriptString(g_ACompressionFormatHint).c_str() ); freemem(mem); } else output.addf("VirtualDub.audio.SetCompressionWithHint(%d,%d,%d,%d,%d,%d,\"%s\");" ,g_ACompressionFormat->mTag ,g_ACompressionFormat->mSamplingRate ,g_ACompressionFormat->mChannels ,g_ACompressionFormat->mSampleBits ,g_ACompressionFormat->mDataRate ,g_ACompressionFormat->mBlockSize ,VDEncodeScriptString(g_ACompressionFormatHint).c_str() ); } else output.addf("VirtualDub.audio.SetCompression();"); output.addf("VirtualDub.audio.EnableFilterGraph(%d);", opt->audio.bUseAudioFilterGraph); output.addf("VirtualDub.video.SetInputFormat(%d);", opt->video.mInputFormat); output.addf("VirtualDub.video.SetOutputFormat(%d);", opt->video.mOutputFormat); output.addf("VirtualDub.video.SetMode(%d);", opt->video.mode); output.addf("VirtualDub.video.SetSmartRendering(%d);", opt->video.mbUseSmartRendering); output.addf("VirtualDub.video.SetPreserveEmptyFrames(%d);", opt->video.mbPreserveEmptyFrames); output.addf("VirtualDub.video.SetFrameRate2(%u,%u,%d);", opt->video.mFrameRateAdjustHi, opt->video.mFrameRateAdjustLo, opt->video.frameRateDecimation); if (opt->video.frameRateTargetLo) { output.addf("VirtualDub.video.SetTargetFrameRate(%u,%u);", opt->video.frameRateTargetHi, opt->video.frameRateTargetLo); } output.addf("VirtualDub.video.SetIVTC(0, 0, 0, 0);"); if ((g_Vcompression.dwFlags & ICMF_COMPVARS_VALID) && g_Vcompression.fccHandler) { output.addf("VirtualDub.video.SetCompression(0x%08lx,%d,%d,%d);", g_Vcompression.fccHandler, g_Vcompression.lKey, g_Vcompression.lQ, g_Vcompression.lDataRate); l = ICGetStateSize(g_Vcompression.hic); if (l>0) { mem = (char *)allocmem(l + ((l+2)/3)*4 + 1); if (!mem) throw MyMemoryError(); if (ICGetState(g_Vcompression.hic, mem, l)<0) { freemem(mem); // throw MyError("Bad state data returned from compressor"); // Fine then, be that way. Stupid Pinnacle DV200 driver. mem = NULL; } if (mem) { membase64(mem+l, mem, l); // urk... Windows Media 9 VCM uses a very large configuration struct (~7K pre-BASE64). sprintf(buf, "VirtualDub.video.SetCompData(%d,\"", l); VDStringA line(buf); line += (mem+l); line += "\");"; output.adds(line.c_str()); freemem(mem); } } } else output.addf("VirtualDub.video.SetCompression();"); output.addf("VirtualDub.video.filters.Clear();"); // Add video filters FilterInstance *fa = (FilterInstance *)g_listFA.tail.next, *fa_next; int iFilter = 0; while(fa_next = (FilterInstance *)fa->next) { output.addf("VirtualDub.video.filters.Add(\"%s\");", strCify(fa->GetName())); if (fa->IsCroppingEnabled()) { const vdrect32& cropInsets = fa->GetCropInsets(); output.addf("VirtualDub.video.filters.instance[%d].SetClipping(%d,%d,%d,%d%s);" , iFilter , cropInsets.left , cropInsets.top , cropInsets.right , cropInsets.bottom , fa->IsPreciseCroppingEnabled() ? "" : ",0" ); } VDStringA scriptStr; if (fa->GetScriptString(scriptStr)) output.addf("VirtualDub.video.filters.instance[%d].%s;", iFilter, scriptStr.c_str()); if (!fa->IsEnabled()) output.addf("VirtualDub.video.filters.instance[%d].SetEnabled(false);", iFilter); VDParameterCurve *pc = fa->GetAlphaParameterCurve(); if (pc) { output.addf("declare curve = VirtualDub.video.filters.instance[%d].AddOpacityCurve();", iFilter); const VDParameterCurve::PointList& pts = pc->Points(); for(VDParameterCurve::PointList::const_iterator it(pts.begin()), itEnd(pts.end()); it!=itEnd; ++it) { const VDParameterCurvePoint& pt = *it; output.addf("curve.AddPoint(%g, %g, %d);", pt.mX, pt.mY, pt.mbLinear); } } ++iFilter; fa = fa_next; } // Add audio filters { VDAudioFilterGraph::FilterList::const_iterator it(g_audioFilterGraph.mFilters.begin()), itEnd(g_audioFilterGraph.mFilters.end()); int connidx = 0; int srcfilt = 0; output.addf("VirtualDub.audio.filters.Clear();"); for(; it!=itEnd; ++it, ++srcfilt) { const VDAudioFilterGraph::FilterEntry& fe = *it; output.addf("VirtualDub.audio.filters.Add(\"%s\");", strCify(VDTextWToU8(fe.mFilterName).c_str())); for(unsigned i=0; i<fe.mInputPins; ++i) { const VDAudioFilterGraph::FilterConnection& conn = g_audioFilterGraph.mConnections[connidx++]; output.addf("VirtualDub.audio.filters.Connect(%d, %d, %d, %d);", conn.filt, conn.pin, srcfilt, i); } VDPluginConfig::const_iterator itc(fe.mConfig.begin()), itcEnd(fe.mConfig.end()); for(; itc!=itcEnd; ++itc) { const unsigned idx = (*itc).first; const VDPluginConfigVariant& var = (*itc).second; switch(var.GetType()) { case VDPluginConfigVariant::kTypeU32: output.addf("VirtualDub.audio.filters.instance[%d].SetInt(%d, %d);", srcfilt, idx, var.GetU32()); break; case VDPluginConfigVariant::kTypeS32: output.addf("VirtualDub.audio.filters.instance[%d].SetInt(%d, %d);", srcfilt, idx, var.GetS32()); break; case VDPluginConfigVariant::kTypeU64: output.addf("VirtualDub.audio.filters.instance[%d].SetLong(%d, %I64d);", srcfilt, idx, var.GetU64()); break; case VDPluginConfigVariant::kTypeS64: output.addf("VirtualDub.audio.filters.instance[%d].SetLong(%d, %I64d);", srcfilt, idx, var.GetS64()); break; case VDPluginConfigVariant::kTypeDouble: output.addf("VirtualDub.audio.filters.instance[%d].SetDouble(%d, %g);", srcfilt, idx, var.GetDouble()); break; case VDPluginConfigVariant::kTypeAStr: output.addf("VirtualDub.audio.filters.instance[%d].SetString(%d, \"%s\");", srcfilt, idx, strCify(VDTextWToU8(VDTextAToW(var.GetAStr())).c_str())); break; case VDPluginConfigVariant::kTypeWStr: output.addf("VirtualDub.audio.filters.instance[%d].SetString(%d, \"%s\");", srcfilt, idx, strCify(VDTextWToU8(var.GetWStr(), -1).c_str())); break; case VDPluginConfigVariant::kTypeBlock: output.addf("VirtualDub.audio.filters.instance[%d].SetBlock(%d, %d, \"%s\");", srcfilt, idx, var.GetBlockLen(), VDEncodeBase64A(var.GetBlockPtr(), var.GetBlockLen()).c_str()); break; } } } } // Add subset information if (bIncludeEditList) { const FrameSubset& fs = g_project->GetTimeline().GetSubset(); output.addf("VirtualDub.subset.Clear();"); for(FrameSubset::const_iterator it(fs.begin()), itEnd(fs.end()); it!=itEnd; ++it) output.addf("VirtualDub.subset.Add%sRange(%I64d,%I64d);", it->bMask ? "Masked" : "", it->start, it->len); // Note that this must be AFTER the subset (we used to place it before, which was a bug). if (g_project->IsSelectionPresent()) { output.addf("VirtualDub.video.SetRangeFrames(%I64d,%I64d);", g_project->GetSelectionStartFrame(), g_project->GetSelectionEndFrame()); } else { output.addf("VirtualDub.video.SetRange();"); } } // Add text information if (bIncludeTextInfo) { typedef std::list<std::pair<uint32, VDStringA> > tTextInfo; const tTextInfo& textInfo = g_project->GetTextInfo(); output.addf("VirtualDub.project.ClearTextInfo();"); for(tTextInfo::const_iterator it(textInfo.begin()), itEnd(textInfo.end()); it!=itEnd; ++it) { char buf[5]={0}; memcpy(buf, &(*it).first, 4); output.addf("VirtualDub.project.AddTextInfo(\"%s\", \"%s\");", buf, VDEncodeScriptString((*it).second).c_str()); } } }