From 7a02354513acad9e315b4f4f736b77a08de363a6 Mon Sep 17 00:00:00 2001
From: Lars-Dominik Braun <lars@6xq.net>
Date: Sat, 17 Mar 2012 19:27:27 +0100
Subject: Auto-select last remaining item of filtered list

See #231.
---
 contrib/pianobar.1 |  5 +++++
 src/main.c         |  3 ++-
 src/settings.c     |  3 +++
 src/settings.h     |  3 +++
 src/ui.c           | 41 ++++++++++++++++++++++++++---------------
 src/ui.h           |  4 +++-
 src/ui_act.c       |  9 +++++----
 7 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/contrib/pianobar.1 b/contrib/pianobar.1
index 7a44426..da87270 100644
--- a/contrib/pianobar.1
+++ b/contrib/pianobar.1
@@ -160,6 +160,11 @@ Replacement for %@ in station format string. It's " @ " by default.
 Select audio format. aacplus is default if both libraries (faad, mad) are
 available. mp3-hifi is available for Pandora One customers only.
 
+.TP
+.B autoselect = {1,0}
+Auto-select last remaining item of filtered list. Currently enabled for station
+selection only.
+
 .TP
 .B autostart_station = stationid
 Play this station when starting up. You can get the
diff --git a/src/main.c b/src/main.c
index 2f05d7c..f431331 100644
--- a/src/main.c
+++ b/src/main.c
@@ -137,7 +137,8 @@ static void BarMainGetInitialStation (BarApp_t *app) {
 	}
 	/* no autostart? ask the user */
 	if (app->curStation == NULL) {
-		app->curStation = BarUiSelectStation (app, app->ph.stations, "Select station: ", NULL);
+		app->curStation = BarUiSelectStation (app, app->ph.stations,
+				"Select station: ", NULL, app->settings.autoselect);
 	}
 	if (app->curStation != NULL) {
 		BarUiPrintStation (&app->settings, app->curStation);
diff --git a/src/settings.c b/src/settings.c
index ee332cc..54edba9 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -120,6 +120,7 @@ void BarSettingsRead (BarSettings_t *settings) {
 		settings->audioFormat = PIANO_AF_MP3;
 		#endif
 	#endif
+	settings->autoselect = true;
 	settings->history = 5;
 	settings->volume = 0;
 	settings->sortOrder = BAR_SORT_NAME_AZ;
@@ -242,6 +243,8 @@ void BarSettingsRead (BarSettings_t *settings) {
 		} else if (streq ("fifo", key)) {
 			free (settings->fifo);
 			settings->fifo = strdup (val);
+		} else if (streq ("autoselect", key)) {
+			settings->autoselect = atoi (val);
 		} else if (streq ("tls_fingerprint", key)) {
 			/* expects 40 byte hex-encoded sha1 */
 			if (strlen (val) == 40) {
diff --git a/src/settings.h b/src/settings.h
index b975b23..4c4205e 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -24,6 +24,8 @@ THE SOFTWARE.
 #ifndef _SETTINGS_H
 #define _SETTINGS_H
 
+#include <stdbool.h>
+
 #include <piano.h>
 #include <waitress.h>
 
@@ -78,6 +80,7 @@ typedef struct {
 } BarMsgFormatStr_t;
 
 typedef struct {
+	bool autoselect;
 	unsigned int history;
 	int volume;
 	BarStationSorting_t sortOrder;
diff --git a/src/ui.c b/src/ui.c
index acba151..104ee04 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -330,14 +330,17 @@ static PianoStation_t **BarSortedStations (PianoStation_t *unsortedStations,
 
 /*	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) {
+		const char *prompt, BarUiSelectStationCallback_t callback,
+		bool autoselect) {
 	PianoStation_t **sortedStations = NULL, *retStation = NULL;
-	size_t stationCount, i;
+	size_t stationCount, i, lastDisplayed, displayCount;
 	char buf[100];
 
 	if (stations == NULL) {
@@ -352,6 +355,7 @@ PianoStation_t *BarUiSelectStation (BarApp_t *app, PianoStation_t *stations,
 			app->settings.sortOrder);
 
 	do {
+		displayCount = 0;
 		for (i = 0; i < stationCount; i++) {
 			const PianoStation_t *currStation = sortedStations[i];
 			/* filter stations */
@@ -361,26 +365,33 @@ PianoStation_t *BarUiSelectStation (BarApp_t *app, PianoStation_t *stations,
 						currStation->isQuickMix ? 'Q' : ' ',
 						!currStation->isCreator ? 'S' : ' ',
 						currStation->name);
+				++displayCount;
+				lastDisplayed = i;
 			}
 		}
 
 		BarUiMsg (&app->settings, MSG_QUESTION, prompt);
-		if (BarReadlineStr (buf, sizeof (buf), &app->input,
-				BAR_RL_DEFAULT) == 0) {
-			free (sortedStations);
-			return NULL;
-		}
+		if (autoselect && displayCount == 1 && stationCount != 1) {
+			/* auto-select last remaining station */
+			BarUiMsg (&app->settings, MSG_NONE, "%i\n", lastDisplayed);
+			retStation = sortedStations[lastDisplayed];
+		} else {
+			if (BarReadlineStr (buf, sizeof (buf), &app->input,
+					BAR_RL_DEFAULT) == 0) {
+				break;
+			}
 
-		if (isnumeric (buf)) {
-			unsigned long selected = strtoul (buf, NULL, 0);
-			if (selected < stationCount) {
-				retStation = sortedStations[selected];
+			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);
+			/* hand over buffer to external function if it was not a station number */
+			if (retStation == NULL && callback != NULL) {
+				callback (app, buf);
+			}
 		}
 	} while (retStation == NULL);
 
diff --git a/src/ui.h b/src/ui.h
index 01d30fb..08dcca0 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -24,6 +24,8 @@ THE SOFTWARE.
 #ifndef _UI_H
 #define _UI_H
 
+#include <stdbool.h>
+
 #include <piano.h>
 #include <waitress.h>
 
@@ -37,7 +39,7 @@ typedef void (*BarUiSelectStationCallback_t) (BarApp_t *app, char *buf);
 
 void BarUiMsg (const BarSettings_t *, const BarUiMsg_t, const char *, ...);
 PianoStation_t *BarUiSelectStation (BarApp_t *, PianoStation_t *, const char *,
-		BarUiSelectStationCallback_t);
+		BarUiSelectStationCallback_t, bool);
 PianoSong_t *BarUiSelectSong (const BarSettings_t *, PianoSong_t *,
 		BarReadlineFds_t *);
 PianoArtist_t *BarUiSelectArtist (BarApp_t *, PianoArtist_t *);
diff --git a/src/ui_act.c b/src/ui_act.c
index df6cb73..2cc559f 100644
--- a/src/ui_act.c
+++ b/src/ui_act.c
@@ -316,7 +316,7 @@ BarUiActCallback(BarUiActMoveSong) {
 	reqData.step = 0;
 
 	reqData.to = BarUiSelectStation (app, app->ph.stations,
-			"Move song to station: ", NULL);
+			"Move song to station: ", NULL, false);
 	if (reqData.to != NULL) {
 		/* find original station (just is case we're playing a quickmix
 		 * station) */
@@ -379,7 +379,7 @@ BarUiActCallback(BarUiActRenameStation) {
  */
 BarUiActCallback(BarUiActSelectStation) {
 	PianoStation_t *newStation = BarUiSelectStation (app, app->ph.stations,
-			"Select station: ", NULL);
+			"Select station: ", NULL, app->settings.autoselect);
 	if (newStation != NULL) {
 		app->curStation = newStation;
 		BarUiPrintStation (&app->settings, app->curStation);
@@ -475,7 +475,7 @@ BarUiActCallback(BarUiActSelectQuickMix) {
 		PianoStation_t *toggleStation;
 		while ((toggleStation = BarUiSelectStation (app, app->ph.stations,
 				"Toggle quickmix for station: ",
-				BarUiActQuickmixCallback)) != NULL) {
+				BarUiActQuickmixCallback, false)) != NULL) {
 			toggleStation->useQuickMix = !toggleStation->useQuickMix;
 		}
 		BarUiMsg (&app->settings, MSG_INFO, "Setting quickmix stations... ");
@@ -660,7 +660,8 @@ BarUiActCallback(BarUiActManageStation) {
 			}
 		} else if (selectBuf[0] == 't') {
 			PianoStation_t *station = BarUiSelectStation (app,
-					reqData.info.stationSeeds, "Delete seed station: ", NULL);
+					reqData.info.stationSeeds, "Delete seed station: ", NULL,
+					false);
 			if (station != NULL) {
 				PianoRequestDataDeleteSeed_t subReqData;
 
-- 
cgit v1.2.3