void VDFileAsync9x::Open(const wchar_t *pszFilename, uint32 count, uint32 bufferSize) { try { mFilename = VDTextWToA(pszFilename); const DWORD slowFlags = mbWriteThrough ? FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH : FILE_ATTRIBUTE_NORMAL; mhFileSlow = CreateFileA(mFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, slowFlags, NULL); if (mhFileSlow == INVALID_HANDLE_VALUE) throw MyWin32Error("Unable to open file \"%s\" for write: %%s", GetLastError(), mFilename.c_str()); if (mbUseFastMode) mhFileFast = CreateFileA(mFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL); mSectorSize = 4096; // guess for now... proper way would be GetVolumeMountPoint() followed by GetDiskFreeSpace(). mBlockSize = bufferSize; mBlockCount = count; mBuffer.Init(count * bufferSize); mState = kStateNormal; } catch(const MyError&) { Close(); throw; } ThreadStart(); }
void MRUList::load() { clear(); VDRegistryAppKey key(mpKeyName); if (!key.isReady()) return; VDStringA s; if (!key.getString("MRUList", s)) return; int nItems = std::min<int>(mMaxCount, s.length()); mKey.resize(mMaxCount, 0); for(int i=0; i<nItems; i++) { char name[2]={s[i], 0}; if (!name[0]) break; if (!key.getString(name, mFiles[i])) break; mKey[i] = (char)('a'+i); } }
void VDFileAsyncNT::Open(VDFileHandle h, uint32 count, uint32 bufferSize) { try { mFilename = "<anonymous pipe>"; HANDLE hProcess = GetCurrentProcess(); if (!DuplicateHandle(hProcess, h, hProcess, &mhFileSlow, 0, FALSE, DUPLICATE_SAME_ACCESS)) throw MyWin32Error("Unable to open file \"%s\" for write: %%s", GetLastError(), mFilename.c_str()); mSectorSize = 4096; // guess for now... proper way would be GetVolumeMountPoint() followed by GetDiskFreeSpace(). mBlockSize = bufferSize; mBlockCount = count; mBufferSize = mBlockSize * mBlockCount; mWriteOffset = 0; mBufferLevel = 0; mState = kStateNormal; if (mhFileFast != INVALID_HANDLE_VALUE) { mpBlocks = new VDFileAsyncNTBuffer[count]; mBuffer.resize(count * bufferSize); ThreadStart(); } } catch(const MyError&) { Close(); throw; } }
void VDFileAsyncNT::Open(const wchar_t *pszFilename, uint32 count, uint32 bufferSize) { try { mFilename = VDTextWToA(pszFilename); mhFileSlow = CreateFileW(pszFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (mhFileSlow == INVALID_HANDLE_VALUE) throw MyWin32Error("Unable to open file \"%s\" for write: %%s", GetLastError(), mFilename.c_str()); mhFileFast = CreateFileW(pszFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); if (mhFileFast == INVALID_HANDLE_VALUE) mhFileFast = CreateFileW(pszFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED, NULL); mSectorSize = 4096; // guess for now... proper way would be GetVolumeMountPoint() followed by GetDiskFreeSpace(). mBlockSize = bufferSize; mBlockCount = count; mBufferSize = mBlockSize * mBlockCount; mWriteOffset = 0; mBufferLevel = 0; mState = kStateNormal; if (mhFileFast != INVALID_HANDLE_VALUE) { mpBlocks = new VDFileAsyncNTBuffer[count]; mBuffer.resize(count * bufferSize); ThreadStart(); } } catch(const MyError&) { Close(); throw; } }
void VDFileAsyncNT::Write(sint64 pos, const void *p, uint32 bytes) { Seek(pos); DWORD dwActual; if (!WriteFile(mhFileSlow, p, bytes, &dwActual, NULL) || (mClientSlowPointer += dwActual),(dwActual != bytes)) throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str()); }
bool VDRegistryKey::getString(const char *pszName, VDStringA& str) const { DWORD type, s = sizeof(DWORD); if (!pHandle || RegQueryValueEx((HKEY)pHandle, pszName, 0, &type, NULL, &s) || type != REG_SZ) return false; str.resize(s); if (RegQueryValueEx((HKEY)pHandle, pszName, 0, NULL, (BYTE *)str.data(), &s)) return false; if (!s) str.clear(); else str.resize(strlen(str.c_str())); // Trim off pesky terminating NULLs. return true; }
void VDScriptInterpreter::ExecuteLine(const char *s) { int t; mErrorExtraToken.clear(); TokenBegin(s); while(t = Token()) { if (isExprFirstToken(t)) { TokenUnput(t); VDASSERT(mStack.empty()); ParseExpression(); VDASSERT(!mStack.empty()); VDScriptValue& val = mStack.back(); mStack.pop_back(); VDASSERT(mStack.empty()); if (Token() != ';') SCRIPT_ERROR(SEMICOLON_EXPECTED); } else if (t == TOK_DECLARE) { do { t = Token(); if (t != TOK_IDENT) SCRIPT_ERROR(IDENTIFIER_EXPECTED); VariableTableEntry *vte = vartbl.Declare(szIdent); t = Token(); if (t == '=') { ParseExpression(); VDASSERT(!mStack.empty()); vte->v = mStack.back(); mStack.pop_back(); t = Token(); } } while(t == ','); if (t != ';') SCRIPT_ERROR(SEMICOLON_EXPECTED); } else SCRIPT_ERROR(PARSE_ERROR); } VDASSERT(mStack.empty()); GC(); }
sint64 VDFileAsyncNT::GetSize() { DWORD dwSizeHigh; DWORD dwSizeLow = GetFileSize(mhFileSlow, &dwSizeHigh); if (dwSizeLow == (DWORD)-1 && GetLastError() != NO_ERROR) throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str()); return dwSizeLow + ((sint64)dwSizeHigh << 32); }
VDStringA VDJob::ToString() const { VDStringA s; static const char *const kStateNames[]={ "Waiting", "In progress", "Completed", "Postponed", "Aborted", "Error", "Aborting", "Starting", }; VDASSERTCT(sizeof(kStateNames) / sizeof(kStateNames[0]) == kStateCount); s.sprintf("%s | %s | %-11s (%s:%d)", mInputFile.c_str(), mOutputFile.c_str(), kStateNames[mState], mRunnerName.c_str(), (uint32)mRunnerId); return s; }
void VDVideoFilterShowInfo::Run() { const VDXFBitmap& dst = *fa->mpOutputFrames[0]; const VDXPixmap& pxdst = *dst.mpPixmap; const float size = 8.0f * 8.0f * 20.0f; VDPixmap pxdst2; pxdst2.data = pxdst.data; pxdst2.data2 = pxdst.data2; pxdst2.data3 = pxdst.data3; pxdst2.pitch = pxdst.pitch; pxdst2.pitch2 = pxdst.pitch2; pxdst2.pitch3 = pxdst.pitch3; pxdst2.format = pxdst.format; pxdst2.w = pxdst.w; pxdst2.h = pxdst.h; pxdst2.palette = pxdst.palette; float y = 20.0f; for(int lines=0; lines<3; ++lines) { switch(lines) { case 0: mTextLine.sprintf("Source frame: %d (%.3fs)", (int)fa->pfsi->lCurrentSourceFrame, (double)fa->pfsi->lSourceFrameMS / 1000.0); break; case 1: mTextLine.sprintf("Output frame: %d", (int)fa->pfsi->mOutputFrame); break; case 2: mTextLine.sprintf("Sequence frame: %d (%.3fs)", (int)fa->pfsi->lCurrentFrame, (double)fa->pfsi->lDestFrameMS / 1000.0); break; } mRasterizer.Clear(); VDPixmapConvertTextToPath(mRasterizer, NULL, size, 8.0f * 8.0f * 10.0f, 8.0f * 8.0f * y, mTextLine.c_str()); mRasterizer.ScanConvert(mTextRegion); VDPixmapConvolveRegion(mShadowRegion, mTextRegion, mShadowBrush); VDPixmapFillRegionAntialiased8x(pxdst2, mShadowRegion, 0, 0, 0xFF000000); VDPixmapFillRegionAntialiased8x(pxdst2, mTextRegion, 0, 0, 0xFFFFFF00); y += 20.0f; } }
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; } } }
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()); } } }
size_t vdhash<VDStringA>::operator()(const VDStringA& s) const { return VDHashString32(s.data(), s.length()); }
bool VDFile::open_internal(const char *pszFilename, const wchar_t *pwszFilename, uint32 flags, bool throwOnError) { close(); mpFilename = _wcsdup(VDFileSplitPath(pszFilename ? VDTextAToW(pszFilename).c_str() : pwszFilename)); if (!mpFilename) { if (!throwOnError) return false; throw MyMemoryError(); } // At least one of the read/write flags must be set. VDASSERT(flags & (kRead | kWrite)); DWORD dwDesiredAccess = 0; if (flags & kRead) dwDesiredAccess = GENERIC_READ; if (flags & kWrite) dwDesiredAccess |= GENERIC_WRITE; // Win32 docs are screwed here -- FILE_SHARE_xxx is the inverse of a deny flag. DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; if (flags & kDenyRead) dwShareMode = FILE_SHARE_WRITE; if (flags & kDenyWrite) dwShareMode &= ~FILE_SHARE_WRITE; // One of the creation flags must be set. VDASSERT(flags & kCreationMask); DWORD dwCreationDisposition; uint32 creationType = flags & kCreationMask; switch(creationType) { case kOpenExisting: dwCreationDisposition = OPEN_EXISTING; break; case kOpenAlways: dwCreationDisposition = OPEN_ALWAYS; break; case kCreateAlways: dwCreationDisposition = CREATE_ALWAYS; break; case kCreateNew: dwCreationDisposition = CREATE_NEW; break; case kTruncateExisting: dwCreationDisposition = TRUNCATE_EXISTING; break; default: VDNEVERHERE; return false; } VDASSERT((flags & (kSequential | kRandomAccess)) != (kSequential | kRandomAccess)); DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL; if (flags & kSequential) dwAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; if (flags & kRandomAccess) dwAttributes |= FILE_FLAG_RANDOM_ACCESS; if (flags & kWriteThrough) dwAttributes |= FILE_FLAG_WRITE_THROUGH; if (flags & kUnbuffered) dwAttributes |= FILE_FLAG_NO_BUFFERING; VDStringA tempFilenameA; VDStringW tempFilenameW; if (IsWindowsNT()) { if (pszFilename) { tempFilenameW = VDTextAToW(pszFilename); pwszFilename = tempFilenameW.c_str(); pszFilename = NULL; } } else { if (pwszFilename) { tempFilenameA = VDTextWToA(pwszFilename); pszFilename = tempFilenameA.c_str(); pwszFilename = NULL; } } if (pszFilename) mhFile = CreateFileA(pszFilename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwAttributes, NULL); else { if (!IsHardDrivePath(pwszFilename)) flags &= ~FILE_FLAG_NO_BUFFERING; mhFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwAttributes, NULL); } DWORD err = GetLastError(); // If we failed and FILE_FLAG_NO_BUFFERING was set, strip it and try again. // VPC and Novell shares sometimes do this.... if (mhFile == INVALID_HANDLE_VALUE && err != ERROR_FILE_NOT_FOUND && err != ERROR_PATH_NOT_FOUND) { if (dwAttributes & FILE_FLAG_NO_BUFFERING) { dwAttributes &= ~FILE_FLAG_NO_BUFFERING; dwAttributes |= FILE_FLAG_WRITE_THROUGH; if (pszFilename) mhFile = CreateFileA(pszFilename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwAttributes, NULL); else mhFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwAttributes, NULL); err = GetLastError(); } } // INVALID_HANDLE_VALUE isn't NULL. *sigh* if (mhFile == INVALID_HANDLE_VALUE) { mhFile = NULL; if (!throwOnError) return false; throw MyWin32Error("Cannot open file \"%ls\":\n%%s", err, mpFilename.get()); } mFilePosition = 0; return true; }
void VDFileAsyncNT::ThreadRun() { int requestHead = 0; int requestTail = 0; int requestCount = mBlockCount; uint32 pendingLevel = 0; uint32 readOffset = 0; bool bPreemptiveExtend = mbPreemptiveExtend; sint64 currentSize; try { if (!VDGetFileSizeW32(mhFileFast, currentSize)) throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str()); for(;;) { int state = mState; if (state == kStateAbort) { typedef BOOL (WINAPI *tpCancelIo)(HANDLE); static const tpCancelIo pCancelIo = (tpCancelIo)GetProcAddress(GetModuleHandle(L"kernel32"), "CancelIo"); pCancelIo(mhFileFast); // Wait for any pending blocks to complete. for(int i=0; i<requestCount; ++i) { VDFileAsyncNTBuffer& buf = mpBlocks[i]; if (buf.mbActive) { WaitForSingleObject(buf.hEvent, INFINITE); buf.mbActive = false; } } break; } uint32 actual = mBufferLevel - pendingLevel; VDASSERT((int)actual >= 0); if (readOffset + actual > mBufferSize) actual = mBufferSize - readOffset; if (actual < mBlockSize) { if (state == kStateNormal || actual < mSectorSize) { // check for blocks that have completed bool blocksCompleted = false; for(;;) { VDFileAsyncNTBuffer& buf = mpBlocks[requestTail]; if (!buf.mbActive) { if (state == kStateFlush) goto all_done; if (!blocksCompleted) { // wait for further writes mWriteOccurred.wait(); } break; } if (buf.mbPending) { HANDLE h[2] = {buf.hEvent, mWriteOccurred.getHandle()}; DWORD waitResult = WaitForMultipleObjects(2, h, FALSE, INFINITE); if (waitResult == WAIT_OBJECT_0+1) // write pending break; DWORD dwActual; if (!GetOverlappedResult(mhFileFast, &buf, &dwActual, TRUE)) throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str()); } buf.mbActive = false; blocksCompleted = true; if (++requestTail >= requestCount) requestTail = 0; mBufferLevel -= buf.mLength; pendingLevel -= buf.mLength; VDASSERT((int)mBufferLevel >= 0); VDASSERT((int)pendingLevel >= 0); mReadOccurred.signal(); } continue; } VDASSERT(state == kStateFlush); actual &= ~(mSectorSize-1); VDASSERT(actual > 0); } else { actual = mBlockSize; if (bPreemptiveExtend) { sint64 checkpt = mFastPointer + mBlockSize + mBufferSize; if (checkpt > currentSize) { currentSize += mBufferSize; if (currentSize < checkpt) currentSize = checkpt; if (!VDSetFilePointerW32(mhFileFast, currentSize, FILE_BEGIN) || !SetEndOfFile(mhFileFast)) mbPreemptiveExtend = bPreemptiveExtend = false; } } } // Issue a write to OS VDFileAsyncNTBuffer& buf = mpBlocks[requestHead]; VDASSERT(!buf.mbActive); DWORD dwActual; buf.Offset = (DWORD)mFastPointer; buf.OffsetHigh = (DWORD)((uint64)mFastPointer >> 32); buf.Internal = 0; buf.InternalHigh = 0; buf.mLength = actual; buf.mbPending = false; if (!WriteFile(mhFileFast, &mBuffer[readOffset], actual, &dwActual, &buf)) { if (GetLastError() != ERROR_IO_PENDING) throw MyWin32Error("Write error occurred on file \"%s\": %%s", GetLastError(), mFilename.c_str()); buf.mbPending = true; } buf.mbActive = true; pendingLevel += actual; VDASSERT(pendingLevel <= (uint32)mBufferLevel); readOffset += actual; VDASSERT(readOffset <= mBufferSize); if (readOffset >= mBufferSize) readOffset = 0; mFastPointer += actual; if (++requestHead >= requestCount) requestHead = 0; } all_done: ; } catch(MyError& e) { MyError *p = new MyError; p->TransferFrom(e); delete mpError.xchg(p); mReadOccurred.signal(); } }
void VDFileAsyncNT::Seek(sint64 pos) { if (!SeekNT(pos)) throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str()); }
void VDFileAsyncNT::Truncate(sint64 pos) { Seek(pos); if (!SetEndOfFile(mhFileSlow)) throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str()); }
bool VDRegistryProviderMemory::Key::KeyPred::operator()(const VDStringA& s, const char *t) const { return s.comparei(t) == 0; }
const char *VDScriptInterpreter::TranslateScriptError(const VDScriptError& cse) { int i; char szError[1024]; switch(cse.err) { case VDScriptError::OVERLOADED_FUNCTION_NOT_FOUND: case VDScriptError::AMBIGUOUS_CALL: { if (cse.err == VDScriptError::OVERLOADED_FUNCTION_NOT_FOUND) { if (mpCurrentInvocationMethod && mpCurrentInvocationMethod->name) sprintf(szError, "Overloaded method %s(", mpCurrentInvocationMethod->name); else strcpy(szError, "Overloaded method ("); } else { if (mpCurrentInvocationMethod && mpCurrentInvocationMethod->name) sprintf(szError, "Ambiguous call with arguments %s(", mpCurrentInvocationMethod->name); else strcpy(szError, "Ambiguous call with arguments ("); } mError.assign(szError, szError + strlen(szError)); const VDScriptValue *const argv = &*(mStack.end() - mMethodArgumentCount); for(i=0; i<mMethodArgumentCount; i++) { if (i) { if (argv[i].isVoid()) break; mError.push_back(','); } switch(argv[i].type) { case VDScriptValue::T_VOID: strveccat(mError, "void"); break; case VDScriptValue::T_INT: strveccat(mError, "int"); break; case VDScriptValue::T_LONG: strveccat(mError, "long"); break; case VDScriptValue::T_DOUBLE: strveccat(mError, "double"); break; case VDScriptValue::T_STR: strveccat(mError, "string"); break; case VDScriptValue::T_OBJECT: strveccat(mError, "object"); break; case VDScriptValue::T_FNAME: strveccat(mError, "method"); break; case VDScriptValue::T_FUNCTION: strveccat(mError, "function"); break; case VDScriptValue::T_VARLV: strveccat(mError, "var"); break; } } strveccat(mError, ")"); if (cse.err == VDScriptError::OVERLOADED_FUNCTION_NOT_FOUND) strveccat(mError, " not found"); } mError.push_back(0); return mError.data(); case VDScriptError::MEMBER_NOT_FOUND: sprintf(szError, "Class '%s' does not have a member called '%s'", mErrorObject.asObjectDef()->mpName, szIdent); mError.assign(szError, szError + strlen(szError) + 1); return mError.data(); case VDScriptError::VAR_NOT_FOUND: if (!mErrorExtraToken.empty()) { sprintf(szError, "Variable '%s' not found", mErrorExtraToken.c_str()); mError.assign(szError, szError + strlen(szError) + 1); return mError.data(); } break; } return ::VDScriptTranslateError(cse); }
void vdmove<VDStringA>(VDStringA& dst, VDStringA& src) { dst.move_from(src); }
void VDFileAsync9x::ThreadRun() { bool bPreemptiveExtend = mbPreemptiveExtend; sint64 currentSize; sint64 pos = 0; uint32 bufferSize = mBlockCount * mBlockSize; HANDLE hFile = mhFileFast != INVALID_HANDLE_VALUE ? mhFileFast : mhFileSlow; try { if (bPreemptiveExtend && !VDGetFileSizeW32(hFile, currentSize)) throw MyWin32Error("I/O error on file \"%s\": %%s", GetLastError(), mFilename.c_str()); for(;;) { int state = mState; if (state == kStateAbort) break; int actual; const void *p = mBuffer.LockRead(mBlockSize, actual); if ((uint32)actual < mBlockSize) { if (state == kStateNormal) { mWriteOccurred.wait(); continue; } VDASSERT(state == kStateFlush); actual &= ~(mSectorSize-1); if (!actual) break; } else { if (bPreemptiveExtend) { sint64 checkpt = pos + mBlockSize + bufferSize; if (checkpt > currentSize) { currentSize += bufferSize; if (currentSize < checkpt) currentSize = checkpt; if (!VDSetFilePointerW32(hFile, currentSize, FILE_BEGIN) || !SetEndOfFile(hFile)) mbPreemptiveExtend = bPreemptiveExtend = false; if (!VDSetFilePointerW32(hFile, pos, FILE_BEGIN)) throw MyWin32Error("Seek error occurred on file \"%s\": %%s\n", GetLastError(), mFilename.c_str()); } } } DWORD dwActual; if (!WriteFile(hFile, p, actual, &dwActual, NULL) || dwActual != actual) { DWORD dwError = GetLastError(); throw MyWin32Error("Write error occurred on file \"%s\": %%s\n", dwError, mFilename.c_str()); } pos += actual; mBuffer.UnlockRead(actual); mReadOccurred.signal(); } } catch(MyError& e) { MyError *p = new MyError; p->TransferFrom(e); delete mpError.xchg(p); mReadOccurred.signal(); } }
bool VDDialogEditAccelerators::OnCommand(uint32 id, uint32 extcode) { if (id == IDC_FILTER) { if (extcode == EN_CHANGE) { VDStringA s("*"); s += VDTextWToA(GetControlValueString(id)).c_str(); s += '*'; RefilterCommands(s.c_str()); return true; } } else if (id == IDC_ADD) { VDUIAccelerator accel; int selIdx = LBGetSelectedIndex(IDC_AVAILCOMMANDS); if ((size_t)selIdx < mFilteredCommands.size()) { const VDAccelToCommandEntry *ace = mFilteredCommands[selIdx]; if (mpHotKeyControl) { mpHotKeyControl->GetAccelerator(accel); // Look for a conflicting command. for(BoundCommands::iterator it(mBoundCommands.begin()), itEnd(mBoundCommands.end()); it != itEnd; ++it) { BoundCommand *obc = *it; if (obc->mAccel == accel) { VDStringW keyName; VDUIGetAcceleratorString(accel, keyName); VDStringA msg; msg.sprintf("The key %ls is already bound to %hs. Rebind it to %hs?", keyName.c_str(), obc->mpCommand, ace->mpName); if (IDOK != MessageBox(mhdlg, msg.c_str(), g_szWarning, MB_OKCANCEL | MB_ICONEXCLAMATION)) return true; mBoundCommands.erase(it); obc->Release(); } } vdrefptr<BoundCommand> bc(new_nothrow BoundCommand); if (bc) { bc->mpCommand = ace->mpName; bc->mCommandId = ace->mId; bc->mAccel = accel; mBoundCommands.push_back(bc.release()); RefreshBoundList(); } } } return true; } else if (id == IDC_REMOVE) { int selIdx = mListViewBoundCommands.GetSelectedIndex(); if ((unsigned)selIdx < mBoundCommands.size()) { BoundCommand *bc = mBoundCommands[selIdx]; mBoundCommands.erase(mBoundCommands.begin() + selIdx); bc->Release(); RefreshBoundList(); } return true; } else if (id == IDC_RESET) { if (IDOK == MessageBox(mhdlg, "Really reset?", g_szWarning, MB_OKCANCEL | MB_ICONEXCLAMATION)) LoadTable(mBoundCommandsDefault); return true; } return false; }
size_t VDRegistryProviderMemory::Key::KeyHash::operator()(const VDStringA& s) const { return VDHashString32I(s.data(), s.size()); }
void VDDumpChangeLog() { HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_CHANGES), "STUFF"); if (!hResource) return; HGLOBAL hGlobal = LoadResource(NULL, hResource); if (!hGlobal) return; LPVOID lpData = LockResource(hGlobal); if (!lpData) return; const char *s = (const char *)lpData; while(*s!='\r') ++s; s+=2; tTextStream lineBuffer; VDStringA breakLineBuffer; bool foundNonIndentedLine = false; while(*s) { // parse line if (*s != ' ') { if (foundNonIndentedLine) break; foundNonIndentedLine = true; } const char *end = s; while(*end && *end != '\r' && *end != '\n') ++end; lineBuffer.clear(); append_cooked(lineBuffer, s, end, false); // skip line termination s = end; if (*s == '\r' || *s == '\n') { ++s; if ((s[0] ^ s[-1]) == ('\r' ^ '\n')) ++s; } lineBuffer.push_back(0); // break into lines const char *t = lineBuffer.data(); int maxLine = 78; breakLineBuffer.clear(); do { const char *lineStart = t; const char *break1 = NULL; const char *break2 = NULL; do { while(*t && *t != ' ') ++t; const char *u = t; while(*t && *t == ' ') ++t; if (u - lineStart > maxLine) { if (!break1) { break1 = u + maxLine; break2 = break1; } break; } break1 = u; break2 = t; } while(*t); breakLineBuffer.append(lineStart, break1); VDLog(kVDLogInfo, VDTextAToW(breakLineBuffer.data(), breakLineBuffer.size())); t = break2; breakLineBuffer.clear(); breakLineBuffer.resize(5, ' '); maxLine = 73; } while(*t); } }