CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
PsyInternal.cpp
Go to the documentation of this file.
1
6#include "PsyInternal.h"
7
8namespace cmlabs {
9
11 //printf("************ Simple start [%p] %s *************\n", api, api->getModuleName().c_str()); fflush(stdout);
12 bool print = false;
13 if (api->hasParameter("Print"))
14 print = (api->getParameterString("Print").compare("yes") == 0);
15
16 int32 c = 0;
17 DataMessage* inMsg, *msg;
18 const char* triggerName;
19 if (api->shouldContinue()) {
20 if (inMsg = api->waitForNewMessage(0, triggerName)) {
21 //printf("[%u]", c++); fflush(stdout);
22 msg = new DataMessage(*inMsg);
23 //std::string pIn = inMsg->getUserEntriesAsString();
24 //std::string pOut = msg->getUserEntriesAsString();
25 //utils::AppendToAFile("d:/out.txt", pIn.c_str(), pIn.length() + 1);
26 //utils::AppendToAFile("d:/out.txt", pOut.c_str(), pOut.length() + 1);
27
28
29
30 //delete(msg);
34 //msg = new DataMessage();
35
36 //uint32 size = 100000;
37 //char* data = new char[size];
39 //memset(data, 0, size);
42
44 //msg = new DataMessage();
46 //msg->setData("AudioDataFrame", data, size);
47 //msg->setInt("AudioChannels", 1);
48 //msg->setInt("AudioRate", 16000);
49 //msg->setInt("AudioSamples", 1);
50 //msg->setInt("AudioBitsPerSample", 2);
51 //msg->setInt("TimeMS", 0);
52 //msg->setDouble("FilePosition", 0);
53 //msg->setDouble("VideoFPS", 0);
54
55 c = api->postOutputMessage(NULL, msg);
56
57 //delete[] data;
58
59 if (c > 1) {
60 if (print)
61 api->logPrint(1, "Posted %d output messages", c);
62 }
63 else if (c == 1) {
64 if (print)
65 api->logPrint(1, "Posted one output message", c);
66 }
67 else if (c < 0)
68 api->logPrint(1, "Posted no messages (%d)", c);
69 else
70 api->logPrint(1, "Posted no messages");
71 }
72 }
73 //printf("************ Simple end [%p] %s *************\n", api, api->getModuleName().c_str()); fflush(stdout);
74 return 0;
75}
76
78
79 api->logPrint(1,"Started running (internal)...");
80
81 DataMessage* inMsg, *outMsg;
82 int64 counter = 0, start, end;
83 int64 t = 0;
84 const char* triggerName;
85 bool print = false;
86 int64 count = 10000;
87 int64 cycles = 10;
88 int64 modules = 2;
89 double current, last = 0;
90
91 int64 val;
92 if (api->hasParameter("Cycles"))
93 if (api->getParameter("Cycles", val))
94 cycles = val;
95 if (api->hasParameter("Count"))
96 if (api->getParameter("Count", val))
97 count = val;
98 if (api->hasParameter("Modules"))
99 if (api->getParameter("Modules", val))
100 modules = val;
101
102 int64 totalMessageCount = cycles*count;
103
104 while (api->shouldContinue()) {
105 if ( inMsg = api->waitForNewMessage(100, triggerName)) {
106 outMsg = new DataMessage();
107 if ( (stricmp(triggerName, "Ready") == 0) || (stricmp(triggerName, "Start") == 0) ) {
108 api->logPrint(1,"Starting %u cycles test...", cycles);
109 start = GetTimeNow();
110 print = true;
111 t = 0;
112 counter = 0;
113 }
114 else if (stricmp(triggerName, "Ball") == 0) {
115 t += GetTimeAge(inMsg->getCreatedTime());
116 // api->logPrint(2,"[%s] got ball message type '%s'...", api->typeToText(inMsg->getType()).c_str());
117 if (!counter++)
118 start = GetTimeNow();
119 else if (counter % totalMessageCount == 0) {
120 end = GetTimeNow();
121 current = ((double)(end-start))/(modules*count);
122 if (!last)
123 api->logPrint(1,"Got msg %llu, avg msg time: %.1fus, avg msg age: %.1fus...",
124 counter, current, ((double)t/count));
125 else if (last > current)
126 api->logPrint(1,"Got msg %llu, avg msg time: %.1fus, avg msg age: %.1fus (%.1fus faster)...",
127 counter, current, ((double)t/count), last-current);
128 else
129 api->logPrint(1,"Got msg %llu, avg msg time: %.1fus, avg msg age: %.1fus (%.1fus slower)...",
130 counter, current, ((double)t/count), current-last);
131 api->postOutputMessage("Done", outMsg);
132 outMsg = NULL;
133 }
134 else if (counter % count == 0) {
135 end = GetTimeNow();
136 current = ((double)(end-start))/(modules*count);
137 if (print) {
138 if (!last)
139 api->logPrint(1,"Got msg %llu, avg msg time: %.1fus, avg msg age: %.1fus...",
140 counter, current, ((double)t/count));
141 else if (last > current)
142 api->logPrint(1,"Got msg %llu, avg msg time: %.1fus, avg msg age: %.1fus (%.1fus faster)...",
143 counter, current, ((double)t/count), last-current);
144 else
145 api->logPrint(1,"Got msg %llu, avg msg time: %.1fus, avg msg age: %.1fus (%.1fus slower)...",
146 counter, current, ((double)t/count), current-last);
147 }
148 last = current;
149 t = 0;
150 start = GetTimeNow();
151 }
152 }
153 else {
154 api->logPrint(1,"Got other message type '%s'...", api->typeToText(inMsg->getType()).c_str());
155 delete(outMsg);
156 outMsg = NULL;
157 }
158 if (outMsg) {
159 api->postOutputMessage("Ball", outMsg);
160 // utils::Sleep(5);
161 }
162 }
163 }
164
165 return 0;
166}
167
169
170 api->logPrint(1,"Started running...");
171
172 const char* triggerName;
173 DataMessage* inMsg;
174 while (api->shouldContinue()) {
175 if ( inMsg = api->waitForNewMessage(100, triggerName))
176 api->postOutputMessage("Ball");
177 }
178
179 return 0;
180}
181
183
184 api->logPrint(1,"Started running...");
185
186 DataMessage* inMsg, *outMsg;
187 const char* triggerName;
188
189 while (api->shouldContinue()) {
190 if ( inMsg = api->waitForNewMessage(100, triggerName)) {
191 outMsg = new DataMessage();
192 api->postOutputMessage("Done", outMsg);
193 }
194 }
195
196 return 0;
197}
198
200
201 api->logPrint(1,"Started running...");
202
203 DataMessage* inMsg;
204 const char* triggerName;
205 std::string userdata;
206 PsyContext context;
207
208 uint32 count = 0;
209 uint64 lastTime = 0;
210 while (api->shouldContinue()) {
211 if ( inMsg = api->waitForNewMessage(100, triggerName)) {
212 userdata = inMsg->getUserEntriesAsString();
213
214 context = inMsg->getContextChange();
215 if (context != NOCONTEXT) {
216 if (lastTime)
217 api->logPrint(1, "Trigger '%s' new context '%s' from '%s' context '%s' [%u] (%s):\n%s", triggerName, api->contextToText(context).c_str(), api->getOtherModuleName(inMsg->getFrom()).c_str(), api->contextToText(api->getCurrentTriggerContext()).c_str(), count, PrintTimeDifString(GetTimeAge(lastTime)).c_str(), userdata.c_str());
218 else
219 api->logPrint(1, "Trigger '%s' new context '%s' from '%s' context '%s' [%u]:\n%s\n", triggerName, api->contextToText(context).c_str(), api->getOtherModuleName(inMsg->getFrom()).c_str(), api->contextToText(api->getCurrentTriggerContext()).c_str(), count, userdata.c_str());
220 }
221 else if (userdata.length()) {
222 if (lastTime)
223 api->logPrint(1, "Trigger '%s' type '%s' from '%s' context '%s' [%u] (%s):\n%s", triggerName, api->typeToText(inMsg->getType()).c_str(), api->getOtherModuleName(inMsg->getFrom()).c_str(), api->contextToText(api->getCurrentTriggerContext()).c_str(), count, PrintTimeDifString(GetTimeAge(lastTime)).c_str(), userdata.c_str());
224 else
225 api->logPrint(1, "Trigger '%s' type '%s' from '%s' context '%s' [%u]:\n%s\n", triggerName, api->typeToText(inMsg->getType()).c_str(), api->getOtherModuleName(inMsg->getFrom()).c_str(), api->contextToText(api->getCurrentTriggerContext()).c_str(), count, userdata.c_str());
226 }
227 else {
228 if (lastTime)
229 api->logPrint(1, "Trigger '%s' type '%s' from '%s' context '%s' [%u] (%s)", triggerName, api->typeToText(inMsg->getType()).c_str(), api->getOtherModuleName(inMsg->getFrom()).c_str(), api->contextToText(api->getCurrentTriggerContext()).c_str(), count, PrintTimeDifString(GetTimeAge(lastTime)).c_str());
230 else
231 api->logPrint(1, "Trigger '%s' type '%s' from '%s' context '%s' [%u]", triggerName, api->typeToText(inMsg->getType()).c_str(), api->getOtherModuleName(inMsg->getFrom()).c_str(), api->contextToText(api->getCurrentTriggerContext()).c_str(), count);
232 }
233 lastTime = inMsg->getCreatedTime();
234 if (api->getCurrentPostNames().size())
235 api->postOutputMessage();
236 count++;
237 //if (++count == 1) {
238 // api->postOutputMessage();
239 // count = 0;
240 //}
241 }
242 }
243
244 return 0;
245}
246
248
249 uint64 t1, t2;
250 int64 t;
251 uint32 errorCount = 0;
252 double var = 0;
253
254 DataMessage* inMsg;
255 const char* triggerName;
256 while (api->shouldContinue()) {
257 if ( inMsg = api->waitForNewMessage(100, triggerName))
258 api->postOutputMessage();
259
260 for (uint32 n=0; n<9; n++) {
261 t1 = GetTimeNow();
262 for (uint32 m=0; m<1000; m++) {
263 var += sqrt((double)m*m+1);
264 }
265 t2 = GetTimeNow();
266 t = t2 - t1;
267 if ( (t < 0) || (t > 50) ) {
268 errorCount++;
269 api->logPrint(1,"[%u] Timing error - %lld", errorCount, t, var);
270 }
271 }
272 }
273 return 0;
274}
275
277 DataMessage* inMsg;
278 const char* triggerName;
279
280 api->logPrint(1,"Started running...");
281
282 int64 steps = 10;
283 int64 cycles;
284 if (api->hasParameter("Cycles"))
285 if (api->getParameter("Cycles", cycles))
286 steps = cycles;
287
288 uint64 lastTime = GetTimeNow() - 1000000;
289 uint64 totalTime = 0;
290 uint32 count = 0;
291 while (api->shouldContinue()) {
292 if ( inMsg = api->waitForNewMessage(0, triggerName)) {
293 if (stricmp(triggerName, "Start") == 0) {
294 api->logPrint(1,"Emitting signal [%u]...", count);
295 api->emitSignal("Output");
296 utils::Sleep(10);
297 }
298 }
299 else if (inMsg = api->waitForSignal("Input", 100, lastTime)) {
300 totalTime += GetTimeAge( lastTime = inMsg->getCreatedTime() );
301 count++;
302 // api->logPrint(1,"[%s] got signal, %u [%u]...", totalTime, count);
303 if (count % 10 == 0)
304 api->logPrint(1,"Got signal, average %.3fus [%u]...", ((double)totalTime/count), count);
305 utils::Sleep(10);
306 if (count < steps)
307 api->emitSignal("Output");
308 else
309 api->postOutputMessage();
310 }
311 }
312 return 0;
313}
314
316 DataMessage* inMsg;
317 const char* triggerName;
318
319 api->logPrint(1,"Started running...");
320
321 utils::Sleep(100);
322
323 uint64 lastTime = GetTimeNow() - 1000000;
324 while (api->shouldContinue()) {
325 if ( inMsg = api->waitForNewMessage(0, triggerName)) {
326 }
327 else if (inMsg = api->waitForSignal("Input", 100, lastTime)) {
328 lastTime = inMsg->getCreatedTime();
329 // api->postOutputMessage();
330 api->emitSignal("Output");
331 // utils::Sleep(10);
332 }
333 }
334 return 0;
335}
336
338
339 int64 steps = 10;
340 int64 cycles;
341 if (api->hasParameter("Cycles"))
342 if (api->getParameter("Cycles", cycles))
343 steps = cycles;
344
345 api->logPrint(1,"Started running, %u steps...", steps);
346
347 int64 val;
348 DataMessage* inMsg, *outMsg;
349 const char* triggerName;
350 uint64 start = GetTimeNow();
351
352 std::list<DataMessage*> retrievedMsgs;
353 std::list<DataMessage*>::iterator i, e;
354
355 while (api->shouldContinue()) {
356 if ( inMsg = api->waitForNewMessage(100, triggerName)) {
357 if ( (stricmp(triggerName, "Ready") == 0) || (stricmp(triggerName, "Start") == 0) ) {
358 api->logPrint(1,"Got start message type '%s'...", api->typeToText(inMsg->getType()).c_str());
359 for (val = 0; val < 10; val++) {
360 outMsg = new DataMessage();
361 outMsg->setInt("count", val);
362 // api->logPrint(1,"[%s] Posting msg %llu %s...", val, PrintTimeString(outMsg->getCreatedTime()).c_str());
363 api->postOutputMessage("Ball", outMsg);
364 }
365 start = GetTimeNow();
366 }
367 }
368
369 uint8 status;
370 if (GetTimeAgeMS(start) > 1000) {
371 for (uint32 nn=0; nn<steps; nn++) {
372 status = api->retrieve(retrievedMsgs, "r1");
373 if (status == QUERY_SUCCESS)
374 api->logPrint(1,"Successfully retrieved %u messages...", retrievedMsgs.size());
375 else if (status == QUERY_TIMEOUT)
376 api->logPrint(1,"Retrieve 'r1' timed out...");
377 else
378 api->logPrint(1,"Retrieve 'r1' failed (%u)...", status);
379
380 for (i = retrievedMsgs.begin(), e = retrievedMsgs.end(); i != e; i++) {
381 //if ((*i)->getInt("count", val))
382 // api->logPrint(1,"Count: %u", val);
383 delete(*i);
384 }
385 retrievedMsgs.clear();
386
387 status = api->retrieveIntegerParam(retrievedMsgs, "r2", 2, 8, 4);
388 if (status == QUERY_SUCCESS)
389 api->logPrint(1,"Successfully retrieved %u messages...", retrievedMsgs.size());
390 else if (status == QUERY_TIMEOUT)
391 api->logPrint(1,"Retrieve 'r2' timed out...");
392 else
393 api->logPrint(1,"Retrieve 'r2' failed (%u)...", status);
394
395 for (i = retrievedMsgs.begin(), e = retrievedMsgs.end(); i != e; i++) {
396 //if ((*i)->getInt("count", val))
397 // api->logPrint(1,"Count: %u", val);
398 delete(*i);
399 }
400 retrievedMsgs.clear();
401 utils::Sleep(100);
402
403 status = api->retrieveIntegerParam(retrievedMsgs, "r3", 0, 100, 100);
404 if (status == QUERY_SUCCESS)
405 api->logPrint(1,"Successfully retrieved %u messages...", retrievedMsgs.size());
406 else if (status == QUERY_TIMEOUT)
407 api->logPrint(1,"Retrieve 'r3' timed out...");
408 else
409 api->logPrint(1,"Retrieve 'r3' failed (%u)...", status);
410
411 for (i = retrievedMsgs.begin(), e = retrievedMsgs.end(); i != e; i++) {
412 //if ((*i)->getInt("count", val))
413 // api->logPrint(1,"Count: %u", val);
414 delete(*i);
415 }
416 retrievedMsgs.clear();
417
418 uint32 datasize = 0;
419 char* data = NULL;
420 char* result = NULL;
421 status = api->queryCatalog(&result, datasize, "MyFiles", "test", "read");
422 if (status == QUERY_SUCCESS)
423 api->logPrint(1,"Successfully retrieved %u bytes from file catalog...", datasize);
424 else if (status == QUERY_TIMEOUT)
425 api->logPrint(1,"Retrieve 'read' timed out for file catalog...");
426 else
427 api->logPrint(1,"Retrieve 'read' failed (%u) for file catalog...", status);
428 delete [] result;
429
430 data = utils::StringFormat(datasize, "Hello1 World");
431 status = api->queryCatalog(&result, datasize, "MyFiles", "test", "write", data, datasize);
432 if (status == QUERY_SUCCESS)
433 api->logPrint(1,"Successfully wrote %u bytes to file catalog...", datasize);
434 else if (status == QUERY_TIMEOUT)
435 api->logPrint(1,"Retrieve 'write' timed out for file catalog...");
436 else
437 api->logPrint(1,"Retrieve 'write' failed (%u) for file catalog...", status);
438 delete [] data;
439 delete [] result;
440
441 status = api->queryCatalog(&result, datasize, "MyData", "test", "read");
442 if (status == QUERY_SUCCESS)
443 api->logPrint(1,"Successfully read %u bytes from data catalog...", datasize);
444 else if (status == QUERY_TIMEOUT)
445 api->logPrint(1,"Retrieve 'read' timed out from data catalog...");
446 else
447 api->logPrint(1,"Retrieve 'read' failed (%u) from data catalog, ok if starting with a fresh catalog ...", status);
448 delete [] result;
449
450 data = utils::StringFormat(datasize, "Hello2 World");
451 status = api->queryCatalog(&result, datasize, "MyData", "test", "write", data, datasize);
452 if (status == QUERY_SUCCESS)
453 api->logPrint(1,"Successfully wrote %u bytes to data catalog...", datasize);
454 else if (status == QUERY_TIMEOUT)
455 api->logPrint(1,"Retrieve 'write' timed out to data catalog...");
456 else
457 api->logPrint(1,"Retrieve 'write' failed to data catalog (%u)...", status);
458 delete [] data;
459 delete [] result;
460
461 status = api->queryCatalog(&result, datasize, "MyData", "test", "read");
462 if (status == QUERY_SUCCESS)
463 api->logPrint(1,"Successfully read %u bytes from data catalog...", datasize);
464 else if (status == QUERY_TIMEOUT)
465 api->logPrint(1,"Retrieve 'read' timed out from data catalog...");
466 else
467 api->logPrint(1,"Retrieve 'read' failed (%u) from data catalog...", status);
468 delete [] result;
469 }
470
471 api->postOutputMessage("Done");
472
473 start = 0;
474 }
475 }
476
477 return 0;
478}
479
480
481bool TrackPlayerMessage::addEntry(const char* key, const char* value, const char* keytype) {
482 if (entryMap.find(key) != entryMap.end())
483 return false;
485 entry.key = key;
486 entry.value = value;
487 if (!keytype || (stricmp("String", keytype) == 0) || (stricmp("Text", keytype) == 0))
489 else if ((stricmp("Integer", keytype) == 0) || (stricmp("Int", keytype) == 0))
491 else if ((stricmp("Float", keytype) == 0) || (stricmp("Double", keytype) == 0))
493 else
495 entryMap[key] = entry;
496 return true;
497}
498
500 bool print = false;
501 if (api->hasParameter("Print"))
502 print = api->getParameterAsBool("Print");
503
504 XMLResults xmlResults;
505 std::string xml = api->getParameterString("componentsetup");
506 XMLNode entryNode, node, trackNode, mainNode = XMLNode::parseString(xml.c_str(), "setup", &xmlResults);
507
508 // display error message (if any)
509 if (xmlResults.error != eXMLErrorNone)
510 {
511 if (xmlResults.error == eXMLErrorFirstTagNotFound) {
512 api->logPrint(0, "Module setup error, main tag '<setup>' not found");
513 }
514 else {
515 api->logPrint(0, "Module setup parsing error at line %i, column %i:\n %s\n",
516 xmlResults.nLine, xmlResults.nColumn, XMLNode::getError(xmlResults.error));
517 }
518 }
519
520 uint64 startTime = GetTimeNow();
521 uint64 lastTriggerTime = 0;
522 uint32 nextDelayEntry = 0;
523 uint32 globalIntervalMS = 0;
524 uint32 trackIntervalMS = 0;
525 std::string autoTrack;
526
527 std::map<std::string, std::vector<TrackPlayerMessage> > trackMap;
528 std::vector<TrackPlayerMessage>* trackEntries;
530
531 TrackPlayerMessage entry;
532 uint32 lastOffset = 0;
533 int n = 0, t = 0, m = 0;
534 const char* str, *postName, *key, *value, *keytype, *name, *output;
535 uint32 timeMS, intervalMS, delayMS;
536
537 if (str = mainNode.getAttribute("intervalms")) {
538 if (utils::TextStartsWith(str, "+")) {
539 lastOffset = 0;
540 // interval needs calculating...
541 globalIntervalMS = utils::Ascii2Uint32(str + 1);
542 timeMS = 0;
543 // only from the __default__ track, i.e. not from posts inside a track tag
544 while (!(node = mainNode.getChildNode("post", n++)).isEmpty()) {
545 if (str = node.getAttribute("timems")) {
546 if (utils::TextStartsWith(str, "+")) {
547 timeMS = utils::Ascii2Uint32(str + 1);
548 timeMS += lastOffset;
549 }
550 else
551 timeMS = utils::Ascii2Uint32(str);
552 lastOffset = timeMS;
553 }
554 }
555 globalIntervalMS += timeMS;
556 api->logPrint(1, "Global track interval calculated: %ums", globalIntervalMS);
557 }
558 else {
559 globalIntervalMS = utils::Ascii2Uint32(str);
560 api->logPrint(1, "Global track interval: %ums", globalIntervalMS);
561 }
562 }
563
564 bool usingMainNode = false;
565 if ((trackNode = mainNode.getChildNode("track", t++)).isEmpty()) {
566 trackNode = mainNode;
567 usingMainNode = true;
568 }
569
570 std::string trackName;
571 do { // process track node
572 trackIntervalMS = 0;
573 name = trackNode.getAttribute("name");
574 if (!(name = trackNode.getAttribute("name")) || !strlen(name)) {
575 if (!usingMainNode)
576 continue;
577 trackName = "__default__";
578 api->logPrint(1, "Adding single global track (__default__)");
579 }
580 else {
581 trackName = name;
582 api->logPrint(1, "Adding track '%s'", trackName.c_str());
583 }
584
585 trackEntries = &trackMap[trackName];
586
587 if (str = trackNode.getAttribute("autostart"))
588 autoTrack = trackName;
589
590 if (!usingMainNode && (str = trackNode.getAttribute("intervalms"))) {
591 if (utils::TextStartsWith(str, "+")) {
592 lastOffset = 0;
593 // interval needs calculating...
594 trackIntervalMS = utils::Ascii2Uint32(str + 1);
595 timeMS = 0;
596 while (!(node = trackNode.getChildNode("post", n++)).isEmpty()) {
597 if (str = node.getAttribute("timems")) {
598 if (utils::TextStartsWith(str, "+")) {
599 timeMS = utils::Ascii2Uint32(str + 1);
600 timeMS += lastOffset;
601 }
602 else
603 timeMS = utils::Ascii2Uint32(str);
604 lastOffset = timeMS;
605 }
606 }
607 trackIntervalMS += timeMS;
608 api->logPrint(1, "Track '%s' interval calculated: %ums", trackName.c_str(), trackIntervalMS);
609 }
610 else {
611 trackIntervalMS = utils::Ascii2Uint32(str);
612 api->logPrint(1, "Track '%s' interval: %ums", trackName.c_str(), trackIntervalMS);
613 }
614 }
615
616 lastOffset = 0;
617 n = 0;
618 while (!(node = trackNode.getChildNode("post", n++)).isEmpty()) {
619 timeMS = intervalMS = delayMS = 0;
620 postName = node.getAttribute("name");
621 key = node.getAttribute("key");
622 value = node.getAttribute("value");
623 keytype = node.getAttribute("keytype");
624 output = node.getAttribute("output");
625
626 if (str = node.getAttribute("timems")) {
627 if (utils::TextStartsWith(str, "+")) {
628 timeMS = utils::Ascii2Uint32(str + 1);
629 timeMS += lastOffset;
630 }
631 else
632 timeMS = utils::Ascii2Uint32(str);
633 lastOffset = timeMS;
634 }
635 if (str = node.getAttribute("intervalms"))
636 intervalMS = utils::Ascii2Uint32(str);
637 else
638 intervalMS = 0;
639 if (str = node.getAttribute("delayms"))
640 delayMS = utils::Ascii2Uint32(str);
641 else
642 delayMS = 0;
643 if (!intervalMS && trackIntervalMS)
644 intervalMS = trackIntervalMS;
645 if (!intervalMS && globalIntervalMS)
646 intervalMS = globalIntervalMS;
647 if (!timeMS && intervalMS)
648 timeMS = intervalMS;
649 //if (!timeMS && !intervalMS && !delayMS)
650 // delayMS = 1000;
651
652 entry.delayMS = delayMS;
653 entry.timeMS = timeMS;
654 entry.nextTime = timeMS ? startTime + (timeMS * 1000) : 0;
655 entry.intervalMS = intervalMS;
656 entry.postName = postName ? postName : "";
658
659 if (output && (stricmp("Signal", output) == 0)) {
660 if (!postName || !strlen(postName)) {
661 api->logPrint(1, "Signal posts must specify a signal name, ignoring post entry");
662 continue;
663 }
665 }
666 else
668
669 if (triggerType == TrackPlayerMessage::NONE)
670 triggerType = entry.triggerType;
671 if (triggerType != entry.triggerType) {
672 if (triggerType == TrackPlayerMessage::TRIGGER)
673 api->logPrint(1, "Trigger track '%s' cannot use time posts, ignoring time post entry", trackName.c_str());
674 else
675 api->logPrint(1, "Time track '%s' cannot use trigger posts, ignoring trigger post entry", trackName.c_str());
676 continue;
677 }
678
679 entry.entryMap.clear();
680 if (key && value && strlen(key) && strlen(value))
681 entry.addEntry(key, value, keytype);
682 m = 0;
683 while (!(entryNode = node.getChildNode("user", m++)).isEmpty()) {
684 key = entryNode.getAttribute("key");
685 value = entryNode.getAttribute("value");
686 keytype = entryNode.getAttribute("keytype");
687 if (!keytype)
688 keytype = node.getAttribute("type");
689 if (key && value && strlen(key) && strlen(value))
690 entry.addEntry(key, value, keytype);
691 }
692 trackEntries->push_back(entry);
693 }
694 api->logPrint(1, "Added %u posts to track '%s'", trackEntries->size(), trackName.c_str());
695 trackEntries = NULL;
696 trackNode = mainNode.getChildNode("track", t++);
697 } while (!trackNode.isEmpty());
698
699 api->logPrint(1, "Added %u tracks in total", trackMap.size());
700
701 std::vector<TrackPlayerMessage>::iterator i, e;
702 std::map<std::string, TrackPlayerMessageEntry>::iterator iEntry, eEntry;
703
704 triggerType = TrackPlayerMessage::NONE;
705 trackName = "";
706
707 int32 c = 0;
708 uint64 now;
709 uint32 waitTime = 50;
710 DataMessage* inMsg, *msg;
711 const char* triggerName;
712 while (api->shouldContinue()) {
713 inMsg = NULL;
714 if (inMsg = api->waitForNewMessage(waitTime, triggerName)) {
715 //if (print)
716 // api->logPrint(1, "New message...");
717 if (stricmp("Start", triggerName) == 0) {
718 if (autoTrack.length()) {
719 trackEntries = &trackMap[autoTrack];
720 if (trackEntries) {
721 api->logPrint(1, "Auto starting track '%s'", autoTrack.c_str());
722 trackName = autoTrack;
723 }
724 }
725 lastTriggerTime = 0;
726 nextDelayEntry = 0;
727 triggerType = TrackPlayerMessage::NONE;
728 }
729 else if (stricmp("Restart", triggerName) == 0) {
730 lastTriggerTime = 0;
731 nextDelayEntry = 0;
732 if (trackEntries) {
733 i = trackEntries->begin();
734 e = trackEntries->end();
735 while (i != e) {
736 if ((*i).triggerType == TrackPlayerMessage::TIME) {
737 if ((*i).timeMS)
738 (*i).nextTime = GetTimeNow() + ((*i).timeMS * 1000);
739 }
740 i++;
741 }
742 if (trackEntries)
743 api->logPrint(1, "Auto starting track '%s'", autoTrack.c_str());
744 }
745 triggerType = TrackPlayerMessage::NONE;
746 }
747 else if (trackMap.find(triggerName) != trackMap.end()) {
748 trackEntries = &trackMap[triggerName];
749 trackName = triggerName;
750 //api->logPrint(1, "Changing track to: %s", triggerName);
751 lastTriggerTime = 0;
752 nextDelayEntry = 0;
753 i = trackEntries->begin();
754 e = trackEntries->end();
755 while (i != e) {
756 if ((*i).triggerType == TrackPlayerMessage::TIME) {
757 if ((*i).timeMS)
758 (*i).nextTime = GetTimeNow() + ((*i).timeMS * 1000);
759 }
760 i++;
761 }
762 triggerType = TrackPlayerMessage::NONE;
763 }
764 else {
765 if (!lastTriggerTime)
766 lastTriggerTime = GetTimeNow();
767 }
768 }
769
770 now = GetTimeNow();
771
772 if (trackEntries && trackEntries->size()) {
773 if (triggerType == TrackPlayerMessage::NONE) {
774 i = trackEntries->begin();
775 if (i != trackEntries->end()) {
776 triggerType = (*i).triggerType;
777 api->logPrint(1, "New track '%s' starting, track type: %s", trackName.c_str(), (triggerType == TrackPlayerMessage::TRIGGER) ? "Trigger" : "Time" );
778 }
779 }
780 if (triggerType == TrackPlayerMessage::TRIGGER) {
781 entry = trackEntries->at(nextDelayEntry);
782 if (lastTriggerTime && (entry.delayMS < (uint32)GetTimeAgeMS(lastTriggerTime))) {
783 if (!nextDelayEntry) {
784 msg = new DataMessage();
785 msg->setString("Track", trackName.c_str());
786 api->postOutputMessage("TrackStart", msg);
787 }
788 msg = new DataMessage();
789 iEntry = entry.entryMap.begin();
790 eEntry = entry.entryMap.end();
791 while (iEntry != eEntry) {
792 if ((*iEntry).second.key.length() && (*iEntry).second.value.length()) {
793 if ((*iEntry).second.entryType == TrackPlayerMessageEntry::INT)
794 msg->setInt((*iEntry).second.key.c_str(), utils::Ascii2Int64((*iEntry).second.value.c_str()));
795 else if ((*iEntry).second.entryType == TrackPlayerMessageEntry::FLOAT)
796 msg->setFloat((*iEntry).second.key.c_str(), utils::Ascii2Float64((*iEntry).second.value.c_str()));
797 else
798 msg->setString((*iEntry).second.key.c_str(), (*iEntry).second.value.c_str());
799 }
800 iEntry++;
801 }
802 if (entry.postName.length()) {
804 api->emitSignal(entry.postName.c_str(), msg);
805 if (print)
806 api->logPrint(1, "Triggered signal '%s' after delay of %ums", entry.postName.c_str(), entry.delayMS);
807 }
808 else {
809 api->postOutputMessage(entry.postName.c_str(), msg);
810 if (print)
811 api->logPrint(1, "Triggered post '%s' after delay of %ums", entry.postName.c_str(), entry.delayMS);
812 }
813 }
814 else {
816 api->postOutputMessage(NULL, msg);
817 if (print)
818 api->logPrint(1, "Triggered all posts after delay of %ums", entry.delayMS);
819 }
820 }
821 lastTriggerTime = 0;
822 nextDelayEntry++;
823 if (nextDelayEntry >= trackEntries->size()) {
824 msg = new DataMessage();
825 msg->setString("Track", trackName.c_str());
826 api->postOutputMessage("TrackEnd", msg);
827 nextDelayEntry = 0;
828 }
829 }
830 }
831 else { // TrackPlayerMessage::TIME
832 uint32 n = 0;
833 i = trackEntries->begin();
834 e = trackEntries->end();
835 while (i != e) {
836 n++;
837 if ((*i).nextTime && ((*i).nextTime < now)) {
838 if (n == 1) {
839 msg = new DataMessage();
840 msg->setString("Track", trackName.c_str());
841 api->postOutputMessage("TrackStart", msg);
842 }
843 msg = new DataMessage();
844 iEntry = (*i).entryMap.begin();
845 eEntry = (*i).entryMap.end();
846 while (iEntry != eEntry) {
847 if ((*iEntry).second.key.length() && (*iEntry).second.value.length()) {
848 if ((*iEntry).second.entryType == TrackPlayerMessageEntry::INT)
849 msg->setInt((*iEntry).second.key.c_str(), utils::Ascii2Int64((*iEntry).second.value.c_str()));
850 else if ((*iEntry).second.entryType == TrackPlayerMessageEntry::FLOAT)
851 msg->setFloat((*iEntry).second.key.c_str(), utils::Ascii2Float64((*iEntry).second.value.c_str()));
852 else
853 msg->setString((*iEntry).second.key.c_str(), (*iEntry).second.value.c_str());
854 }
855 iEntry++;
856 }
857
858 if ((*i).postName.length()) {
859 if ((*i).postType == TrackPlayerMessage::SIGNAL) {
860 api->emitSignal((*i).postName.c_str(), msg);
861 if (print) {
862 if (!(*i).intervalMS)
863 api->logPrint(1, "Triggered timed signal '%s' once at %s", (*i).postName.c_str(), PrintTimeDifString(GetTimeAge(startTime)).c_str());
864 else
865 api->logPrint(1, "Triggered timed signal '%s' at %s, next post in %s", (*i).postName.c_str(), PrintTimeDifString(GetTimeAge(startTime)).c_str(), PrintTimeDifString((*i).intervalMS * 1000).c_str());
866 }
867 }
868 else {
869 api->postOutputMessage((*i).postName.c_str(), msg);
870 if (print) {
871 if (!(*i).intervalMS)
872 api->logPrint(1, "Triggered timed post '%s' once at %s", (*i).postName.c_str(), PrintTimeDifString(GetTimeAge(startTime)).c_str());
873 else
874 api->logPrint(1, "Triggered timed post '%s' at %s, next post in %s", (*i).postName.c_str(), PrintTimeDifString(GetTimeAge(startTime)).c_str(), PrintTimeDifString((*i).intervalMS * 1000).c_str());
875 }
876 }
877 }
878 else {
879 if ((*i).postType == TrackPlayerMessage::MESSAGE) {
880 api->postOutputMessage(NULL, msg);
881 if (print) {
882 if (!(*i).intervalMS)
883 api->logPrint(1, "Triggered all timed posts once at %s", (*i).postName.c_str(), PrintTimeDifString(GetTimeAge(startTime)).c_str());
884 else
885 api->logPrint(1, "Triggered all timed posts at %s, next post in %s", (*i).postName.c_str(), PrintTimeDifString(GetTimeAge(startTime)).c_str(), PrintTimeDifString((*i).intervalMS*1000).c_str());
886 }
887 }
888 }
889
890 if (!(*i).intervalMS)
891 (*i).nextTime = 0;
892 else
893 (*i).nextTime += ((*i).intervalMS * 1000);
894
895 if (n == trackEntries->size()) {
896 msg = new DataMessage();
897 msg->setString("Track", trackName.c_str());
898 api->postOutputMessage("TrackEnd", msg);
899 }
900 }
901 i++;
902 }
903 }
904 }
905 }
906 return 0;
907}
908
910
911 DataMessage* inMsg, *msg, *resultMsg;
912 const char* triggerName;
913 uint64 start = GetTimeNow();
914
915 std::list<DataMessage*> retrievedMsgs;
916 std::list<DataMessage*>::iterator i, e;
917
918 while (api->shouldContinue()) {
919 if (inMsg = api->waitForNewMessage(100, triggerName)) {
920 start = GetTimeNow();
921 }
922
923 uint8 status;
924 if (GetTimeAgeMS(start) > 1000) {
925 msg = new DataMessage();
926 msg->setTag(10);
927 status = api->queryCatalog(&resultMsg, "Test", msg, 5000);
928 if (status == QUERY_SUCCESS) {
929 if (resultMsg)
930 api->logPrint(1, "Successfully retrieved reply msg from catalog...");
931 else
932 api->logPrint(1, "Successfully got reply from catalog...");
933 }
934 else if (status == QUERY_TIMEOUT)
935 api->logPrint(1, "Query timed out for catalog...");
936 else
937 api->logPrint(1, "Query failed (%u) for catalog...", status);
938 delete resultMsg;
939
940 start = GetTimeNow();
941 }
942 }
943 return 0;
944}
945
946
948
949 api->logPrint(1, "Started running...");
950
951 bool shouldReplace = api->getParameterAsBool("Replace");
952 bool shouldRotate = api->getParameterAsBool("Rotate");
953
954 uint64 start = GetTimeNow();
955
956 std::string outFile = api->getParameterString("OutputFile");
957 if (!outFile.length())
958 outFile = utils::StringFormat("%s.stats", PrintDateStringSortableDelimiter(start, "").c_str());
959
960 if (utils::DoesAFileExist(outFile.c_str())) {
961 if (shouldRotate) {
962 uint32 n = 1;
963 while (utils::DoesAFileExist(utils::StringFormat("%s.%u", outFile.c_str(), n).c_str()))
964 n++;
965 std::string newOutFile = utils::StringFormat("%s.%u", outFile.c_str(), n);
966 utils::MoveAFile(outFile.c_str(), newOutFile.c_str(), true);
967 }
968 else if (shouldReplace) {
969 utils::DeleteAFile(outFile.c_str(), true);
970 }
971 }
972
973 uint64 createdTime, sendTime, recvTime;
974 uint32 count = 0;
975 uint64 lastWrite = GetTimeNow();
976 std::string buffer;
977 const char* triggerName;
978 DataMessage* inMsg;
979 while (api->shouldContinue()) {
980 if (inMsg = api->waitForNewMessage(100, triggerName)) {
981 createdTime = inMsg->getCreatedTime();
982 sendTime = inMsg->getSendTime();
983 recvTime = inMsg->getRecvTime();
984 // add log output line
985 buffer += utils::StringFormat("%s,%s,%llu,%llu,%llu,%u,%u,%u,%u\n",
986 triggerName, PrintTimeSortableMicrosecString(recvTime).c_str(), recvTime,
987 recvTime - createdTime, recvTime - sendTime,
988 inMsg->data->cyclecputime, inMsg->data->cyclewalltime,
989 inMsg->data->chaincputime, inMsg->data->chainwalltime
990 );
991 }
992 count++;
993
994 if (count > 20) {
995 if (buffer.length())
996 utils::AppendToAFile(outFile.c_str(), buffer.c_str(), (uint32)buffer.length());
997 buffer.clear();
998 count = 0;
999 }
1000
1001 }
1002
1003 return 0;
1004}
1005
1007
1008 api->logPrint(1, "Started running...");
1009
1010 bool shouldRotate = api->getParameterAsBool("Rotate");
1011 std::string sourceDir = api->getParameterString("SourceDir");
1012 int64 intervalMS = api->getParameterInt("Interval");
1013 if (!intervalMS)
1014 intervalMS = 1000;
1015 int64 updateIntervalMS = api->getParameterInt("Interval");
1016 if (!updateIntervalMS)
1017 updateIntervalMS = 10000;
1018
1019 uint32 fileCount;
1020 char* files = utils::GetFileList(sourceDir.c_str(), "bmp", fileCount, true);
1021
1022 std::vector<std::string> fileNames;
1023 const char* name;
1024 uint32 n;
1025 for (n = 0; n<fileCount; n++) {
1026 name = files + (n*(MAXFILENAMELEN + 1));
1027 if (utils::DoesAFileExist(name))
1028 fileNames.push_back(name);
1029 }
1030 delete[] files;
1031
1032 DataMessage* msg;
1033 Bitmap* bitmap;
1034 uint32 count, postCount = 0, currentNamePos = 0;
1035 uint64 lastPost = GetTimeNow();
1036 uint64 lastUpdate = GetTimeNow();
1037 const char* triggerName;
1038 DataMessage* inMsg;
1039 while (api->shouldContinue()) {
1040 if (inMsg = api->waitForNewMessage(100, triggerName)) {
1041 }
1042 if ((currentNamePos < fileNames.size()) && (GetTimeAgeMS(lastPost) > intervalMS)) {
1043 name = fileNames[currentNamePos].c_str();
1044 if (utils::DoesAFileExist(name)) {
1045 bitmap = new Bitmap(name);
1046 if (bitmap->width > 0) {
1047 msg = new DataMessage();
1048 msg->setSerial(postCount++);
1049 msg->setData("VideoDataFrame", bitmap->data, bitmap->size);
1050 msg->setInt("Width", bitmap->width);
1051 msg->setInt("Height", bitmap->height);
1052 msg->setString("Filename", name);
1053 api->postOutputMessage("Image", msg);
1054 }
1055 else {
1056 api->logPrint(1, "File '%s' isn't a valid BMP file", name);
1057 }
1058 delete bitmap;
1059 }
1060 else {
1061 api->logPrint(1, "File '%s' doesn't exist", name);
1062 }
1063 currentNamePos++;
1064 if ((currentNamePos >= fileNames.size()) && shouldRotate)
1065 currentNamePos = 0;
1066 lastPost = GetTimeNow();
1067 }
1068
1069 if (GetTimeAgeMS(lastUpdate) > updateIntervalMS) {
1070 files = utils::GetFileList(sourceDir.c_str(), "bmp", count, true);
1071 if (count != fileCount) {
1072 api->logPrint(1, "File changes detected in '%s', updating list of files and starting over", sourceDir.c_str());
1073 fileNames.clear();
1074 for (n = 0; n<count; n++) {
1075 name = files + (n*(MAXFILENAMELEN + 1));
1076 if (utils::DoesAFileExist(name))
1077 fileNames.push_back(name);
1078 }
1079 fileCount = count;
1080 delete[] files;
1081 currentNamePos = 0;
1082 }
1083 lastUpdate = GetTimeNow();
1084 }
1085 }
1086
1087 return 0;
1088}
1089
1091
1092 std::string overrideState = api->getParameterString("OverrideState");
1093 std::string defaultState = api->getParameterString("DefaultState");
1094 if (!defaultState.length())
1095 defaultState = overrideState;
1096 std::string currentState = defaultState;
1097 std::string switchKey = api->getParameterString("SwitchKey");
1098 if (!switchKey.length()) {
1099 api->logPrint(1, "No SwitchKey parameter provided, cannot proceed without it");
1100 return -1;
1101 }
1102
1103 DataMessage* inMsg;
1104 const char* triggerName, *newState;
1105 std::string postName;
1106 while (api->shouldContinue()) {
1107 if (inMsg = api->waitForNewMessage(100, triggerName)) {
1108
1109 if (stricmp(triggerName, "Ready") == 0) {
1110 if (defaultState.length()) {
1111 if (api->hasCurrentPostName(defaultState.c_str()))
1112 api->postOutputMessage(defaultState.c_str());
1113 }
1114 else {
1115 if (api->hasCurrentPostName("NoState"))
1116 api->postOutputMessage("NoState");
1117 }
1118 }
1119 else if (stricmp(triggerName, "SwitchMessage") == 0) {
1120 if ((newState = inMsg->getString(switchKey.c_str())) != 0) {
1121 if (!strlen(newState)) {
1122 currentState.clear();
1123 if (api->hasCurrentPostName("NoState"))
1124 api->postOutputMessage("NoState", inMsg->copy());
1125 }
1126 else if (stricmp(currentState.c_str(), newState) != 0) {
1127 currentState = newState;
1128 if (api->hasCurrentPostName(newState))
1129 api->postOutputMessage(newState, inMsg->copy());
1130 }
1131 }
1132 }
1133 else {
1134 postName = utils::StringFormat("%s_%s", triggerName, currentState.c_str());
1135 if (api->hasCurrentPostName(postName.c_str()))
1136 api->postOutputMessage(postName.c_str(), inMsg->copy());
1137 else {
1138 if (overrideState.length()) {
1139 if (currentState.length())
1140 api->logPrint(1, "No post (%s) found for current state '%s', using override state instead (%s)",
1141 postName.c_str(), currentState.c_str(), overrideState.c_str());
1142 else
1143 api->logPrint(1, "No post (%s) found for current empty state, using override state instead (%s)",
1144 postName.c_str(), overrideState.c_str());
1145 postName = utils::StringFormat("%s_%s", triggerName, overrideState.c_str());
1146 if (api->hasCurrentPostName(postName.c_str()))
1147 api->postOutputMessage(postName.c_str(), inMsg->copy());
1148 else {
1149 api->logPrint(1, "No post (%s) found for override state '%s'",
1150 postName.c_str(), overrideState.c_str());
1151 }
1152 }
1153 else {
1154 if (currentState.length())
1155 api->logPrint(1, "No post (%s) found for current state '%s'", postName.c_str(), currentState.c_str());
1156 else
1157 api->logPrint(1, "No post (%s) found for current empty state", postName.c_str());
1158 }
1159 }
1160 }
1161 }
1162 }
1163 return 0;
1164}
1165
1167 DataMessage* inMsg;
1168 const char* triggerName;
1169 if (api->shouldContinue()) {
1170 if (inMsg = api->waitForNewMessage(0, triggerName)) {
1171 if (api->hasCurrentPostName(triggerName))
1172 api->postOutputMessage(triggerName, inMsg->copy());
1173 }
1174 }
1175 return 0;
1176}
1177
1178} // namespace cmlabs
#define QUERY_SUCCESS
The query succeeded.
Definition PsyAPI.h:60
#define QUERY_TIMEOUT
No reply within the timeout.
Definition PsyAPI.h:56
Built-in internal cranks and message-script playback structures.
static struct PsyContext NOCONTEXT
The empty/unset context (isValid() == false).
Definition Types.h:437
#define stricmp
Definition Utils.h:132
#define MAXFILENAMELEN
Definition Utils.h:89
32-bit RGBA raster image with drawing, compositing, scaling, BMP I/O and update-region tracking.
Definition Bitmap.h:139
uint32 height
Height in pixels.
Definition Bitmap.h:249
uint32 width
Width in pixels.
Definition Bitmap.h:248
uint32 size
Data buffer size in bytes (width*height*4).
Definition Bitmap.h:250
char * data
Pixel data, 32-bit RGBA, row-major top-down.
Definition Bitmap.h:251
The central Psyclone data container: a self-contained binary message with typed, named user entries.
bool setFloat(const char *key, float64 value)
setFloat(const char* key, float64 value)
uint32 getFrom()
getFrom() Get the sender id
bool setString(const char *key, const char *value)
setString(const char* key, const char* value)
bool setInt(const char *key, int64 value)
setInt(const char* key, int64 value)
bool setTag(uint32 tag)
setTag(uint32 tag)
PsyContext getContextChange()
getContextChange()
DataMessageHeader * data
Pointer to the message's flat memory block (header + user entries).
PsyType getType()
getType()
uint64 getCreatedTime()
getCreatedTime()
bool setData(const char *key, const char *value, uint32 size)
setData(const char* key, const char* value, uint32 size)
const char * getString(const char *key)
getString(const char* key)
bool setSerial(uint64 serial)
setSerial(uint64 serial)
uint64 getRecvTime()
getRecvTime()
uint64 getSendTime()
getSendTime()
DataMessage * copy()
copy() Creates a full deep copy of the message and returns it.
std::string getUserEntriesAsString()
getUserEntriesAsString() Returns the textual representation of the full message including all user en...
The API handle a component (crank) uses to talk to the Psyclone system.
Definition PsyAPI.h:82
PsyContext getCurrentTriggerContext()
Get the context of the current trigger, just retrieved using waitForNewMessage().
Definition PsyAPI.cpp:374
uint8 retrieveIntegerParam(std::list< DataMessage * > &result, const char *name, int64 startInteger, int64 endInteger=INT64_NOVALUE, uint32 maxcount=0, uint32 maxage=0, uint32 timeout=5000)
Used by a module to retrieve messages from a whiteboard.
Definition PsyAPI.cpp:815
std::string getParameterString(const char *name)
Read and return value of parameter by name.
Definition PsyAPI.h:848
std::string contextToText(PsyContext context)
Get textual representation of the context.
Definition PsyAPI.cpp:252
uint8 retrieve(std::list< DataMessage * > &result, const char *name, uint32 maxcount=0, uint32 maxage=0, uint32 timeout=5000)
Retrieve stored messages from a whiteboard, by named <retrieve> spec entry.
Definition PsyAPI.cpp:718
int64 getParameterInt(const char *name)
Read and return value of parameter by name.
Definition PsyAPI.h:872
bool getParameter(const char *name, char *val, uint32 maxSize)
Read string parameter into existing data chunk val, maximum size maxSize.
Definition PsyAPI.h:837
int32 postOutputMessage(const char *postName=NULL, DataMessage *msg=NULL)
Post the crank's output according to the spec's post entries.
Definition PsyAPI.cpp:521
bool shouldContinue()
Check whether the crank should keep running, or exit its loop.
Definition PsyAPI.cpp:87
bool emitSignal(const char *name, DataMessage *msg=NULL)
Emit a signal by its spec name.
Definition PsyAPI.cpp:654
bool hasCurrentPostName(const char *name)
Check to see if the post name is currently active - i.e.
Definition PsyAPI.cpp:207
bool hasParameter(const char *name)
Checks if a named parameter exists.
Definition PsyAPI.h:777
std::string getOtherModuleName(uint32 id)
Get the name of another module by id.
Definition PsyAPI.cpp:118
DataMessage * waitForSignal(const char *name, uint32 timeout, uint64 lastReceivedTime=0)
Wait for a signal (latest-value broadcast) by its spec name.
Definition PsyAPI.cpp:686
uint8 queryCatalog(char **result, uint32 &resultsize, const char *name, const char *query, const char *operation=NULL, const char *data=NULL, uint32 datasize=0, uint32 timeout=5000)
Send a query to another module or catalog by named <query> spec entry, receiving raw bytes back.
Definition PsyAPI.cpp:1071
bool getParameterAsBool(const char *name)
Read and interpret value of parameter by name as boolean True: String 'Yes', Integer and Float non-ze...
Definition PsyAPI.h:861
DataMessage * waitForNewMessage(uint32 ms)
Wait for the next trigger message from the component's input queue.
Definition PsyAPI.cpp:365
bool logPrint(int level, const char *formatstring,...)
Write a printf-style entry to the component's log (and the console when level is below the logging th...
Definition PsyAPI.cpp:1171
std::set< std::string > getCurrentPostNames()
Get a list of post names currently active - i.e.
Definition PsyAPI.cpp:220
std::string typeToText(PsyType type)
Get textual representation of the type.
Definition PsyAPI.cpp:248
std::string PrintDateStringSortableDelimiter(uint64 t, const char *del, bool local=true)
Definition PsyTime.cpp:712
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
Definition PsyTime.cpp:69
std::string PrintTimeDifString(uint64 t, bool us=true, bool ms=true)
Definition PsyTime.cpp:722
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
Definition PsyTime.cpp:35
int64 GetTimeAge(uint64 t)
Age of a timestamp relative to now.
Definition PsyTime.cpp:25
std::string PrintTimeSortableMicrosecString(uint64 t, bool local=true)
Sortable date+time with microseconds.
Definition PsyTime.cpp:749
bool TextStartsWith(const char *str, const char *start, bool caseSensitive=true)
Test whether str starts with start.
Definition Utils.cpp:7240
bool Sleep(uint32 ms)
Suspend the calling thread.
Definition Utils.cpp:2802
uint32 Ascii2Uint32(const char *ascii, uint32 start=0, uint32 end=0)
Parse an unsigned 32-bit decimal integer from a substring.
Definition Utils.cpp:7526
bool AppendToAFile(const char *filename, const char *data, uint32 length, bool binary=false)
Append to a file, creating it if missing.
Definition Utils.cpp:6905
char * GetFileList(const char *dirname, const char *ext, uint32 &count, bool fullpath, uint32 maxNameLen=256)
List files in a directory matching an extension.
Definition Utils.cpp:7293
bool MoveAFile(const char *oldfilename, const char *newfilename, bool force=false)
Move/rename a file.
Definition Utils.cpp:6957
bool DoesAFileExist(const char *filename)
Test whether a regular file exists.
Definition Utils.cpp:7359
bool DeleteAFile(const char *filename, bool force)
Delete a file.
Definition Utils.cpp:6933
std::string StringFormat(const char *format,...)
printf into a std::string.
Definition Utils.cpp:6626
int64 Ascii2Int64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a signed 64-bit decimal integer from a substring.
Definition Utils.cpp:7462
float64 Ascii2Float64(const char *ascii, uint32 start=0, uint32 end=0)
Parse a 64-bit float from a substring (decimal point, not locale dependent).
Definition Utils.cpp:7546
int8 Internal_QueryTest(PsyAPI *api)
Exercises query/queryReply round-trips.
int8 Internal_Pong(PsyAPI *api)
Latency test counterpart: answers pings.
int8 Internal_Print(PsyAPI *api)
Prints incoming messages to the console/log.
int8 Internal_Simple(PsyAPI *api)
Pass-through test crank: copies each incoming message to its posts.
@ eXMLErrorFirstTagNotFound
Definition xml_parser.h:142
@ eXMLErrorNone
Definition xml_parser.h:131
int8 Internal_SignalPong(PsyAPI *api)
Signal-based pong counterpart.
int8 Internal_StatsLog(PsyAPI *api)
Periodically logs system statistics.
int8 Internal_SignalPing(PsyAPI *api)
Signal-based ping test.
int8 Internal_MessageToggler(PsyAPI *api)
Alternates/toggles message output for testing.
int8 Internal_Shutdown(PsyAPI *api)
Initiates system shutdown when triggered.
int8 Internal_Ping(PsyAPI *api)
Latency test: posts pings, expects pongs.
int8 Internal_Time(PsyAPI *api)
Posts time information/timestamps.
int8 Internal_BitmapPoster(PsyAPI *api)
Posts test bitmap/image messages.
int8 Internal_MessageTypeConverter(PsyAPI *api)
Converts incoming messages to another type before reposting.
int8 Internal_MessageScript(PsyAPI *api)
Plays back scripted TrackPlayerMessage sequences.
int8 Internal_RetrieveTest(PsyAPI *api)
Exercises whiteboard retrieve calls.
Hierarchical execution-context identifier.
Definition Types.h:284
uint32 chaincputime
Accumulated CPU time across the whole causal message chain, in microseconds.
uint32 cyclewalltime
Wall-clock time spent in this cycle, in microseconds (profiling).
uint32 chainwalltime
Accumulated wall time across the whole causal message chain, in microseconds.
uint32 cyclecputime
CPU time spent processing the triggering message in this cycle, in microseconds (profiling).
One key/value entry of a scripted TrackPlayerMessage.
Definition PsyInternal.h:20
std::string key
Entry key placed in the generated message.
Definition PsyInternal.h:22
@ TEXT
Definition PsyInternal.h:21
@ INT
Definition PsyInternal.h:21
@ FLOAT
Definition PsyInternal.h:21
std::string value
Entry value (textual; converted per entryType).
Definition PsyInternal.h:23
enum cmlabs::TrackPlayerMessageEntry::EntryType entryType
Data type of the value string.
One scripted post/signal action for the message-script player (Internal_MessageScript).
Definition PsyInternal.h:31
std::string postName
Post/signal name to use.
Definition PsyInternal.h:34
enum cmlabs::TrackPlayerMessage::PostType postType
Send as a posted message or as a signal.
uint32 timeMS
Time offset in ms for time-triggered sends.
Definition PsyInternal.h:37
bool addEntry(const char *key, const char *value, const char *keytype=NULL)
Add an entry to the message.
uint32 intervalMS
Repeat interval in ms; 0 for one-shot.
Definition PsyInternal.h:38
uint64 nextTime
Next scheduled send time (PsyTime µs), maintained by the player.
Definition PsyInternal.h:36
std::map< std::string, TrackPlayerMessageEntry > entryMap
Entries copied into each generated message.
Definition PsyInternal.h:39
enum cmlabs::TrackPlayerMessage::TriggerType triggerType
What causes the send: incoming trigger, timer, or nothing.
uint32 delayMS
Delay in ms before sending (after the trigger).
Definition PsyInternal.h:35
XMLAttribute getAttribute(int i=0) const
XMLNode getChildNode(int i=0) const
char isEmpty() const
enum XMLError error
Definition xml_parser.h:168