The offsetFile example demonstrates how to read packets from a MAK Logger tape file (.lgr), apply a time offset to each packet, and write the modified packets to a new tape file. It supports both DIS and HLA logger formats, auto-detects the input file format, and preserves packet content while adjusting timestamps.
#include <vlutil/vlProcessControl.h>
#include <vlutil/vlPrint.h>
#include <vlutil/vlMiniDumper.h>
#include <cmdLine/cmdLine.h>
#if DtDIS
#include <vl/exerciseConnInitializerDIS.h>
#endif
#if DtHLA
#include <vl/exerciseConnInitializerHLA.h>
#include <vl/emptyFomMapper.h>
#endif
#include "vlutil/vlLogFileInfo.h"
#include "lgrUtil/svnRev.h"
using namespace MAKLogger;
#if DtDIS
const char defaultFileName[] = "..\\logger_tapes\\bombMission2025-DIS.lgr";
#elif DtHLA_4
const char defaultFileName[] = "..\\logger_tapes\\bombMission2025-HLA4-NETN.lgr";
#endif
bool fileTypeMatches(
DtString& filename);
void setConfigParameters(DtExerciseConnInitializer& exConnInit, const DtFilename& filename);
bool keyCheck(const char* keysToCheck);
int playFile(int argc, char** argv)
{
DtCmdLine::UnlabeledMultiArg<DtString> filenameArg("Filename","The name of the logger file to play.","string");
DtCmdLine::ValueArg<double> playbackSpeed("s","speed", "The playback speed.",false, 1.0,"double");
cmdLine.add(&filenameArg);
cmdLine.add(playbackSpeed);
cmdLine.parse(argc,argv);
std::vector<DtString> values = filenameArg.getValue();
if(values.size() == 0)
{
#ifdef DtHLA_4
values.push_back(defaultFileName);
#elif DtHLA_1516_EVOLVED
DtInfo << "Please provide a logger file using the HLA 1516 Evolved protocol to read." << std::endl;
return 1;
#elif DtDIS
values.push_back(defaultFileName);
#elif DtHLA_1516
DtInfo << "Please provide a logger file using the HLA 1516 protocol to read." << std::endl;
return 1;
#else
DtInfo << "Please provide a logger file using the HLA 1.3 protocol to read." << std::endl;
return 1;
#endif
}
DtFilename filename(values.front().c_str());
try
{
DtExerciseConnInitializer exConnInit;
#if DtDIS
DtDisLogger* aLogger = DtDisLogger::create(true);
#else
exConnInit.setFederateType("playFile");
exConnInit.setFederateName("playFile");
#endif
if (!fileTypeMatches(filename))
{
DtInfo << "Unable to process file (" <<
filename.c_str() << "): file format designator does not match, unknown or corrupted." << std::endl;
return 1;
}
#if DtHLA
setConfigParameters(exConnInit, filename);
#endif
{
DtInfo << "Unable to connect." << std::endl;
return 1;
}
delete simInterface;
if(!pbInterface)
{
DtInfo << "Error: Unable to create playback interface." << std::endl;
return 1;
}
{
DtInfo << "Unable to open file: " << filename << "." << std::endl;
return 1;
}
if (playbackSpeed.isSet())
{
DtInfo << "Setting playback speed to " << playbackSpeed.getValue() << std::endl;
}
DtInfo << "Playing file: " << filename << "." << std::endl;
DtInfo << "Press 'q' or 'enter' to quit." << std::endl;
{
DtInfo << "Unable to play file." << std::endl;
return 1;
}
double printDelay = 1.0;
double printLoopTotal = 0;
double loopDelay = .1;
{
if(printLoopTotal >= printDelay)
{
DtInfo <<
"Current Time = " << pbInterface->
currentTime() <<
"." << std::endl;
printLoopTotal = 0.0;
}
printLoopTotal += loopDelay;
DtSleep(loopDelay);
if(keyCheck("q\r")) break;
}
{
DtInfo << "Stopping playback." << std::endl;
}
DtInfo << "Finished playing file." << std::endl;
DtRestoreKbHit();
delete pbInterface;
delete aLogger;
}
catch (DtException& ex)
{
DtInfo << output << std::endl;
return 0;
}
return 0;
}
int main(int argc, char** argv)
{
DtLogFileInfo::instance().setAppName("PlayFile");
DtLogFileInfo::instance().setProtocol(DT_PROTOCOL_SHORT_NAME);
DtLogFileInfo::instance().setSvnRev(SVN_REV);
DtINIT_MINIDUMPER(DtLogFileInfo::instance().getFullString().c_str());
return playFile(argc,argv);
}
bool keyCheck(const char* keysToCheck)
{
if(DtKbHit())
{
char c = DtGetCh();
return strchr(keysToCheck,c) != 0;
}
return false;
}
bool fileTypeMatches(
DtString& filename)
{
unsigned int magic = 0;
std::ifstream fs;
fs.open(filename.c_str(),std::ios::binary );
if(!fs.is_open() || !fs.good())
{
DtInfo << "Unable to open file: " << filename << "." << std::endl;
exit(1);
}
fs.read((char*)&magic,4);
magic = (magic >> 24) | ((magic >> 8) & 0xFF00) |
((magic << 8) & 0xFF0000) | (magic << 24);
#if DtDIS
return DtString(
"Unknown") != DtLgrDisFileFormats::versionString(magic);
#else
#endif
}
#if DtHLA
void setConfigParameters(DtExerciseConnInitializer& exConnInit, const DtFilename& filename)
{
try
{
}
catch(DtException& ex)
{
DtInfo << output << std::endl;
}
if(configPacket)
{
}
exConnInit.setRprFomVersion(configData.
fomVersion().toDouble());
{
{
}
}
{
}
DtFilename fedFile(configData.
fedFile().c_str());
fedFile.stripPath();
exConnInit.setFedFileName(fedFile);
#if DtHLA_1516_EVOLVED
std::vector<DtString> fomModNames;
int numberModules = fomModNames.size();
if (numberModules > 0)
{
for (int fmIndex=0; fmIndex < numberModules; ++fmIndex)
{
DtFilename fmFilename(fomModNames[fmIndex].c_str());
fmFilename.stripPath();
fomModNames[fmIndex] = fmFilename;
}
exConnInit.setFomModules(fomModNames);
}
if (!configData.
mim().isEmpty())
{
DtFilename mim(configData.
mim().c_str());
mim.stripPath();
exConnInit.setMimModule(mim);
}
#endif
delete file;
}
#endif