summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <PromyLOPh@lavabit.com>2010-07-30 17:45:36 +0200
committerLars-Dominik Braun <PromyLOPh@lavabit.com>2010-07-30 17:45:36 +0200
commitd3046d174245920c01f2e19fa43f2cccdba9540b (patch)
treed2893ab841490e9e88f21ec6653e227a7b80c395
parentdf4022ccda870f2a1b0e4e254f4a298da48fc4f9 (diff)
downloadpianobar-d3046d174245920c01f2e19fa43f2cccdba9540b.tar.gz
pianobar-d3046d174245920c01f2e19fa43f2cccdba9540b.tar.bz2
pianobar-d3046d174245920c01f2e19fa43f2cccdba9540b.zip
Feature: Custom station sorting
Sort stations by name and/or isquickmix.
-rw-r--r--src/main.c3
-rw-r--r--src/settings.c18
-rw-r--r--src/settings.h15
-rw-r--r--src/ui.c73
-rw-r--r--src/ui.h4
-rw-r--r--src/ui_act.c8
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 <string.h>
#include <errno.h>
#include <strings.h>
+#include <assert.h>
/* waitpid () */
#include <sys/types.h>
@@ -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... ");