Big Mouth Billy Bass automation library
song.cpp@6:ea8136eb6976, 2013-06-20 (annotated)
- Committer:
- bikeNomad
- Date:
- Thu Jun 20 03:04:36 2013 +0000
- Revision:
- 6:ea8136eb6976
- Parent:
- 5:869b3711bdb3
- Child:
- 7:dba9221acf48
Added diagnostic output and manual (keyboard) testing
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bikeNomad | 0:84aaade0de8f | 1 | #include <stdlib.h> |
bikeNomad | 0:84aaade0de8f | 2 | #include <string.h> |
bikeNomad | 0:84aaade0de8f | 3 | #include <stdio.h> |
bikeNomad | 0:84aaade0de8f | 4 | #include <ctype.h> |
bikeNomad | 0:84aaade0de8f | 5 | #include <algorithm> |
bikeNomad | 0:84aaade0de8f | 6 | |
bikeNomad | 0:84aaade0de8f | 7 | #include "billybass.hpp" |
bikeNomad | 0:84aaade0de8f | 8 | #include "song.hpp" |
bikeNomad | 0:84aaade0de8f | 9 | |
bikeNomad | 0:84aaade0de8f | 10 | // class static |
bikeNomad | 0:84aaade0de8f | 11 | char const Song::directoryName[ BASS_DIRECTORY_LENGTH + 1 ] = BASS_DIRECTORY; |
bikeNomad | 0:84aaade0de8f | 12 | // class static |
bikeNomad | 0:84aaade0de8f | 13 | char const *Song::textExtension = "txt"; |
bikeNomad | 0:84aaade0de8f | 14 | // class static |
bikeNomad | 0:84aaade0de8f | 15 | char const *Song::sampleExtension = "raw"; |
bikeNomad | 0:84aaade0de8f | 16 | // class static |
bikeNomad | 0:84aaade0de8f | 17 | unsigned const Song::NO_FISH = MAX_FISH + 1; |
bikeNomad | 4:f009306756b3 | 18 | // one song, re-used |
bikeNomad | 4:f009306756b3 | 19 | Song Song::theSong; |
bikeNomad | 0:84aaade0de8f | 20 | |
bikeNomad | 0:84aaade0de8f | 21 | // _name is relative to BASS_DIRECTORY |
bikeNomad | 0:84aaade0de8f | 22 | // class static |
bikeNomad | 0:84aaade0de8f | 23 | Song *Song::newSong(char const *_name) |
bikeNomad | 0:84aaade0de8f | 24 | { |
bikeNomad | 4:f009306756b3 | 25 | Song *s = &theSong; |
bikeNomad | 4:f009306756b3 | 26 | s->reset(); |
bikeNomad | 0:84aaade0de8f | 27 | if (! s->parseFilename(_name)) { |
bikeNomad | 3:6c91a6232c4a | 28 | fprintf(stderr, "parseFilename(%s) failed\r\n", _name); |
bikeNomad | 0:84aaade0de8f | 29 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 30 | } |
bikeNomad | 3:6c91a6232c4a | 31 | fprintf(stderr, "parsed filename OK\r\n"); |
bikeNomad | 0:84aaade0de8f | 32 | if (! s->readActions()) { |
bikeNomad | 3:6c91a6232c4a | 33 | fprintf(stderr, "readActions(%s) failed\r\n", _name); |
bikeNomad | 0:84aaade0de8f | 34 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 35 | } |
bikeNomad | 0:84aaade0de8f | 36 | |
bikeNomad | 0:84aaade0de8f | 37 | return s; |
bikeNomad | 0:84aaade0de8f | 38 | |
bikeNomad | 0:84aaade0de8f | 39 | on_error: |
bikeNomad | 0:84aaade0de8f | 40 | return 0; |
bikeNomad | 0:84aaade0de8f | 41 | } |
bikeNomad | 0:84aaade0de8f | 42 | |
bikeNomad | 0:84aaade0de8f | 43 | bool Song::parseFilename(char const *_name) |
bikeNomad | 0:84aaade0de8f | 44 | { |
bikeNomad | 0:84aaade0de8f | 45 | if (strlen(_name) > MAX_BASENAME_LENGTH) |
bikeNomad | 0:84aaade0de8f | 46 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 47 | |
bikeNomad | 0:84aaade0de8f | 48 | strcpy(fullname, directoryName); |
bikeNomad | 0:84aaade0de8f | 49 | basename = fullname + BASS_DIRECTORY_LENGTH; |
bikeNomad | 0:84aaade0de8f | 50 | *basename++ = '/'; |
bikeNomad | 0:84aaade0de8f | 51 | strcpy(basename, _name); |
bikeNomad | 0:84aaade0de8f | 52 | |
bikeNomad | 0:84aaade0de8f | 53 | char *p; |
bikeNomad | 0:84aaade0de8f | 54 | long n = strtol(_name, &p, 10); |
bikeNomad | 0:84aaade0de8f | 55 | if (*p != '_' || n <= 0) |
bikeNomad | 0:84aaade0de8f | 56 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 57 | |
bikeNomad | 0:84aaade0de8f | 58 | sequenceNumber = (unsigned)(n - 1); |
bikeNomad | 0:84aaade0de8f | 59 | |
bikeNomad | 0:84aaade0de8f | 60 | p++; // skip underscore |
bikeNomad | 0:84aaade0de8f | 61 | n = strtol(p, &p, 10); |
bikeNomad | 0:84aaade0de8f | 62 | if (*p != '_' || n <= 0 || n > MAX_FISH) |
bikeNomad | 0:84aaade0de8f | 63 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 64 | |
bikeNomad | 0:84aaade0de8f | 65 | whichFish = (unsigned)(n - 1); |
bikeNomad | 0:84aaade0de8f | 66 | |
bikeNomad | 0:84aaade0de8f | 67 | p = strrchr(basename, '.'); |
bikeNomad | 0:84aaade0de8f | 68 | if (!p) |
bikeNomad | 0:84aaade0de8f | 69 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 70 | |
bikeNomad | 0:84aaade0de8f | 71 | extension = p+1; |
bikeNomad | 0:84aaade0de8f | 72 | |
bikeNomad | 0:84aaade0de8f | 73 | if (strcasecmp(extension, sampleExtension)) |
bikeNomad | 0:84aaade0de8f | 74 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 75 | |
bikeNomad | 0:84aaade0de8f | 76 | return true; |
bikeNomad | 0:84aaade0de8f | 77 | |
bikeNomad | 0:84aaade0de8f | 78 | on_error: |
bikeNomad | 0:84aaade0de8f | 79 | whichFish = NO_FISH; |
bikeNomad | 0:84aaade0de8f | 80 | basename = 0; |
bikeNomad | 0:84aaade0de8f | 81 | return false; |
bikeNomad | 0:84aaade0de8f | 82 | } |
bikeNomad | 0:84aaade0de8f | 83 | |
bikeNomad | 0:84aaade0de8f | 84 | bool Song::readActions() |
bikeNomad | 0:84aaade0de8f | 85 | { |
bikeNomad | 3:6c91a6232c4a | 86 | fprintf(stderr, "reading actions of %s\r\n", getTextFileName()); |
bikeNomad | 1:9b1f3eb204ac | 87 | |
bikeNomad | 0:84aaade0de8f | 88 | FILE *txtfile = fopen(getTextFileName(), "r"); |
bikeNomad | 0:84aaade0de8f | 89 | if (!txtfile) { |
bikeNomad | 3:6c91a6232c4a | 90 | fprintf(stderr, "can't open %s\r\n", getTextFileName()); |
bikeNomad | 0:84aaade0de8f | 91 | return false; |
bikeNomad | 1:9b1f3eb204ac | 92 | } else |
bikeNomad | 3:6c91a6232c4a | 93 | fprintf(stderr, "opened %s OK\r\n", getTextFileName()); |
bikeNomad | 0:84aaade0de8f | 94 | bool retval = false; |
bikeNomad | 0:84aaade0de8f | 95 | |
bikeNomad | 0:84aaade0de8f | 96 | BillyBass *bass = BillyBass::bassNumber(whichFish); |
bikeNomad | 0:84aaade0de8f | 97 | if (!bass) { |
bikeNomad | 3:6c91a6232c4a | 98 | fprintf(stderr, "No bass!\r\n"); |
bikeNomad | 0:84aaade0de8f | 99 | goto done; |
bikeNomad | 0:84aaade0de8f | 100 | } |
bikeNomad | 0:84aaade0de8f | 101 | |
bikeNomad | 0:84aaade0de8f | 102 | // read actions from file |
bikeNomad | 5:869b3711bdb3 | 103 | static char textFileBuffer[ MAX_TEXT_FILE_LENGTH ]; |
bikeNomad | 1:9b1f3eb204ac | 104 | memset(textFileBuffer, 0, sizeof(textFileBuffer)); |
bikeNomad | 1:9b1f3eb204ac | 105 | int nread = fread(textFileBuffer, 1, sizeof(textFileBuffer), txtfile); |
bikeNomad | 3:6c91a6232c4a | 106 | // fprintf(stderr, "Read %d bytes\r\n", nread); |
bikeNomad | 1:9b1f3eb204ac | 107 | if (nread <= 0 || nread == sizeof(textFileBuffer)) { |
bikeNomad | 1:9b1f3eb204ac | 108 | goto done; |
bikeNomad | 1:9b1f3eb204ac | 109 | } |
bikeNomad | 0:84aaade0de8f | 110 | unsigned line = 1; |
bikeNomad | 1:9b1f3eb204ac | 111 | for (char *actionLine = strtok(textFileBuffer, "\r\n"); |
bikeNomad | 1:9b1f3eb204ac | 112 | actionLine; |
bikeNomad | 1:9b1f3eb204ac | 113 | actionLine = strtok(0, "\r\n"), line++) { |
bikeNomad | 1:9b1f3eb204ac | 114 | char *p; |
bikeNomad | 0:84aaade0de8f | 115 | float startTime = strtof(actionLine, &p); |
bikeNomad | 0:84aaade0de8f | 116 | if (p == actionLine) |
bikeNomad | 0:84aaade0de8f | 117 | goto done; |
bikeNomad | 0:84aaade0de8f | 118 | |
bikeNomad | 0:84aaade0de8f | 119 | char *q; |
bikeNomad | 0:84aaade0de8f | 120 | float endTime = strtof(p, &q); |
bikeNomad | 0:84aaade0de8f | 121 | if (q == p) |
bikeNomad | 0:84aaade0de8f | 122 | goto done; |
bikeNomad | 0:84aaade0de8f | 123 | |
bikeNomad | 0:84aaade0de8f | 124 | char const *outName; |
bikeNomad | 1:9b1f3eb204ac | 125 | DigitalOut *out = bass->outputNamed(++q, &outName); |
bikeNomad | 0:84aaade0de8f | 126 | if (!out) { |
bikeNomad | 3:6c91a6232c4a | 127 | fprintf(stderr, "%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q); |
bikeNomad | 0:84aaade0de8f | 128 | goto done; |
bikeNomad | 0:84aaade0de8f | 129 | } |
bikeNomad | 3:6c91a6232c4a | 130 | // fprintf(stderr, "%d add %f %f %s\r\n", line, startTime, endTime, outName); |
bikeNomad | 0:84aaade0de8f | 131 | |
bikeNomad | 6:ea8136eb6976 | 132 | addAction(startTime, bass->onState(), out, toupper(outName[0])); |
bikeNomad | 6:ea8136eb6976 | 133 | addAction(endTime, bass->offState(), out, outName[0]); |
bikeNomad | 0:84aaade0de8f | 134 | } |
bikeNomad | 4:f009306756b3 | 135 | fprintf(stderr, "Added %d actions\r\n", numActions); |
bikeNomad | 4:f009306756b3 | 136 | qsort(actions, numActions, sizeof(Action), &Action::compare); |
bikeNomad | 0:84aaade0de8f | 137 | retval = true; |
bikeNomad | 0:84aaade0de8f | 138 | |
bikeNomad | 0:84aaade0de8f | 139 | done: |
bikeNomad | 1:9b1f3eb204ac | 140 | |
bikeNomad | 0:84aaade0de8f | 141 | fclose(txtfile); |
bikeNomad | 0:84aaade0de8f | 142 | return retval; |
bikeNomad | 0:84aaade0de8f | 143 | } |
bikeNomad | 4:f009306756b3 | 144 |