Example #1
0
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(&parameters[1]));
			}
			else if(firstParameterChar == '+') {
				adjustTimeSeconds(number(&parameters[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;
}
Example #2
0
void autoplayLoop() {
    static int32_t then; // now field from last time in loop

    int32_t now = timeNowSecondsSinceMidnight();
    int16_t nowMinute = now / 60;

    // start any new autoplays
    if(nowMinute > then / 60 || autoplayNow) {
        // its a new minute; check the playlists to see if any due to start autoplaying this minute
        autoplayNow = false;

        for(int ix = 0; ix < N_PLAYLISTS; ix++) {
            Playlist *p = Playlists::playlist(ix);

            if(p->nChirps > 0 && p->autoplayCount == 0) { // only check if playlist has chirps and isn't already playing
                AutoplayStructure settings;
                p->getAutoplaySettings(&settings);

                int16_t startMinute = settings.startMinute;

                // run through all start times for playlist
                // doesn't play before initial start time and doesn't continue repeating past midnight
                for(uint8_t n = 0; n < settings.count && nowMinute >= startMinute && startMinute < minutesInOneDay; n++) {
                    if(startMinute == nowMinute) {
                        if(p->getUpdateFlags() & UPDATE_WHEN_AUTOPLAY) {
                            p->requestUpdate();
                        }

                        // setting non-zero count makes autoplay active
                        p->autoplayCount = min(settings.maxChirps, p->nChirps); 
                        p->autoplayTimeSeconds = 0; // play as soon as possible
                        break;
                    }
                    startMinute += settings.repeatMinutes;
                }
            }
        }
    }

    // autoplay up to one chirp per new second

    if(now > then) {
        // it's a new second

        // first check to see if current playlist is being autoplayed from the command line
        if(immediateAutoplayCount > 0 && now >= immediateAutoplayTimeSeconds) {
            Playlist *p = Playlists::currentPlaylist();

            if(p->playSequenced()) {
                immediateAutoplayCount--;
                immediateAutoplayTimeSeconds = now + p->getInterval();
            }
            else {
                // empty playlist: turn off
                immediateAutoplayCount = 0;
            }
            if(immediateAutoplayCount == 0) {
                showPrompt();
            }
        }
        else {
            // check any timed autoplaying playlists for any due to play now
            for(int ix = 0; ix < N_PLAYLISTS; ix++) {
                Playlist *p = Playlists::playlist(ix);

                if(p->autoplayCount > 0 && now >= p->autoplayTimeSeconds && p->awaitingUpdate == NOT_AWAITING_UPDATE) {
                    if(p->playSequenced()) {
                        p->autoplayCount--;
                        p->autoplayTimeSeconds = now + p->getInterval();
                        break; // only one play per vsit to this function
                    }
                    else {
                        p->autoplayCount = 0; // empty playlist (shouldn't happen here)
                    }
                }
            }
        }
    }

    then = now;
}