#include "LoggerFactory.hpp"
#include "Feedlet.hpp"
#include "TimerEvent.hpp"
#include "ValueEvent.hpp"
#include "PortLibrary.hpp"
#include
#include
#ifndef M_PI
#define M_PI 3.1415926
#endif
/* --------------------- INSTRUMENTATION START ------------------------- */
ILogger* logger;
IFeedlet* signalFeedlet;
IFeedlet* activityFeedlet;
IFeedlet* midiFeedlet;
TimerEvent* activityTimer;
ValueEvent* signalET;
ValueEvent* loudnessET;
PortLibrary *portLibrary;
EventType *midiEventET;
void instrumentationInit(char* fileNameOrPortNumber, int durationSeconds) {
portLibrary = new PortLibrary();
// Create a logger
int portNumber = atoi(fileNameOrPortNumber);
const int numEventTypeSpaces = 1;
EventTypeSpaceVersion* eventTypeSpaces[numEventTypeSpaces];
eventTypeSpaces[0] = EventTypeSpaceVersion::newInstance(portLibrary, "com.ibm.tuningfork.music", 1);
if (portNumber > 0) {
logger = LoggerFactory::makeServerLogger(portLibrary, portNumber, eventTypeSpaces, numEventTypeSpaces);
} else {
if (strcmp(fileNameOrPortNumber, "none") == 0) {
logger = LoggerFactory::makeNullLogger(portLibrary);
} else {
logger = LoggerFactory::makeFileLogger(portLibrary, fileNameOrPortNumber, eventTypeSpaces, numEventTypeSpaces);
}
if (logger == NULL) {
fprintf(stderr, "Could not open file %s for writing.\n", fileNameOrPortNumber);
exit(-1);
}
}
// Add some properties
char valueBuffer[20];
sprintf(valueBuffer, "%d sec", durationSeconds);
logger->addProperty("Program Run Length", valueBuffer);
// Add some event types - two for each type of threads
activityTimer = logger->makeTimerEvent("Activity");
signalET = logger->makeValueEvent("Signal Value");
loudnessET = logger->makeValueEvent("Loudness");
EventAttribute* eventAttrs[4];
eventAttrs[0] = EventAttribute::newInstance(portLibrary, "channel", "channel", logger->getInt(portLibrary));
eventAttrs[1] = EventAttribute::newInstance(portLibrary, "status", "status", logger->getInt(portLibrary));
eventAttrs[2] = EventAttribute::newInstance(portLibrary, "data1", "data1", logger->getInt(portLibrary));
eventAttrs[3] = EventAttribute::newInstance(portLibrary, "data2", "data2", logger->getInt(portLibrary));
midiEventET = EventType::newInstance(portLibrary, logger, "MIDI Events", "MIDI Events", 4, eventAttrs);
logger->addEventType(midiEventET);
midiFeedlet = logger->makeFeedlet();
midiFeedlet->setName("midi");
signalFeedlet = logger->makeFeedlet();
signalFeedlet->setName("signal feedlet");
activityFeedlet = logger->makeFeedlet();
activityFeedlet->setName("activity");
}
void setSignal(double amplitude, double loudness) {
signalET->addValue(amplitude); // ---------------- INSTRUMENTATION -------------------
loudnessET->addValue(loudness); // ---------------- INSTRUMENTATION -------------------
// Do some work related to setting signal - we simulate by sleeping briefly
portLibrary->sleep(1);
}
void runOneInterval(int timeMs) {
activityTimer->start(); // ---------------------- INSTRUMENTATION -------------------
portLibrary->sleep(timeMs);
activityTimer->stop(); // --------------------- INSTRUMENTATION -------------------
}
int runMidi(void* durSec) {
int durationSec = (int) durSec;
midiFeedlet->bindToCurrentThread(); // --------------------- INSTRUMENTATION -------------------
// Now make some MIDI events
int channel = 0;
int status = 0x90; // on
int data1 = 0x30; // pitch
int data2 = 64; // velocity
U_64 start = portLibrary->nanoTimeCoarse();
while (true) {
double timeSec = (portLibrary->nanoTimeCoarse() - start) / 1e9;
I_32 ivals[4];
ivals[0] = channel;
ivals[1] = status;
ivals[2] = data1;
ivals[3] = data2;
midiFeedlet->addEvent(midiEventET, 4, ivals, 0, NULL, 0, NULL, 0, NULL);
if (status == 0x90) {
status = 0x80;
} else {
status = 0x90;
if (++data1 > 0x60) {
data1 = 0x30;
}
}
if (timeSec > durationSec) {
break;
}
portLibrary->sleep(100);
}
}
int runSignal(void *durSec) {
int durationSec = (int) durSec;
signalFeedlet->bindToCurrentThread(); // --------------------- INSTRUMENTATION -------------------
// Now make some events
double pitchFrequency = 5;
double loudnessFrequency = 0.5;
U_64 start = portLibrary->nanoTimeCoarse();
while (true) {
double timeSec = (portLibrary->nanoTimeCoarse() - start) / 1e9;
double pitchPosition = timeSec * pitchFrequency * 2 * M_PI;
double loudnessPosition = timeSec * loudnessFrequency * 2 * M_PI;
double loudness = 1 + 0.5 * sin(loudnessPosition);
double amplitude = sin(pitchPosition) * loudness;
setSignal(amplitude, loudness);
if (timeSec > durationSec) {
break;
}
}
return 0;
}
int runIntervals(void* durSec) {
int durationSec = (int) durSec;
activityFeedlet->bindToCurrentThread(); // --------------------- INSTRUMENTATION -------------------
double onMaxLenMs = 200; // activity's length is from a uniform distribution from 0 to onMaxLen
double offMaxLenMs = 500; // time until next activity is from a uniform distribution from 0 to onMaxLen
U_64 start = portLibrary->nanoTimeCoarse();
while (true) {
double r1 = rand() / ((double) RAND_MAX);
double r2 = rand() / ((double) RAND_MAX);
int onLenMs = (int) (onMaxLenMs * r1);
int offLenMs = (int) (offMaxLenMs * r2);
runOneInterval(onLenMs);
portLibrary->sleep(offLenMs);
double timeSec = (portLibrary->nanoTimeCoarse() - start) / 1e9;
if (timeSec > durationSec) {
break;
}
}
return 0;
}
int main(int argc, char **args) {
/* ------- INSTRUMENTATION MODIFICATION START --------- */
if (argc != 3) {
fprintf(stderr, "Usage: Client ");
return -1;
}
char* duration = args[1];
int durationSeconds = atoi(duration);
if (durationSeconds == 0) {
durationSeconds = 60; // Default is 60 seconds
fprintf(stderr, "Could not parse duration argument. Using %d seconds.", durationSeconds);
}
char* fileNameOrPortNumber = args[2]; // INSRUMENTATION
instrumentationInit(fileNameOrPortNumber, durationSeconds); // INSRUMENTATION
/* ------- INSTRUMENTATION MODIFICATION END --------- */
// Run 2 threads that make events for some time
fprintf(stderr, "Running 2 threads for %d seconds.\n", durationSeconds);
portLibrary->runOnNewThread(runSignal, (void*) durationSeconds);
portLibrary->runOnNewThread(runIntervals, (void*) durationSeconds);
portLibrary->runOnNewThread(runMidi, (void*) durationSeconds);
// This is only an approximation - not synchronized with event-generating threads
portLibrary->sleep(durationSeconds * 1000);
logger->flush(); /* INSTRUMENTATION */
// Flush buffered data
fprintf(stderr, "Done.");
}
}