From d3046d174245920c01f2e19fa43f2cccdba9540b Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Fri, 30 Jul 2010 17:45:36 +0200 Subject: Feature: Custom station sorting Sort stations by name and/or isquickmix. --- src/main.c | 3 ++- src/settings.c | 18 ++++++++++++++- src/settings.h | 15 ++++++++++-- src/ui.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/ui.h | 4 ++-- src/ui_act.c | 8 ++++--- 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/src/main.c b/src/main.c index 86bdaf1..e0c344b 100644 --- a/src/main.c +++ b/src/main.c @@ -175,7 +175,8 @@ int main (int argc, char **argv) { } /* no autostart? ask the user */ if (curStation == NULL) { - curStation = BarUiSelectStation (&ph, "Select station: ", stdin); + curStation = BarUiSelectStation (&ph, "Select station: ", + settings.sortOrder, stdin); } if (curStation != NULL) { BarUiPrintStation (curStation); diff --git a/src/settings.c b/src/settings.c index 1dee0ea..8aa764c 100644 --- a/src/settings.c +++ b/src/settings.c @@ -87,7 +87,6 @@ void BarSettingsDestroy (BarSettings_t *settings) { void BarSettingsRead (BarSettings_t *settings) { /* FIXME: what is the max length of a path? */ char configfile[1024], key[256], val[256]; - size_t i; FILE *configfd; /* _must_ have same order as in BarKeyShortcutId_t */ const char defaultKeys[] = {'?', '+', '-', 'a', 'c', 'd', 'e', 'g', @@ -113,6 +112,7 @@ void BarSettingsRead (BarSettings_t *settings) { #endif #endif settings->history = 5; + settings->sortOrder = BAR_SORT_NAME_AZ; memcpy (settings->keys, defaultKeys, sizeof (defaultKeys)); BarGetXdgConfigDir (PACKAGE "/config", configfile, sizeof (configfile)); @@ -138,6 +138,7 @@ void BarSettingsRead (BarSettings_t *settings) { } else if (strcmp ("password", key) == 0) { settings->password = strdup (val); } else if (memcmp ("act_", key, 4) == 0) { + size_t i; /* keyboard shortcuts */ for (i = 0; i < BAR_KS_COUNT; i++) { if (strcmp (shortcutFileKeys[i], key) == 0) { @@ -159,6 +160,21 @@ void BarSettingsRead (BarSettings_t *settings) { settings->eventCmd = strdup (val); } else if (strcmp ("history", key) == 0) { settings->history = atoi (val); + } else if (strcmp ("sort", key) == 0) { + size_t i; + char *mapping[] = {"name_az", + "name_za", + "quickmix_01_name_az", + "quickmix_01_name_za", + "quickmix_10_name_az", + "quickmix_10_name_za", + }; + for (i = 0; i < BAR_SORT_COUNT; i++) { + if (strcmp (mapping[i], val) == 0) { + settings->sortOrder = i; + break; + } + } } } diff --git a/src/settings.h b/src/settings.h index 42443d7..2505321 100644 --- a/src/settings.h +++ b/src/settings.h @@ -64,16 +64,27 @@ typedef enum { BAR_KS_COUNT = 22, } BarKeyShortcutId_t; +typedef enum { + BAR_SORT_NAME_AZ = 0, + BAR_SORT_NAME_ZA = 1, + BAR_SORT_QUICKMIX_01_NAME_AZ = 2, + BAR_SORT_QUICKMIX_01_NAME_ZA = 3, + BAR_SORT_QUICKMIX_10_NAME_AZ = 4, + BAR_SORT_QUICKMIX_10_NAME_ZA = 5, + BAR_SORT_COUNT = 6, +} BarStationSorting_t; + typedef struct { + unsigned int history; + BarStationSorting_t sortOrder; + PianoAudioFormat_t audioFormat; char *username; char *password; char *controlProxy; /* non-american listeners need this */ char *proxy; char keys[BAR_KS_COUNT]; - PianoAudioFormat_t audioFormat; char *autostartStation; char *eventCmd; - unsigned int history; } BarSettings_t; typedef void (*BarKeyShortcutFunc_t) (BAR_KS_ARGS); diff --git a/src/ui.c b/src/ui.c index 1295a33..0254089 100644 --- a/src/ui.c +++ b/src/ui.c @@ -33,6 +33,7 @@ THE SOFTWARE. #include #include #include +#include /* waitpid () */ #include @@ -41,6 +42,8 @@ THE SOFTWARE. #include "ui.h" #include "ui_readline.h" +typedef int (*BarSortFunc_t) (const void *, const void *); + /* output message and flush stdout * @param message */ @@ -169,26 +172,78 @@ int BarUiPianoCall (PianoHandle_t *ph, PianoRequestType_t type, return 1; } -/* compare stations by name (ignore case) - * @param station a - * @param station b - * @return -1, 0, 1 +/* Station sorting functions */ + +static inline int BarStationQuickmix01Cmp (const void *a, const void *b) { + const PianoStation_t *stationA = *((PianoStation_t **) a), + *stationB = *((PianoStation_t **) b); + return stationA->isQuickMix - stationB->isQuickMix; +} + +/* sort by station name from a to z, case insensitive */ -static int BarStationCmp (const void *a, const void *b) { +static inline int BarStationNameAZCmp (const void *a, const void *b) { const PianoStation_t *stationA = *((PianoStation_t **) a), *stationB = *((PianoStation_t **) b); return strcasecmp (stationA->name, stationB->name); } +/* sort by station name from z to a, case insensitive + */ +static int BarStationNameZACmp (const void *a, const void *b) { + return BarStationNameAZCmp (b, a); +} + +/* helper for quickmix/name sorting + */ +static inline int BarStationQuickmixNameCmp (const void *a, const void *b, + const void *c, const void *d) { + int qmc = BarStationQuickmix01Cmp (a, b); + return qmc == 0 ? BarStationNameAZCmp (c, d) : qmc; +} + +/* sort by quickmix (no to yes) and name (a to z) + */ +static int BarStationCmpQuickmix01NameAZ (const void *a, const void *b) { + return BarStationQuickmixNameCmp (a, b, a, b); +} + +/* sort by quickmix (no to yes) and name (z to a) + */ +static int BarStationCmpQuickmix01NameZA (const void *a, const void *b) { + return BarStationQuickmixNameCmp (a, b, b, a); +} + +/* sort by quickmix (yes to no) and name (a to z) + */ +static int BarStationCmpQuickmix10NameAZ (const void *a, const void *b) { + return BarStationQuickmixNameCmp (b, a, a, b); +} + +/* sort by quickmix (yes to no) and name (z to a) + */ +static int BarStationCmpQuickmix10NameZA (const void *a, const void *b) { + return BarStationQuickmixNameCmp (b, a, b, a); +} + /* sort linked list (station) * @param stations * @return NULL-terminated array with sorted stations */ PianoStation_t **BarSortedStations (PianoStation_t *unsortedStations, - size_t *retStationCount) { + size_t *retStationCount, BarStationSorting_t order) { + static const BarSortFunc_t orderMapping[] = {BarStationNameAZCmp, + BarStationNameZACmp, + BarStationCmpQuickmix01NameAZ, + BarStationCmpQuickmix01NameZA, + BarStationCmpQuickmix10NameAZ, + BarStationCmpQuickmix10NameZA, + }; PianoStation_t **stationArray = NULL, *currStation = NULL; size_t stationCount = 0, i; + assert (order < sizeof (orderMapping)/sizeof(*orderMapping)); + /* get size */ currStation = unsortedStations; while (currStation != NULL) { @@ -206,7 +261,7 @@ PianoStation_t **BarSortedStations (PianoStation_t *unsortedStations, ++i; } - qsort (stationArray, stationCount, sizeof (*stationArray), BarStationCmp); + qsort (stationArray, stationCount, sizeof (*stationArray), orderMapping[order]); *retStationCount = stationCount; return stationArray; @@ -217,13 +272,13 @@ PianoStation_t **BarSortedStations (PianoStation_t *unsortedStations, * @return pointer to selected station or NULL */ PianoStation_t *BarUiSelectStation (PianoHandle_t *ph, const char *prompt, - FILE *curFd) { + 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); + 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, diff --git a/src/ui.h b/src/ui.h index 0a23881..eed0b07 100644 --- a/src/ui.h +++ b/src/ui.h @@ -35,8 +35,8 @@ typedef enum {MSG_NONE, MSG_INFO, MSG_PLAYING, MSG_TIME, MSG_ERR, void BarUiMsg (uiMsg_t type, const char *format, ...); PianoReturn_t BarUiPrintPianoStatus (PianoReturn_t ret); -PianoStation_t *BarUiSelectStation (PianoHandle_t *ph, const char *prompt, - FILE *curFd); +PianoStation_t *BarUiSelectStation (PianoHandle_t *, const char *, + BarStationSorting_t, FILE *); PianoSong_t *BarUiSelectSong (PianoSong_t *startSong, FILE *curFd); PianoArtist_t *BarUiSelectArtist (PianoArtist_t *startArtist, FILE *curFd); char *BarUiSelectMusicId (PianoHandle_t *ph, WaitressHandle_t *, FILE *curFd, char *); diff --git a/src/ui_act.c b/src/ui_act.c index ba7dd1c..7328e40 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -327,7 +327,8 @@ void BarUiActMoveSong (BAR_KS_ARGS) { RETURN_IF_NO_SONG; - reqData.to = BarUiSelectStation (ph, "Move song to station: ", curFd); + reqData.to = BarUiSelectStation (ph, "Move song to station: ", + settings->sortOrder, curFd); if (reqData.to != NULL) { /* find original station (just is case we're playing a quickmix * station) */ @@ -392,7 +393,7 @@ void BarUiActRenameStation (BAR_KS_ARGS) { */ void BarUiActSelectStation (BAR_KS_ARGS) { PianoStation_t *newStation = BarUiSelectStation (ph, "Select station: ", - curFd); + settings->sortOrder, curFd); if (newStation != NULL) { *curStation = newStation; BarUiPrintStation ((*curStation)); @@ -450,7 +451,8 @@ void BarUiActSelectQuickMix (BAR_KS_ARGS) { if ((*curStation)->isQuickMix) { PianoStation_t *selStation; while ((selStation = BarUiSelectStation (ph, - "Toggle quickmix for station: ", curFd)) != NULL) { + "Toggle quickmix for station: ", settings->sortOrder, + curFd)) != NULL) { selStation->useQuickMix = !selStation->useQuickMix; } BarUiMsg (MSG_INFO, "Setting quickmix stations... "); -- cgit v1.2.3