| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace { |
| |
| TFilePath getExternFxPath() { |
| return TSystem::getBinDir() + "plugins" + "externFxs"; |
| } |
| } |
| |
| |
| |
| |
| void TExternFx::getNames(std::vector<std::string> &names) {} |
| |
| |
| |
| TExternFx *TExternFx::create(std::string name) { |
| TExternalProgramFx *fx = new TExternalProgramFx(name); |
| return fx; |
| } |
| |
| |
| |
| TExternalProgramFx::TExternalProgramFx(std::string name) |
| : m_externFxName(name) { |
| initialize(name); |
| setName(L"ExternalProgramFx"); |
| |
| } |
| |
| |
| |
| TExternalProgramFx::TExternalProgramFx() : m_externFxName() { |
| setName(L"ExternalProgramFx"); |
| |
| } |
| |
| |
| |
| TExternalProgramFx::~TExternalProgramFx() {} |
| |
| |
| |
| void TExternalProgramFx::initialize(std::string name) { |
| TFilePath fp = getExternFxPath() + (name + ".xml"); |
| TIStream is(fp); |
| if (!is) return; |
| |
| std::string tagName; |
| if (!is.matchTag(tagName) || tagName != "externFx") return; |
| |
| try { |
| while (is.matchTag(tagName)) { |
| if (tagName == "executable") { |
| TFilePath executable = TFilePath(is.getTagAttribute("path")); |
| std::string args = is.getTagAttribute("args"); |
| if (executable == TFilePath()) |
| throw TException("missing executable path"); |
| if (args == "") throw TException("missing args string"); |
| setExecutable(executable, args); |
| } else if (tagName == "inport" || tagName == "outport") { |
| std::string portName = is.getTagAttribute("name"); |
| std::string ext = is.getTagAttribute("ext"); |
| if (portName == "") throw TException("missing port name"); |
| if (ext == "") throw TException("missing port ext"); |
| addPort(portName, ext, tagName == "inport"); |
| } else if (tagName == "param") { |
| std::string paramName = is.getTagAttribute("name"); |
| if (paramName == "") throw TException("missing param name"); |
| std::string type = is.getTagAttribute("type"); |
| if (type == "") throw TException("missing param type"); |
| if (type != "double") |
| throw TException("param type not yet implemented"); |
| TDoubleParamP param = new TDoubleParam(); |
| param->setName(paramName); |
| m_params.push_back(param); |
| } else |
| throw TException("unexpected tag " + tagName); |
| } |
| is.closeChild(); |
| |
| for (int i = 0; i < (int)m_params.size(); i++) |
| bindParam(this, m_params[i]->getName(), m_params[i]); |
| |
| } catch (...) { |
| } |
| } |
| |
| |
| |
| void TExternalProgramFx::addPort(std::string portName, std::string ext, |
| bool isInput) { |
| if (isInput) { |
| TRasterFxPort *port = new TRasterFxPort(); |
| m_ports[portName] = Port(portName, ext, port); |
| addInputPort(portName, *port); |
| } else |
| m_ports[portName] = Port(portName, ext, 0); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TFx *TExternalProgramFx::clone(bool recursive) const { |
| TExternalProgramFx *fx = |
| dynamic_cast<TExternalProgramFx *>(TExternFx::create(m_externFxName)); |
| assert(fx); |
| |
| |
| |
| |
| fx->setActiveTimeRegion(getActiveTimeRegion()); |
| |
| |
| fx->getParams()->copy(getParams()); |
| |
| assert(getInputPortCount() == fx->getInputPortCount()); |
| |
| |
| |
| |
| |
| |
| if (recursive) { |
| for (int i = 0; i < getInputPortCount(); ++i) { |
| TFxPort *port = getInputPort(i); |
| if (port->getFx()) |
| fx->connect(getInputPortName(i), port->getFx()->clone(true)); |
| } |
| } |
| |
| |
| |
| |
| |
| return fx; |
| } |
| |
| |
| |
| bool TExternalProgramFx::doGetBBox(double frame, TRectD &bBox, |
| const TRenderSettings &info) { |
| |
| |
| |
| std::map<std::string, Port>::const_iterator portIt; |
| for (portIt = m_ports.begin(); portIt != m_ports.end(); ++portIt) { |
| if (portIt->second.m_port != 0) { |
| TRasterFxPort *tmp; |
| tmp = portIt->second.m_port; |
| if (tmp->isConnected()) { |
| TRectD tmpbBox; |
| (*tmp)->doGetBBox(frame, tmpbBox, info); |
| bBox += tmpbBox; |
| } |
| } |
| } |
| |
| if (bBox.isEmpty()) { |
| bBox = TRectD(); |
| return false; |
| } else |
| return true; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| void TExternalProgramFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &ri) { |
| TRaster32P ras = tile.getRaster(); |
| if (!ras) return; |
| std::string args = m_args; |
| std::string executablePath = ::to_string(m_executablePath); |
| std::map<std::string, TFilePath> tmpFiles; |
| TFilePath outputTmpFile; |
| |
| std::map<std::string, Port>::const_iterator portIt; |
| for (portIt = m_ports.begin(); portIt != m_ports.end(); ++portIt) { |
| TFilePath fp = TSystem::getUniqueFile("externfx"); |
| fp = fp.withType(portIt->second.m_ext); |
| tmpFiles[portIt->first] = fp; |
| if (portIt->second.m_port == 0) |
| outputTmpFile = fp; |
| else { |
| TRasterFxPort *tmp; |
| tmp = portIt->second.m_port; |
| if (tmp->isConnected()) { |
| (*tmp)->compute(tile, frame, ri); |
| TImageWriter::save(fp, ras); |
| } |
| } |
| } |
| |
| |
| |
| int i = 0; |
| for (;;) { |
| i = args.find('$', i); |
| if (i == (int)std::string::npos) break; |
| int j = i + 1; |
| int len = args.length(); |
| while (j < len && isalnum(args[j])) j++; |
| |
| if (j == i + 1) { |
| |
| if (j < len && args[j] == '$') args.replace(i, 2, "$"); |
| i++; |
| continue; |
| } |
| |
| int m = j - i - 1; |
| std::string name = args.substr(i + 1, m); |
| |
| std::string value; |
| |
| std::map<std::string, TFilePath>::const_iterator it; |
| it = tmpFiles.find(name); |
| if (it != tmpFiles.end()) { |
| |
| |
| value = "\"" + ::to_string(it->second.getWideString()) + "\""; |
| } else { |
| |
| |
| TDoubleParamP param = TParamP(getParams()->getParam(name)); |
| if (param) value = std::to_string(param->getValue(frame)); |
| } |
| |
| args.replace(i, m + 1, value); |
| } |
| args = " " + args; |
| |
| |
| |
| |
| |
| |
| |
| |
| std::string expandedargs; |
| char buffer[1024]; |
| |
| ExpandEnvironmentStrings(args.c_str(), buffer, 1024); |
| |
| STARTUPINFO si; |
| PROCESS_INFORMATION pinfo; |
| |
| GetStartupInfo(&si); |
| |
| BOOL ret = CreateProcess( |
| (char *)executablePath.c_str(), |
| buffer, |
| NULL, |
| NULL, |
| TRUE, |
| CREATE_NO_WINDOW, |
| NULL, |
| NULL, |
| &si, |
| &pinfo |
| ); |
| |
| if (!ret) DWORD err = GetLastError(); |
| |
| |
| WaitForSingleObject(pinfo.hProcess, INFINITE); |
| |
| DWORD exitCode; |
| ret = GetExitCodeProcess(pinfo.hProcess, |
| &exitCode); |
| |
| |
| std::string cmdline = executablePath + buffer; |
| |
| system(cmdline.c_str()); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| try { |
| TRasterP ras = tile.getRaster(); |
| TImageReader::load(outputTmpFile, ras); |
| } catch (...) { |
| } |
| |
| |
| std::map<std::string, TFilePath>::const_iterator fileIt; |
| for (fileIt = tmpFiles.begin(); fileIt != tmpFiles.end(); ++fileIt) { |
| if (TFileStatus(fileIt->second).doesExist() == true) try { |
| TSystem::deleteFile(fileIt->second); |
| } catch (...) { |
| } |
| } |
| if (TFileStatus(outputTmpFile).doesExist() == true) try { |
| TSystem::deleteFile(outputTmpFile); |
| } catch (...) { |
| } |
| } |
| |
| |
| |
| void TExternalProgramFx::loadData(TIStream &is) { |
| std::string tagName; |
| while (is.openChild(tagName)) { |
| if (tagName == "path") { |
| is >> m_executablePath; |
| } else if (tagName == "args") { |
| is >> m_args; |
| } else if (tagName == "name") { |
| is >> m_externFxName; |
| |
| } else if (tagName == "params") { |
| while (is.matchTag(tagName)) { |
| if (tagName == "param") { |
| |
| std::string paramName = is.getTagAttribute("name"); |
| TDoubleParamP param = new TDoubleParam(); |
| param->setName(paramName); |
| m_params.push_back(param); |
| } else |
| throw TException("unexpected tag " + tagName); |
| } |
| for (int i = 0; i < (int)m_params.size(); i++) |
| bindParam(this, m_params[i]->getName(), m_params[i]); |
| } else if (tagName == "ports") { |
| while (is.matchTag(tagName)) { |
| if (tagName == "port") { |
| std::string name = is.getTagAttribute("name"); |
| std::string ext = is.getTagAttribute("ext"); |
| addPort(name, ext, true); |
| } else if (tagName == "outport") { |
| std::string name = is.getTagAttribute("name"); |
| std::string ext = is.getTagAttribute("ext"); |
| addPort(name, ext, false); |
| } else |
| throw TException("unexpected tag " + tagName); |
| } |
| } else if (tagName == "super") { |
| TExternFx::loadData(is); |
| } else |
| throw TException("unexpected tag " + tagName); |
| is.closeChild(); |
| } |
| } |
| |
| void TExternalProgramFx::saveData(TOStream &os) { |
| os.child("name") << m_externFxName; |
| os.child("path") << m_executablePath; |
| os.child("args") << m_args; |
| os.openChild("params"); |
| for (int i = 0; i < getParams()->getParamCount(); i++) { |
| std::map<std::string, std::string> attr; |
| attr["name"] = getParams()->getParamName(i); |
| attr["type"] = "double"; |
| os.openCloseChild("param", attr); |
| } |
| os.closeChild(); |
| os.openChild("ports"); |
| std::map<std::string, Port>::iterator portIt; |
| for (portIt = m_ports.begin(); portIt != m_ports.end(); ++portIt) { |
| std::map<std::string, std::string> attr; |
| attr["name"] = portIt->second.m_name; |
| attr["ext"] = portIt->second.m_ext; |
| std::string tagName = portIt->second.m_port == 0 ? "outport" : "port"; |
| os.openCloseChild(tagName, attr); |
| } |
| os.closeChild(); |
| os.openChild("super"); |
| TExternFx::saveData(os); |
| os.closeChild(); |
| } |
| |
| |
| |
| |
| |
| |
| void ExternalProgramFx::doCompute(TTile &tile, double frame, |
| const TRenderSettings &ri) { |
| if (!m_input1.isConnected() || !m_input2.isConnected()) { |
| tile.getRaster()->clear(); |
| return; |
| } |
| std::string name1("C:\\temp\\uno..tif"); |
| std::string name2("C:\\temp\\due..tif"); |
| std::string outname("C:\\temp\\outfile.0001.jpg"); |
| std::string program("C:\\temp\\xdissolve.exe"); |
| std::string extension(".jpg"); |
| TFilePath programpath(program); |
| |
| m_input1->compute(tile, frame, ri); |
| TFilePath fname1(name1); |
| TFilePath fname2(name2); |
| std::string tmp1 = fname1.getName() + extension; |
| std::string tmp2 = fname2.getName() + extension; |
| |
| TFilePath tmpname1(fname1.getParentDir() + tmp1); |
| TFilePath tmpname2(fname2.getParentDir() + tmp2); |
| TFilePath out(outname); |
| TImageWriter::save(tmpname1, tile.getRaster()); |
| m_input2->compute(tile, frame, ri); |
| TImageWriter::save(tmpname2, tile.getRaster()); |
| |
| std::string arglist = " -range1 1 1 -start2 1 -startout 1 "; |
| arglist += toString(tmpname1.getWideString()); |
| arglist += " " + toString(tmpname2.getWideString()); |
| arglist += " " + outname; |
| std::string cmdline = program + arglist; |
| |
| |
| STARTUPINFO si; |
| PROCESS_INFORMATION pinfo; |
| |
| GetStartupInfo(&si); |
| |
| BOOL ret = |
| CreateProcess(NULL, |
| (char *)cmdline.c_str(), |
| NULL, |
| NULL, |
| TRUE, |
| CREATE_NO_WINDOW, |
| NULL, |
| NULL, |
| &si, |
| &pinfo |
| ); |
| |
| if (!ret) DWORD err = GetLastError(); |
| |
| |
| WaitForSingleObject(pinfo.hProcess, INFINITE); |
| |
| DWORD exitCode; |
| ret = GetExitCodeProcess(pinfo.hProcess, |
| &exitCode); |
| |
| |
| int exitCode = system(cmdline.c_str()); |
| |
| TImageReader::load(out, tile.getRaster()); |
| |
| TSystem::deleteFile(tmpname1); |
| TSystem::deleteFile(tmpname2); |
| TSystem::deleteFile(out); |
| } |
| |
| FX_PLUGIN_IDENTIFIER(ExternalProgramFx, "externalProgramFx"); |
| * / |
| |
| |
| FX_IDENTIFIER(TExternalProgramFx, "externalProgramFx") |
| |