Big Mouth Billy Bass automation library
song.cpp@0:84aaade0de8f, 2013-06-17 (annotated)
- Committer:
- bikeNomad
- Date:
- Mon Jun 17 22:17:59 2013 +0000
- Revision:
- 0:84aaade0de8f
- Child:
- 1:9b1f3eb204ac
Mostly working; hangs when reading actions
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 | 0:84aaade0de8f | 18 | // class static |
bikeNomad | 0:84aaade0de8f | 19 | std::list<Song*> Song::songs; |
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 | 0:84aaade0de8f | 25 | Song *s = new Song; |
bikeNomad | 0:84aaade0de8f | 26 | if (!s) { |
bikeNomad | 0:84aaade0de8f | 27 | pc.printf("new Song == 0\r\n"); |
bikeNomad | 0:84aaade0de8f | 28 | return 0; |
bikeNomad | 0:84aaade0de8f | 29 | } |
bikeNomad | 0:84aaade0de8f | 30 | if (! s->parseFilename(_name)) { |
bikeNomad | 0:84aaade0de8f | 31 | pc.printf("parseFilename(%s) failed\r\n", _name); |
bikeNomad | 0:84aaade0de8f | 32 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 33 | } |
bikeNomad | 0:84aaade0de8f | 34 | if (! s->readActions()) { |
bikeNomad | 0:84aaade0de8f | 35 | pc.printf("readActions(%s) failed\r\n", _name); |
bikeNomad | 0:84aaade0de8f | 36 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 37 | } |
bikeNomad | 0:84aaade0de8f | 38 | songs.push_back(s); |
bikeNomad | 0:84aaade0de8f | 39 | |
bikeNomad | 0:84aaade0de8f | 40 | return s; |
bikeNomad | 0:84aaade0de8f | 41 | |
bikeNomad | 0:84aaade0de8f | 42 | on_error: |
bikeNomad | 0:84aaade0de8f | 43 | delete s; |
bikeNomad | 0:84aaade0de8f | 44 | return 0; |
bikeNomad | 0:84aaade0de8f | 45 | } |
bikeNomad | 0:84aaade0de8f | 46 | |
bikeNomad | 0:84aaade0de8f | 47 | // class static |
bikeNomad | 0:84aaade0de8f | 48 | void Song::clearAllSongs() |
bikeNomad | 0:84aaade0de8f | 49 | { |
bikeNomad | 0:84aaade0de8f | 50 | for (std::list<Song *>::const_iterator song = songs.begin(); song != songs.end(); song++) |
bikeNomad | 0:84aaade0de8f | 51 | delete *song; |
bikeNomad | 0:84aaade0de8f | 52 | songs.clear(); |
bikeNomad | 0:84aaade0de8f | 53 | } |
bikeNomad | 0:84aaade0de8f | 54 | |
bikeNomad | 0:84aaade0de8f | 55 | // class static |
bikeNomad | 0:84aaade0de8f | 56 | unsigned Song::readAllSongs(DIR *bassDir) |
bikeNomad | 0:84aaade0de8f | 57 | { |
bikeNomad | 0:84aaade0de8f | 58 | if (!bassDir) return 0; |
bikeNomad | 0:84aaade0de8f | 59 | clearAllSongs(); |
bikeNomad | 0:84aaade0de8f | 60 | |
bikeNomad | 0:84aaade0de8f | 61 | while (dirent *dir = bassDir->readdir()) { |
bikeNomad | 0:84aaade0de8f | 62 | pc.printf("Reading %s\r\n", dir->d_name); |
bikeNomad | 0:84aaade0de8f | 63 | unsigned namelen = strlen(dir->d_name); |
bikeNomad | 0:84aaade0de8f | 64 | if (namelen > 9 && !strcasecmp(dir->d_name + namelen - 3, sampleExtension)) { |
bikeNomad | 0:84aaade0de8f | 65 | Song *song = Song::newSong(dir->d_name); |
bikeNomad | 0:84aaade0de8f | 66 | if (!song) { |
bikeNomad | 0:84aaade0de8f | 67 | pc.printf("ERROR reading %s\r\n", dir->d_name); |
bikeNomad | 0:84aaade0de8f | 68 | } else { |
bikeNomad | 0:84aaade0de8f | 69 | song->print(pc); |
bikeNomad | 0:84aaade0de8f | 70 | } |
bikeNomad | 0:84aaade0de8f | 71 | } |
bikeNomad | 0:84aaade0de8f | 72 | } |
bikeNomad | 0:84aaade0de8f | 73 | |
bikeNomad | 0:84aaade0de8f | 74 | return songs.size(); |
bikeNomad | 0:84aaade0de8f | 75 | } |
bikeNomad | 0:84aaade0de8f | 76 | |
bikeNomad | 0:84aaade0de8f | 77 | bool Song::parseFilename(char const *_name) |
bikeNomad | 0:84aaade0de8f | 78 | { |
bikeNomad | 0:84aaade0de8f | 79 | if (strlen(_name) > MAX_BASENAME_LENGTH) |
bikeNomad | 0:84aaade0de8f | 80 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 81 | |
bikeNomad | 0:84aaade0de8f | 82 | strcpy(fullname, directoryName); |
bikeNomad | 0:84aaade0de8f | 83 | basename = fullname + BASS_DIRECTORY_LENGTH; |
bikeNomad | 0:84aaade0de8f | 84 | *basename++ = '/'; |
bikeNomad | 0:84aaade0de8f | 85 | strcpy(basename, _name); |
bikeNomad | 0:84aaade0de8f | 86 | |
bikeNomad | 0:84aaade0de8f | 87 | char *p; |
bikeNomad | 0:84aaade0de8f | 88 | long n = strtol(_name, &p, 10); |
bikeNomad | 0:84aaade0de8f | 89 | if (*p != '_' || n <= 0) |
bikeNomad | 0:84aaade0de8f | 90 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 91 | |
bikeNomad | 0:84aaade0de8f | 92 | sequenceNumber = (unsigned)(n - 1); |
bikeNomad | 0:84aaade0de8f | 93 | |
bikeNomad | 0:84aaade0de8f | 94 | p++; // skip underscore |
bikeNomad | 0:84aaade0de8f | 95 | n = strtol(p, &p, 10); |
bikeNomad | 0:84aaade0de8f | 96 | if (*p != '_' || n <= 0 || n > MAX_FISH) |
bikeNomad | 0:84aaade0de8f | 97 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 98 | |
bikeNomad | 0:84aaade0de8f | 99 | whichFish = (unsigned)(n - 1); |
bikeNomad | 0:84aaade0de8f | 100 | |
bikeNomad | 0:84aaade0de8f | 101 | p = strrchr(basename, '.'); |
bikeNomad | 0:84aaade0de8f | 102 | if (!p) |
bikeNomad | 0:84aaade0de8f | 103 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 104 | |
bikeNomad | 0:84aaade0de8f | 105 | extension = p+1; |
bikeNomad | 0:84aaade0de8f | 106 | |
bikeNomad | 0:84aaade0de8f | 107 | if (strcasecmp(extension, sampleExtension)) |
bikeNomad | 0:84aaade0de8f | 108 | goto on_error; |
bikeNomad | 0:84aaade0de8f | 109 | |
bikeNomad | 0:84aaade0de8f | 110 | return true; |
bikeNomad | 0:84aaade0de8f | 111 | |
bikeNomad | 0:84aaade0de8f | 112 | on_error: |
bikeNomad | 0:84aaade0de8f | 113 | whichFish = NO_FISH; |
bikeNomad | 0:84aaade0de8f | 114 | basename = 0; |
bikeNomad | 0:84aaade0de8f | 115 | return false; |
bikeNomad | 0:84aaade0de8f | 116 | } |
bikeNomad | 0:84aaade0de8f | 117 | |
bikeNomad | 0:84aaade0de8f | 118 | bool Song::readActions() |
bikeNomad | 0:84aaade0de8f | 119 | { |
bikeNomad | 0:84aaade0de8f | 120 | FILE *txtfile = fopen(getTextFileName(), "r"); |
bikeNomad | 0:84aaade0de8f | 121 | if (!txtfile) { |
bikeNomad | 0:84aaade0de8f | 122 | pc.printf("can't open %s\r\n", getTextFileName()); |
bikeNomad | 0:84aaade0de8f | 123 | return false; |
bikeNomad | 0:84aaade0de8f | 124 | } |
bikeNomad | 0:84aaade0de8f | 125 | bool retval = false; |
bikeNomad | 0:84aaade0de8f | 126 | |
bikeNomad | 0:84aaade0de8f | 127 | BillyBass *bass = BillyBass::bassNumber(whichFish); |
bikeNomad | 0:84aaade0de8f | 128 | if (!bass) { |
bikeNomad | 0:84aaade0de8f | 129 | pc.printf("No bass!\r\n"); |
bikeNomad | 0:84aaade0de8f | 130 | goto done; |
bikeNomad | 0:84aaade0de8f | 131 | } |
bikeNomad | 0:84aaade0de8f | 132 | |
bikeNomad | 0:84aaade0de8f | 133 | // read actions from file |
bikeNomad | 0:84aaade0de8f | 134 | unsigned line = 1; |
bikeNomad | 0:84aaade0de8f | 135 | char actionLine[ MAX_ACTION_LINE_LENGTH + 1 ]; |
bikeNomad | 0:84aaade0de8f | 136 | while (true) { |
bikeNomad | 0:84aaade0de8f | 137 | if (!fgets(actionLine, sizeof(actionLine), txtfile)) |
bikeNomad | 0:84aaade0de8f | 138 | break; |
bikeNomad | 0:84aaade0de8f | 139 | |
bikeNomad | 0:84aaade0de8f | 140 | // delete trailing whitespace |
bikeNomad | 0:84aaade0de8f | 141 | char *p = actionLine + strlen(actionLine) - 1; |
bikeNomad | 0:84aaade0de8f | 142 | while (isspace(*p)) *p-- = 0; |
bikeNomad | 0:84aaade0de8f | 143 | |
bikeNomad | 0:84aaade0de8f | 144 | float startTime = strtof(actionLine, &p); |
bikeNomad | 0:84aaade0de8f | 145 | if (p == actionLine) |
bikeNomad | 0:84aaade0de8f | 146 | goto done; |
bikeNomad | 0:84aaade0de8f | 147 | |
bikeNomad | 0:84aaade0de8f | 148 | char *q; |
bikeNomad | 0:84aaade0de8f | 149 | float endTime = strtof(p, &q); |
bikeNomad | 0:84aaade0de8f | 150 | if (q == p) |
bikeNomad | 0:84aaade0de8f | 151 | goto done; |
bikeNomad | 0:84aaade0de8f | 152 | |
bikeNomad | 0:84aaade0de8f | 153 | while (isspace(*q)) q++; |
bikeNomad | 0:84aaade0de8f | 154 | |
bikeNomad | 0:84aaade0de8f | 155 | char const *outName; |
bikeNomad | 0:84aaade0de8f | 156 | DigitalOut *out = bass->outputNamed(q, &outName); |
bikeNomad | 0:84aaade0de8f | 157 | if (!out) { |
bikeNomad | 0:84aaade0de8f | 158 | pc.printf("%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q); |
bikeNomad | 0:84aaade0de8f | 159 | goto done; |
bikeNomad | 0:84aaade0de8f | 160 | } |
bikeNomad | 0:84aaade0de8f | 161 | pc.printf("%d add %f %f %s\r\n", line, startTime, endTime, outName); |
bikeNomad | 0:84aaade0de8f | 162 | |
bikeNomad | 0:84aaade0de8f | 163 | actions.push_back(Action(startTime, true, out, outName)); |
bikeNomad | 0:84aaade0de8f | 164 | actions.push_back(Action(endTime, false, out, outName)); |
bikeNomad | 0:84aaade0de8f | 165 | |
bikeNomad | 0:84aaade0de8f | 166 | line++; |
bikeNomad | 0:84aaade0de8f | 167 | } |
bikeNomad | 0:84aaade0de8f | 168 | |
bikeNomad | 0:84aaade0de8f | 169 | std::sort(actions.begin(), actions.end()); // sort actions by time |
bikeNomad | 0:84aaade0de8f | 170 | retval = true; |
bikeNomad | 0:84aaade0de8f | 171 | |
bikeNomad | 0:84aaade0de8f | 172 | done: |
bikeNomad | 0:84aaade0de8f | 173 | if (!retval) { |
bikeNomad | 0:84aaade0de8f | 174 | pc.printf("Error reading action from \"%s\"\r\n", actionLine); |
bikeNomad | 0:84aaade0de8f | 175 | } |
bikeNomad | 0:84aaade0de8f | 176 | fclose(txtfile); |
bikeNomad | 0:84aaade0de8f | 177 | return retval; |
bikeNomad | 0:84aaade0de8f | 178 | } |