Big Mouth Billy Bass automation library
song.cpp
- Committer:
- bikeNomad
- Date:
- 2013-06-19
- Revision:
- 5:869b3711bdb3
- Parent:
- 4:f009306756b3
- Child:
- 6:ea8136eb6976
File content as of revision 5:869b3711bdb3:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <algorithm>
#include "billybass.hpp"
#include "song.hpp"
// class static
char const Song::directoryName[ BASS_DIRECTORY_LENGTH + 1 ] = BASS_DIRECTORY;
// class static
char const *Song::textExtension = "txt";
// class static
char const *Song::sampleExtension = "raw";
// class static
unsigned const Song::NO_FISH = MAX_FISH + 1;
// one song, re-used
Song Song::theSong;
// _name is relative to BASS_DIRECTORY
// class static
Song *Song::newSong(char const *_name)
{
Song *s = &theSong;
s->reset();
if (! s->parseFilename(_name)) {
fprintf(stderr, "parseFilename(%s) failed\r\n", _name);
goto on_error;
}
fprintf(stderr, "parsed filename OK\r\n");
if (! s->readActions()) {
fprintf(stderr, "readActions(%s) failed\r\n", _name);
goto on_error;
}
return s;
on_error:
return 0;
}
bool Song::parseFilename(char const *_name)
{
if (strlen(_name) > MAX_BASENAME_LENGTH)
goto on_error;
strcpy(fullname, directoryName);
basename = fullname + BASS_DIRECTORY_LENGTH;
*basename++ = '/';
strcpy(basename, _name);
char *p;
long n = strtol(_name, &p, 10);
if (*p != '_' || n <= 0)
goto on_error;
sequenceNumber = (unsigned)(n - 1);
p++; // skip underscore
n = strtol(p, &p, 10);
if (*p != '_' || n <= 0 || n > MAX_FISH)
goto on_error;
whichFish = (unsigned)(n - 1);
p = strrchr(basename, '.');
if (!p)
goto on_error;
extension = p+1;
if (strcasecmp(extension, sampleExtension))
goto on_error;
return true;
on_error:
whichFish = NO_FISH;
basename = 0;
return false;
}
bool Song::readActions()
{
fprintf(stderr, "reading actions of %s\r\n", getTextFileName());
FILE *txtfile = fopen(getTextFileName(), "r");
if (!txtfile) {
fprintf(stderr, "can't open %s\r\n", getTextFileName());
return false;
} else
fprintf(stderr, "opened %s OK\r\n", getTextFileName());
bool retval = false;
BillyBass *bass = BillyBass::bassNumber(whichFish);
if (!bass) {
fprintf(stderr, "No bass!\r\n");
goto done;
}
// read actions from file
static char textFileBuffer[ MAX_TEXT_FILE_LENGTH ];
memset(textFileBuffer, 0, sizeof(textFileBuffer));
int nread = fread(textFileBuffer, 1, sizeof(textFileBuffer), txtfile);
// fprintf(stderr, "Read %d bytes\r\n", nread);
if (nread <= 0 || nread == sizeof(textFileBuffer)) {
goto done;
}
unsigned line = 1;
for (char *actionLine = strtok(textFileBuffer, "\r\n");
actionLine;
actionLine = strtok(0, "\r\n"), line++) {
char *p;
float startTime = strtof(actionLine, &p);
if (p == actionLine)
goto done;
char *q;
float endTime = strtof(p, &q);
if (q == p)
goto done;
char const *outName;
DigitalOut *out = bass->outputNamed(++q, &outName);
if (!out) {
fprintf(stderr, "%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q);
goto done;
}
// fprintf(stderr, "%d add %f %f %s\r\n", line, startTime, endTime, outName);
addAction(startTime, bass->onState(), out);
addAction(endTime, bass->offState(), out);
}
fprintf(stderr, "Added %d actions\r\n", numActions);
qsort(actions, numActions, sizeof(Action), &Action::compare);
retval = true;
done:
fclose(txtfile);
return retval;
}
Ned Konz