MAK Data Logger API Documentation for HLA
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
playFile Example

The playFile program creates a logger, opens a logger tape, and plays it back.

Periodic messages output the current tape time. If 'q' is pressed playback stops and the program exits\ immediately, otherwise it will continue to the end of the tape at which point it will exit.


The main application:

/*******************************************************************************
** Copyright (c) 1992-2025 MAK Technologies, Inc
** All rights reserved.
*******************************************************************************/
#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;
// Hard coded paths for files. Relative to the bin directories.
#if DtDIS
const char defaultFileName[] = "..\\logger_tapes\\bombMission2025-DIS.lgr";
#elif DtHLA_4
const char defaultFileName[] = "..\\logger_tapes\\bombMission2025-HLA4-NETN.lgr";
//#elif DtHLA_1516_EVOLVED // no default logger tape provided for HLA 1516 Evolved protocol
//const char defaultFileName[] = "..\\logger_tapes\<lgr filename>";
//#elif DtHLA_1516 // no default logger tape provided for HLA 1516 protocol
//const char defaultFileName[] = "..\\logger_tapes\<lgr filename>";
//#else // no default logger tape provided for HLA 1.3 protocol
//const char defaultFileName[] = "..\\logger_tapes\<lgr filename>";
#endif
bool fileTypeMatches(DtString& filename);
void setConfigParameters(DtExerciseConnInitializer& exConnInit, const DtFilename& filename);
bool keyCheck(const char* keysToCheck);
int playFile(int argc, char** argv)
{
DtCmdLine::CmdLine cmdLine("playFile","Example of how to play a logger file.",LOGGER_VERSION_STRING);
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
{
// Initialize logger with settings retrieved from file.
DtExerciseConnInitializer exConnInit;
// Create the logger based upon it's protocol. These helper sub classes
// automatically register the protocol and provide additional utility
// functions.
#if DtDIS
// Create a DIS logger
DtDisLogger* aLogger = DtDisLogger::create(true);
#else
exConnInit.setFederateType("playFile");
exConnInit.setFederateName("playFile");
// Create a HLA logger
DtHlaLogger* aLogger = DtHlaLogger::create(true);
#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
// Extract the configuration data from the file
setConfigParameters(exConnInit, filename);
#endif
aLogger->connect(exConnInit);
DtLgrSimInterface* simInterface = DtLgrSimInterface::create(*aLogger);
aLogger->tick();
simInterface->update();
if(!simInterface->isConnected())
{
DtInfo << "Unable to connect." << std::endl;
return 1;
}
delete simInterface;
// Create Playback interface for controlling playback.
if(!pbInterface)
{
DtInfo << "Error: Unable to create playback interface." << std::endl;
return 1;
}
// Tell the logger to open a file.
pbInterface->openFile(filename, true);
// Process Commands
aLogger->tick();
// Update interface
pbInterface->update();
// Check to see if file was loaded.
if(!pbInterface->isFileLoaded())
{
DtInfo << "Unable to open file: " << filename << "." << std::endl;
return 1;
}
if (playbackSpeed.isSet())
{
DtInfo << "Setting playback speed to " << playbackSpeed.getValue() << std::endl;
pbInterface->setPlaybackSpeed(playbackSpeed.getValue(), false);
}
DtInfo << "Playing file: " << filename << "." << std::endl;
DtInfo << "Press 'q' or 'enter' to quit." << std::endl;
// Tell the logger to play.
pbInterface->play();
// Process Commands
aLogger->tick();
// Update interface
pbInterface->update();
// Check to see if playback was started.
if(!pbInterface->isPlaying())
{
DtInfo << "Unable to play file." << std::endl;
return 1;
}
// The number of seconds between print outs.
double printDelay = 1.0;
double printLoopTotal = 0;
// The time of a loop.
double loopDelay = .1;
// Execution loop.
while(pbInterface->isPlaying())
{
// Tick logger
aLogger->tick();
// Update Interface
pbInterface->update();
if(printLoopTotal >= printDelay)
{
DtInfo << "Current Time = " << pbInterface->currentTime() << "." << std::endl;
printLoopTotal = 0.0;
}
printLoopTotal += loopDelay;
DtSleep(loopDelay);
// Break out if q or enter was pressed.
if(keyCheck("q\r")) break;
}
// Check to see if the logger is still playing.
if(pbInterface->isPlaying())
{
DtInfo << "Stopping playback." << std::endl;
pbInterface->stop();
// Make the logger stop.
aLogger->tick();
}
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)
{
// Used for error handling
DtLogFileInfo::instance().setAppName("PlayFile");
DtLogFileInfo::instance().setProtocol(DT_PROTOCOL_SHORT_NAME);
DtLogFileInfo::instance().setSvnRev(SVN_REV);
DtLogFileInfo::instance().setVersion(LOGGER_VERSION_STRING);
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;
}
// Check that the file type matches one of the tape formats
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);
// File formats must be registered for this check to work
#if DtDIS
return DtString("Unknown") != DtLgrDisFileFormats::versionString(magic);
#else
return DtString("Unknown") != DtLgrHlaFileFormats::versionString(magic);
#endif
}
#if DtHLA
// Add the specific parameters for the tape.
void setConfigParameters(DtExerciseConnInitializer& exConnInit, const DtFilename& filename)
{
// Open the file and grab the config meta data
try
{
file = new DtLoggerPlaybackFile(DtString(filename.c_str()), false, true);
}
catch(DtException& ex)
{
DtInfo << output << std::endl;
}
const DtPacket* configPacket =
DtLgrHlaConfigData configData;
if(configPacket)
{
configData.deserialize(configPacket->data());
}
// Use the config meta data to set the exercise connection initializer
// that select things like the FOM version, FOM file name, etc.
if (!configData.fomVersion().isEmpty())
exConnInit.setRprFomVersion(configData.fomVersion().toDouble());
if (!configData.fomMapperName().isEmpty())
{
exConnInit.setFomMapperLibName(configData.fomMapperName());
if (!configData.fomMapperInitData().isEmpty())
{
exConnInit.setFomMapperInitData((void*)configData.fomMapperInitData().c_str());
}
}
if (!configData.emptyFomMapper().isEmpty() && configData.emptyFomMapper() != "0")
{
exConnInit.setFomMapper(new DtEmptyFomMapper());
}
exConnInit.setExecName(configData.federationName());
DtFilename fedFile(configData.fedFile().c_str());
fedFile.stripPath();
exConnInit.setFedFileName(fedFile);
#if DtHLA_1516_EVOLVED
std::vector<DtString> fomModNames;
configData.getFomModules(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

Document ID: Generated on Thu Dec 18 15:35:09 EST 2025 from SVN revision 282494
Copyright © 2024 MAK Technologies. All Rights Reserved (www.mak.com)