bool Playlist::playAdjacent(int8_t bump, bool chainingPlaylists) { if( ! isFirst) { int8_t next = playIndex + bump; setPlayIndex(next); if(chainingPlaylists && playIndex != next) { // we've wrapped // advance playlists until find another list with chirps or we're back where we started for(int i = 0; i < N_PLAYLISTS; i++) { Playlist *p = Playlists::useAdjacentPlaylist(bump, false); // false to not store if(p->nChirps) { Playlists::useAdjacentPlaylist(0); // use this one & store it this time p->setPlayIndex(bump > 0 ? 0 : -1); // -1 forces wrap to nChirps - 1 return p->play(); } } } } return play(); }
bool doCommand(char *command) { // new commands always turn off immediate autoplay immediateAutoplayStop(); int length = strlen(command); if(length == 0) { return true; } char commandChar = toupper(command[0]); char *parameters = &command[1]; bool noParameters = length == 1; char firstParameterChar = noParameters ? '\0' : toupper(*parameters); Serial.println(command); Playlist *playlist = Playlists::currentPlaylist(); switch(commandChar) { case '+': // see also default at end of switch for making chirps without preceding with + if( ! noParameters) { return makeNewChirp(parameters); } break; case ']': case ')': if(noParameters) { Serial.println(F("next")); playlist->playAdjacent(1, commandChar == ')'); // ] wraps, ) chains } break; case '[': case '(': if(noParameters) { Serial.println(F("back")); playlist->playAdjacent(-1, commandChar == '('); // [ wraps, ( chains } break; case ',': if(noParameters) { Serial.println(F("step")); playlist->playSequenced(); } break; case '@': // select playlist by index number.. if(noParameters) { playlist->setPlayIndex(0); // ..or reset play index to 0 in current playlist } else { playlist = Playlists::usePlaylist(number(parameters, playlist->playlistIndex)); } break; case '}': case '{': if(noParameters) { playlist = Playlists::useAdjacentPlaylist(commandChar == '}' ? 1 : -1); } break; case '!': // play current or supplied code if(noParameters) { playlist->play(); } else if(isAChirpCode(parameters)) { playlist->playChirpCode(parameters); } else { playlist->playIndexed(number(parameters, playlist->playIndex)); } break; case '?': if(noParameters) { Serial.println(F("lookup")); return ! playerLink.fetchChirpContent(playlist); } break; case '~': // clearing Serial.println(F("clear")); if(noParameters) { playlist->clear(CLEAR_LIST); } else if(firstParameterChar == '#') { playlist->clear(CLEAR_SCRIPT_URL); } else if(strcmp(parameters, "!") == 0) { Playlists::clearAll(); } else { playlist->clear(number(parameters)); } break; case '.': // autoplay order & chirping interval if( ! noParameters && strchr("FBRS", firstParameterChar)) { playlist->setPlayOrder(firstParameterChar); parameters++; if(*parameters == '\0') { return true; } } playlist->setInterval(number(parameters, DEFAULT_INTERVAL)); break; case ':': // sound if( ! noParameters && strchr("PNM", firstParameterChar)) { if(firstParameterChar == 'M') { muted = ! muted; Serial.print(F("muting ")); Serial.println(muted ? F("on") : F("off")); } else { playlist->setPortamento(firstParameterChar == 'P'); } parameters++; if(*parameters == '\0') { return true; } } playlist->setVolume(number(parameters, DEFAULT_VOLUME)); // noParam form will set volume to default break; case '*': // autoplay if(noParameters) { Serial.println(F("autoplay now")); immediateAutoplayStart(); return false; // don't show prompt } else { doAutoplaySettingsCommand(playlist, parameters); } break; case '|': Serial.println(F("limit")); playlist->setAutoplayChirpLimit(number(parameters, PLAYLIST_CAPACITY)); break; case '^': // times Serial.println(F("time")); if(noParameters) { return ! playerLink.fetchTimeNow(); } else if(firstParameterChar == '-') { adjustTimeSeconds(-number(¶meters[1])); } else if(firstParameterChar == '+') { adjustTimeSeconds(number(¶meters[1])); } if(stringToSeconds(parameters)) { setTimeUTC(parameters); } break; case '#': // scripts if(noParameters) { if( ! playlist->requestUpdate()) { Serial.println(F("no script")); } } else { if(length == 2) { if(firstParameterChar == '?') { // #? to print current playlist in script format playlist->printAsScript(); } else { playlist->setUpdateFlags(number(parameters)); } } else { playlist->setScriptAddress(parameters); } } break; case '/': // run named script, or update all playlists with scripts Serial.println(F("run")); if(noParameters) { Playlists::updateAll(false); // false => not conditional on playlist flags } else { return ! playerLink.fetchScript(-1, parameters); // -1 signals is general script, not one for a particular playlist } break; case '=': // invoke trigger from the command line Trigger::trigger(parameters); break; case '-': inactivityTrigger.setWaitSeconds(number(parameters)); break; case '%': // comment line; ignore break; default: if(isAChirpCode(command)) { playlist->add(command); } else { Serial.println(F("uh?")); } break; } return true; }