/* let user pick one station * @param piano handle * @return pointer to selected station or NULL */ PianoStation_t *BarUiSelectStation (PianoHandle_t *ph, const char *prompt, BarStationSorting_t order, FILE *curFd) { PianoStation_t **sortedStations = NULL, *retStation = NULL; size_t stationCount, i; int input; /* sort and print stations */ sortedStations = BarSortedStations (ph->stations, &stationCount, order); for (i = 0; i < stationCount; i++) { const PianoStation_t *currStation = sortedStations[i]; BarUiMsg (MSG_LIST, "%2i) %c%c%c %s\n", i, currStation->useQuickMix ? 'q' : ' ', currStation->isQuickMix ? 'Q' : ' ', !currStation->isCreator ? 'S' : ' ', currStation->name); } BarUiMsg (MSG_QUESTION, prompt); /* FIXME: using a _signed_ int is ugly */ if (BarReadlineInt (&input, curFd) == 0) { free (sortedStations); return NULL; } if (input < stationCount) { retStation = sortedStations[input]; } free (sortedStations); return retStation; }
/* let user pick one station * @param app handle * @param prompt string * @param called if input was not a number * @return pointer to selected station or NULL */ PianoStation_t *BarUiSelectStation (BarApp_t *app, PianoStation_t *stations, const char *prompt, BarUiSelectStationCallback_t callback) { PianoStation_t **sortedStations = NULL, *retStation = NULL; size_t stationCount, i; char buf[100]; if (stations == NULL) { BarUiMsg (&app->settings, MSG_ERR, "No station available.\n"); return NULL; } memset (buf, 0, sizeof (buf)); /* sort and print stations */ sortedStations = BarSortedStations (stations, &stationCount, app->settings.sortOrder); do { for (i = 0; i < stationCount; i++) { const PianoStation_t *currStation = sortedStations[i]; /* filter stations */ if (BarStrCaseStr (currStation->name, buf) != NULL) { BarUiMsg (&app->settings, MSG_LIST, "%2i) %c%c%c %s\n", i, currStation->useQuickMix ? 'q' : ' ', currStation->isQuickMix ? 'Q' : ' ', !currStation->isCreator ? 'S' : ' ', currStation->name); } } BarUiMsg (&app->settings, MSG_QUESTION, prompt); if (BarReadlineStr (buf, sizeof (buf), &app->input, BAR_RL_DEFAULT) == 0) { free (sortedStations); return NULL; } if (isnumeric (buf)) { unsigned long selected = strtoul (buf, NULL, 0); if (selected < stationCount) { retStation = sortedStations[selected]; } } /* hand over buffer to external function if it was not a station number */ if (retStation == NULL && callback != NULL) { callback (app, buf); } } while (retStation == NULL); free (sortedStations); return retStation; }
/* Excute external event handler * @param settings containing the cmdline * @param event type * @param current station * @param current song * @param piano error-code (PIANO_RET_OK if not applicable) * @param waitress error-code (WAITRESS_RET_OK if not applicable) */ void BarUiStartEventCmd (const BarSettings_t *settings, const char *type, const PianoStation_t *curStation, const PianoSong_t *curSong, const struct audioPlayer *player, PianoStation_t *stations, PianoReturn_t pRet, WaitressReturn_t wRet) { pid_t chld; int pipeFd[2]; if (settings->eventCmd == NULL) { /* nothing to do... */ return; } if (pipe (pipeFd) == -1) { BarUiMsg (settings, MSG_ERR, "Cannot create eventcmd pipe. (%s)\n", strerror (errno)); return; } chld = fork (); if (chld == 0) { /* child */ close (pipeFd[1]); dup2 (pipeFd[0], fileno (stdin)); execl (settings->eventCmd, settings->eventCmd, type, (char *) NULL); BarUiMsg (settings, MSG_ERR, "Cannot start eventcmd. (%s)\n", strerror (errno)); close (pipeFd[0]); exit (1); } else if (chld == -1) { BarUiMsg (settings, MSG_ERR, "Cannot fork eventcmd. (%s)\n", strerror (errno)); } else { /* parent */ int status; PianoStation_t *songStation = NULL; FILE *pipeWriteFd; close (pipeFd[0]); pipeWriteFd = fdopen (pipeFd[1], "w"); if (curSong != NULL && stations != NULL && curStation->isQuickMix) { songStation = PianoFindStationById (stations, curSong->stationId); } fprintf (pipeWriteFd, "artist=%s\n" "title=%s\n" "album=%s\n" "coverArt=%s\n" "stationName=%s\n" "songStationName=%s\n" "pRet=%i\n" "pRetStr=%s\n" "wRet=%i\n" "wRetStr=%s\n" "songDuration=%lu\n" "songPlayed=%lu\n" "rating=%i\n" "detailUrl=%s\n", curSong == NULL ? "" : curSong->artist, curSong == NULL ? "" : curSong->title, curSong == NULL ? "" : curSong->album, curSong == NULL ? "" : curSong->coverArt, curStation == NULL ? "" : curStation->name, songStation == NULL ? "" : songStation->name, pRet, PianoErrorToStr (pRet), wRet, WaitressErrorToStr (wRet), player->songDuration, player->songPlayed, curSong == NULL ? PIANO_RATE_NONE : curSong->rating, curSong == NULL ? "" : curSong->detailUrl ); if (stations != NULL) { /* send station list */ PianoStation_t **sortedStations = NULL; size_t stationCount; sortedStations = BarSortedStations (stations, &stationCount, settings->sortOrder); assert (sortedStations != NULL); fprintf (pipeWriteFd, "stationCount=%zd\n", stationCount); for (size_t i = 0; i < stationCount; i++) { const PianoStation_t *currStation = sortedStations[i]; fprintf (pipeWriteFd, "station%zd=%s\n", i, currStation->name); } free (sortedStations); } else { const char * const msg = "stationCount=0\n"; fwrite (msg, sizeof (*msg), strlen (msg), pipeWriteFd); } /* closes pipeFd[1] as well */ fclose (pipeWriteFd); /* wait to get rid of the zombie */ waitpid (chld, &status, 0); } }
/* Excute external event handler * @param settings containing the cmdline * @param event type * @param current station * @param current song * @param piano error-code (PIANO_RET_OK if not applicable) * @param waitress error-code (WAITRESS_RET_OK if not applicable) */ void BarUiStartEventCmd (const BarSettings_t *settings, const char *type, const PianoStation_t *curStation, const PianoSong_t *curSong, const struct audioPlayer *player, PianoStation_t *stations, PianoReturn_t pRet, WaitressReturn_t wRet) { int status; PianoStation_t *songStation = NULL; if (curSong != NULL && stations != NULL && curStation->isQuickMix) { songStation = PianoFindStationById (stations, curSong->stationId); } printf ("current\tartist=%s\n" "current\ttitle=%s\n" "current\talbum=%s\n" "current\tcoverArt=%s\n" "current\tstationName=%s\n" "songStationName=%s\n" "pRet=%i\n" "pRetStr=%s\n" "wRet=%i\n" "wRetStr=%s\n" "songDuration=%lu\n" "songPlayed=%lu\n" "rating=%i\n" "detailUrl=%s\n", curSong == NULL ? "" : curSong->artist, curSong == NULL ? "" : curSong->title, curSong == NULL ? "" : curSong->album, curSong == NULL ? "" : curSong->coverArt, curStation == NULL ? "" : curStation->name, songStation == NULL ? "" : songStation->name, pRet, PianoErrorToStr (pRet), wRet, WaitressErrorToStr (wRet), player->songDuration, player->songPlayed, curSong == NULL ? PIANO_RATE_NONE : curSong->rating, curSong == NULL ? "" : curSong->detailUrl ); if (stations != NULL) { /* send station list */ PianoStation_t **sortedStations = NULL; size_t stationCount; sortedStations = BarSortedStations (stations, &stationCount, settings->sortOrder); assert (sortedStations != NULL); printf ("station\tstationCount=%zd\n", stationCount); for (size_t i = 0; i < stationCount; i++) { const PianoStation_t *currStation = sortedStations[i]; printf ("station\tstation%zd=%s\n", i, currStation->name); } free (sortedStations); } }
/* let user pick one station * @param app handle * @param stations that should be listed * @param prompt string * @param called if input was not a number * @param auto-select if only one station remains after filtering * @return pointer to selected station or NULL */ PianoStation_t *BarUiSelectStation (BarApp_t *app, PianoStation_t *stations, const char *prompt, BarUiSelectStationCallback_t callback, bool autoselect) { PianoStation_t **sortedStations = NULL, *retStation = NULL; size_t stationCount, i, lastDisplayed, displayCount; char buf[100]; if (stations == NULL) { BarUiMsg (&app->settings, MSG_ERR, "No station available.\n"); return NULL; } memset (buf, 0, sizeof (buf)); /* sort and print stations */ sortedStations = BarSortedStations (stations, &stationCount, app->settings.sortOrder); do { displayCount = 0; for (i = 0; i < stationCount; i++) { const PianoStation_t *currStation = sortedStations[i]; /* filter stations */ if (BarStrCaseStr (currStation->name, buf) != NULL) { BarUiMsg (&app->settings, MSG_LIST, "%2zi) %c%c%c %s\n", i, currStation->useQuickMix ? 'q' : ' ', currStation->isQuickMix ? 'Q' : ' ', !currStation->isCreator ? 'S' : ' ', currStation->name); ++displayCount; lastDisplayed = i; } } BarUiMsg (&app->settings, MSG_QUESTION, "%s", prompt); if (autoselect && displayCount == 1 && stationCount != 1) { /* auto-select last remaining station */ BarUiMsg (&app->settings, MSG_NONE, "%zi\n", lastDisplayed); retStation = sortedStations[lastDisplayed]; } else { if (BarReadlineStr (buf, sizeof (buf), app->rl, BAR_RL_DEFAULT) == 0) { break; } if (isnumeric (buf)) { unsigned long selected = strtoul (buf, NULL, 0); if (selected < stationCount) { retStation = sortedStations[selected]; } } /* hand over buffer to external function if it was not a station number */ if (retStation == NULL && callback != NULL) { callback (app, buf); } } } while (retStation == NULL); free (sortedStations); return retStation; }