From 5488adb613ca623a8ef4cb37b6a802effaaf50ec Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Fri, 25 Mar 2011 16:24:29 +0100 Subject: Filter-/searchable song list --- src/ui.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++----------- src/ui.h | 2 +- src/ui_act.c | 2 +- 3 files changed, 73 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ui.c b/src/ui.c index cd0b7d2..dee6b2c 100644 --- a/src/ui.c +++ b/src/ui.c @@ -34,6 +34,7 @@ THE SOFTWARE. #include #include #include +#include /* tolower() */ /* waitpid () */ #include @@ -337,6 +338,21 @@ PianoStation_t *BarUiSelectStation (PianoHandle_t *ph, const char *prompt, return retStation; } +/* is string a number? + */ +static bool isnumeric (const char *s) { + if (*s == '\0') { + return false; + } + while (*s != '\0') { + if (!isdigit ((unsigned char) *s)) { + return false; + } + ++s; + } + return true; +} + /* let user pick one song * @param pianobar settings * @param song list @@ -346,20 +362,27 @@ PianoStation_t *BarUiSelectStation (PianoHandle_t *ph, const char *prompt, PianoSong_t *BarUiSelectSong (const BarSettings_t *settings, PianoSong_t *startSong, BarReadlineFds_t *input) { PianoSong_t *tmpSong = NULL; - int i = 0; + char buf[100]; - i = BarUiListSongs (settings, startSong); + memset (buf, 0, sizeof (buf)); - BarUiMsg (MSG_QUESTION, "Select song: "); - if (BarReadlineInt (&i, input) == 0) { - return NULL; - } + do { + BarUiListSongs (settings, startSong, buf); - tmpSong = startSong; - while (tmpSong != NULL && i > 0) { - tmpSong = tmpSong->next; - i--; - } + BarUiMsg (MSG_QUESTION, "Select song: "); + if (BarReadlineStr (buf, sizeof (buf), input, BAR_RL_DEFAULT) == 0) { + return NULL; + } + + if (isnumeric (buf)) { + unsigned long i = strtoul (buf, NULL, 0); + tmpSong = startSong; + while (tmpSong != NULL && i > 0) { + tmpSong = tmpSong->next; + i--; + } + } + } while (tmpSong == NULL); return tmpSong; } @@ -566,20 +589,52 @@ inline void BarUiPrintSong (const BarSettings_t *settings, station != NULL ? station->name : ""); } +/* find needle in haystack, ignoring case, and return first position + */ +const char *strcasestr (const char *haystack, const char *needle) { + const char *needlePos = needle; + + assert (haystack != NULL); + assert (needle != NULL); + + if (*needle == '\0') { + return haystack; + } + + while (*haystack != '\0') { + if (tolower ((unsigned char) *haystack) == tolower ((unsigned char) *needlePos)) { + ++needlePos; + } else { + needlePos = needle; + } + ++haystack; + if (*needlePos == '\0') { + return haystack - strlen (needle); + } + } + + return NULL; +} + /* Print list of songs * @param pianobar settings * @param linked list of songs + * @param artist/song filter string * @return # of songs */ size_t BarUiListSongs (const BarSettings_t *settings, - const PianoSong_t *song) { + const PianoSong_t *song, const char *filter) { size_t i = 0; while (song != NULL) { - BarUiMsg (MSG_LIST, "%2lu) %s - %s %s%s\n", i, song->artist, - song->title, - (song->rating == PIANO_RATE_LOVE) ? settings->loveIcon : "", - (song->rating == PIANO_RATE_BAN) ? settings->banIcon : ""); + if (filter == NULL || + (filter != NULL && (strcasestr (song->artist, filter) != NULL || + strcasestr (song->title, filter) != NULL))) { + BarUiMsg (MSG_LIST, "%2lu) %s - %s %s%s\n", i, song->artist, + song->title, + (song->rating == PIANO_RATE_LOVE) ? settings->loveIcon : "", + (song->rating == PIANO_RATE_BAN) ? settings->banIcon : ""); + } song = song->next; i++; } diff --git a/src/ui.h b/src/ui.h index adc7565..4489c71 100644 --- a/src/ui.h +++ b/src/ui.h @@ -47,7 +47,7 @@ void BarStationFromGenre (BarApp_t *); void BarUiPrintStation (PianoStation_t *); void BarUiPrintSong (const BarSettings_t *, const PianoSong_t *, const PianoStation_t *); -size_t BarUiListSongs (const BarSettings_t *, const PianoSong_t *); +size_t BarUiListSongs (const BarSettings_t *, const PianoSong_t *, const char *); void BarUiStartEventCmd (const BarSettings_t *, const char *, const PianoStation_t *, const PianoSong_t *, const struct audioPlayer *, PianoStation_t *, PianoReturn_t, WaitressReturn_t); diff --git a/src/ui_act.c b/src/ui_act.c index f646cdd..67fc0ca 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -413,7 +413,7 @@ BarUiActCallback(BarUiActPrintUpcoming) { PianoSong_t *nextSong = selSong->next; if (nextSong != NULL) { - BarUiListSongs (&app->settings, nextSong); + BarUiListSongs (&app->settings, nextSong, NULL); } else { BarUiMsg (MSG_INFO, "No songs in queue.\n"); } -- cgit v1.2.3