00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "../msg/msg.h"
00025 #include "../utils/utils.h"
00026 #include <dashel/dashel.h>
00027 #include <time.h>
00028 #include <iostream>
00029 #include <cstring>
00030 #include <string>
00031 #include <deque>
00032
00033 namespace Aseba
00034 {
00035 using namespace Dashel;
00036 using namespace std;
00037
00042
00045 class Player : public Hub
00046 {
00047 private:
00048 typedef deque<string> StringList;
00049
00050 bool respectTimings;
00051 int speedFactor;
00052 Stream* in;
00053 string line;
00054 UnifiedTime lastTimeStamp;
00055 UnifiedTime lastEventTime;
00056
00057 public:
00058 Player(const char* inputFile, bool respectTimings, int speedFactor) :
00059 respectTimings(respectTimings),
00060 speedFactor(speedFactor),
00061 lastTimeStamp(0)
00062 {
00063 if (inputFile)
00064 in = connect("file:" + string(inputFile) + ";mode=read");
00065 else
00066 in = connect("stdin:");
00067 }
00068
00069 StringList tokenize(const string& input)
00070 {
00071 StringList list;
00072 const size_t inputSize(input.size());
00073
00074 size_t pos(0);
00075 while ((pos != string::npos) && (pos < inputSize))
00076 {
00077 const size_t next = input.find(' ', pos);
00078 string word;
00079 if (next != string::npos)
00080 word = input.substr(pos, next-pos);
00081 else
00082 word = input.substr(pos);
00083 if (!word.empty())
00084 list.push_back(word);
00085 pos = next + 1;
00086 }
00087
00088 return list;
00089 }
00090
00091 void sendLine()
00092 {
00093
00094 UserMessage userMessage;
00095
00096 StringList tokenizedLine(tokenize(line));
00097
00098 UnifiedTime timeStamp(UnifiedTime::fromRawTimeString(tokenizedLine.front()));
00099 tokenizedLine.pop_front();
00100
00101 userMessage.source = atoi(tokenizedLine.front().c_str());
00102 tokenizedLine.pop_front();
00103
00104 userMessage.type = atoi(tokenizedLine.front().c_str());
00105 tokenizedLine.pop_front();
00106
00107 userMessage.data.reserve(size_t(atoi(tokenizedLine.front().c_str())));
00108 tokenizedLine.pop_front();
00109
00110 while (!tokenizedLine.empty())
00111 {
00112 userMessage.data.push_back(atoi(tokenizedLine.front().c_str()));
00113 tokenizedLine.pop_front();
00114 }
00115
00116
00117 if ((respectTimings) && (lastTimeStamp.value != 0))
00118 {
00119 const UnifiedTime lostTime(UnifiedTime() - lastEventTime);
00120 const UnifiedTime deltaTimeStamp(timeStamp - lastTimeStamp);
00121 if (lostTime < deltaTimeStamp)
00122 {
00123 UnifiedTime waitTime(deltaTimeStamp - lostTime);
00124 waitTime /= speedFactor;
00125 waitTime.sleep();
00126 }
00127 }
00128
00129
00130 for (StreamsSet::iterator it = dataStreams.begin(); it != dataStreams.end();++it)
00131 {
00132 Stream* destStream(*it);
00133 if (destStream != in)
00134 {
00135 userMessage.serialize(destStream);
00136 destStream->flush();
00137 }
00138 }
00139
00140 lastEventTime = UnifiedTime();
00141 lastTimeStamp = timeStamp;
00142
00143 line.clear();
00144 }
00145
00146 protected:
00147
00148 void connectionCreated(Stream *stream)
00149 {
00150
00151 }
00152
00153 void incomingData(Stream *stream)
00154 {
00155 char c(stream->read<char>());
00156 if (stream == in)
00157 {
00158 if (c == '\n')
00159 sendLine();
00160 else
00161 line += c;
00162 }
00163 }
00164
00165 void connectionClosed(Stream *stream, bool abnormal)
00166 {
00167 if (stream == in)
00168 stop();
00169 }
00170 };
00171
00173 }
00174
00175
00177 void dumpHelp(std::ostream &stream, const char *programName)
00178 {
00179 stream << "Aseba play, play recorded user messages from a file or stdin, usage:\n";
00180 stream << programName << " [options] [targets]*\n";
00181 stream << "Options:\n";
00182 stream << "--fast : replay messages twice the speed of real time\n";
00183 stream << "--faster : replay messages four times the speed of real time\n";
00184 stream << "--fastest : replay messages as fast as possible\n";
00185 stream << "-f INPUT_FILE : open INPUT_FILE instead of stdin\n";
00186 stream << "-h, --help : shows this help\n";
00187 stream << "Targets are any valid Dashel targets." << std::endl;
00188 }
00189
00190 int main(int argc, char *argv[])
00191 {
00192 bool respectTimings = true;
00193 int speedFactor = 1;
00194 std::vector<std::string> targets;
00195 const char* inputFile = 0;
00196
00197 int argCounter = 1;
00198
00199 while (argCounter < argc)
00200 {
00201 const char *arg = argv[argCounter];
00202
00203 if (strcmp(arg, "--fastest") == 0)
00204 {
00205 respectTimings = false;
00206 }
00207 else if (strcmp(arg, "--fast") == 0)
00208 {
00209 speedFactor = 2;
00210 }
00211 else if (strcmp(arg, "--faster") == 0)
00212 {
00213 speedFactor = 4;
00214 }
00215 else if ((strcmp(arg, "-h") == 0) || (strcmp(arg, "--help") == 0))
00216 {
00217 dumpHelp(std::cout, argv[0]);
00218 return 0;
00219 }
00220 else if (strcmp(arg, "-f") == 0)
00221 {
00222 argCounter++;
00223 if (argCounter >= argc)
00224 {
00225 dumpHelp(std::cout, argv[0]);
00226 return 1;
00227 }
00228 else
00229 inputFile = argv[argCounter];
00230 }
00231 else
00232 {
00233 targets.push_back(argv[argCounter]);
00234 }
00235 argCounter++;
00236 }
00237
00238 if (targets.empty())
00239 targets.push_back(ASEBA_DEFAULT_TARGET);
00240
00241 try
00242 {
00243 Aseba::Player player(inputFile, respectTimings, speedFactor);
00244 for (size_t i = 0; i < targets.size(); i++)
00245 player.connect(targets[i]);
00246 player.run();
00247 }
00248 catch(Dashel::DashelException e)
00249 {
00250 std::cerr << e.what() << std::endl;
00251 }
00252
00253 return 0;
00254 }