diff options
| author | castlec <castlec@yahoo.com> | 2010-12-05 14:29:17 -0500 | 
|---|---|---|
| committer | Lars-Dominik Braun <lars@6xq.net> | 2010-12-14 19:08:20 +0100 | 
| commit | ed8029f2dd2405da766c3cae716a94c40dde0115 (patch) | |
| tree | ffeee622073a73aceee879aa36be61b3ce693830 | |
| parent | 32eafb121f1cca1303518c85c3d12da9a7c5f16e (diff) | |
| download | pianobar-windows-ed8029f2dd2405da766c3cae716a94c40dde0115.tar.gz pianobar-windows-ed8029f2dd2405da766c3cae716a94c40dde0115.tar.bz2 pianobar-windows-ed8029f2dd2405da766c3cae716a94c40dde0115.zip | |
Refactored main()
No functional changes.
| -rw-r--r-- | src/main.c | 608 | ||||
| -rw-r--r-- | src/main.h | 6 | 
2 files changed, 351 insertions, 263 deletions
| @@ -40,6 +40,7 @@ THE SOFTWARE.  #include <termios.h>  #include <pthread.h>  #include <assert.h> +#include <stdbool.h>  /* pandora.com library */  #include <piano.h> @@ -53,319 +54,399 @@ THE SOFTWARE.  typedef void (*BarKeyShortcutFunc_t) (BarApp_t *app, FILE *curFd); -int main (int argc, char **argv) { -	static BarApp_t app; -	pthread_t playerThread; -	/* FIXME: max path length? */ -	char ctlPath[1024]; -	FILE *ctlFd = NULL; -	struct timeval selectTimeout; -	int maxFd, selectFds[2] = {-1, -1}; -	fd_set readSet, readSetCopy; -	char buf = '\0'; -	/* terminal attributes _before_ we started messing around with ~ECHO */ -	struct termios termOrig; - -	memset (&app, 0, sizeof (app)); - -	/* save terminal attributes, before disabling echoing */ -	BarTermSave (&termOrig); - -	BarTermSetEcho (0); -	BarTermSetBuffer (0); -	/* init some things */ -	ao_initialize (); -	PianoInit (&app.ph); - -	WaitressInit (&app.waith); -	strncpy (app.waith.host, PIANO_RPC_HOST, sizeof (app.waith.host)-1); -	strncpy (app.waith.port, PIANO_RPC_PORT, sizeof (app.waith.port)-1); - -	BarSettingsInit (&app.settings); -	BarSettingsRead (&app.settings); +/*	copy proxy settings to waitress handle + */ +static void BarMainLoadProxy (const BarSettings_t *settings, +		WaitressHandle_t *waith) { +	char tmpPath[2]; -	BarUiMsg (MSG_NONE, "Welcome to " PACKAGE " (" VERSION ")! " -			"Press %c for a list of commands.\n", -			app.settings.keys[BAR_KS_HELP]); - -	/* init fds */ -	FD_ZERO(&readSet); -	selectFds[0] = fileno (stdin); -	FD_SET(selectFds[0], &readSet); -	maxFd = selectFds[0] + 1; +	/* set up proxy (control proxy for non-us citizen or global proxy for poor +	 * firewalled fellows) */ +	if (settings->controlProxy != NULL) { +		/* control proxy overrides global proxy */ +		WaitressSplitUrl (settings->controlProxy, waith->proxyHost, +				sizeof (waith->proxyHost), waith->proxyPort, +				sizeof (waith->proxyPort), tmpPath, sizeof (tmpPath)); +	} else if (settings->proxy != NULL && strlen (settings->proxy) > 0) { +		WaitressSplitUrl (settings->proxy, waith->proxyHost, +				sizeof (waith->proxyHost), waith->proxyPort, +				sizeof (waith->proxyPort), tmpPath, sizeof (tmpPath)); +	} +} -	BarGetXdgConfigDir (PACKAGE "/ctl", ctlPath, sizeof (ctlPath)); -	/* FIXME: why is r_+_ required? */ -	ctlFd = fopen (ctlPath, "r+"); -	if (ctlFd != NULL) { -		selectFds[1] = fileno (ctlFd); -		FD_SET(selectFds[1], &readSet); -		/* assuming ctlFd is always > stdin */ -		maxFd = selectFds[1] + 1; -		BarUiMsg (MSG_INFO, "Control fifo at %s opened\n", ctlPath); +/*	authenticate user + */ +static bool BarMainLoginUser (BarApp_t *app) { +	PianoReturn_t pRet; +	WaitressReturn_t wRet; +	PianoRequestDataLogin_t reqData; +	reqData.user = app->settings.username; +	reqData.password = app->settings.password; +	reqData.step = 0; + +	BarUiMsg (MSG_INFO, "Login... "); +	if (!BarUiPianoCall (app, PIANO_REQUEST_LOGIN, &reqData, &pRet, &wRet)) { +		return false;  	} +	return true; +} -	if (app.settings.username == NULL) { +/*	ask for username/password if none were provided in settings + */ +static void BarMainGetLoginCredentials (BarSettings_t *settings) { +	if (settings->username == NULL) {  		char nameBuf[100];  		BarUiMsg (MSG_QUESTION, "Username: ");  		BarReadlineStr (nameBuf, sizeof (nameBuf), 0, stdin); -		app.settings.username = strdup (nameBuf); +		settings->username = strdup (nameBuf);  	} -	if (app.settings.password == NULL) { +	if (settings->password == NULL) {  		char passBuf[100];  		BarUiMsg (MSG_QUESTION, "Password: ");  		BarReadlineStr (passBuf, sizeof (passBuf), 1, stdin); -		app.settings.password = strdup (passBuf); +		settings->password = strdup (passBuf);  	} +} -	/* set up proxy (control proxy for non-us citizen or global proxy for poor -	 * firewalled fellows) */ -	if (app.settings.controlProxy != NULL) { -		/* control proxy overrides global proxy */ -		char tmpPath[2]; -		WaitressSplitUrl (app.settings.controlProxy, app.waith.proxyHost, -				sizeof (app.waith.proxyHost), app.waith.proxyPort, -				sizeof (app.waith.proxyPort), tmpPath, sizeof (tmpPath)); -	} else if (app.settings.proxy != NULL && strlen (app.settings.proxy) > 0) { -		char tmpPath[2]; -		WaitressSplitUrl (app.settings.proxy, app.waith.proxyHost, -				sizeof (app.waith.proxyHost), app.waith.proxyPort, -				sizeof (app.waith.proxyPort), tmpPath, sizeof (tmpPath)); +/*	get station list + */ +static bool BarMainGetStations (BarApp_t *app) { +	PianoReturn_t pRet; +	WaitressReturn_t wRet; + +	BarUiMsg (MSG_INFO, "Get stations... "); +	if (!BarUiPianoCall (app, PIANO_REQUEST_GET_STATIONS, NULL, &pRet, +			&wRet)) { +		return false;  	} +	return true; +} -	{ -		PianoReturn_t pRet; -		WaitressReturn_t wRet; -		PianoRequestDataLogin_t reqData; -		reqData.user = app.settings.username; -		reqData.password = app.settings.password; -		reqData.step = 0; -		 -		BarUiMsg (MSG_INFO, "Login... "); -		if (!BarUiPianoCall (&app, PIANO_REQUEST_LOGIN, &reqData, &pRet, -				&wRet)) { -			BarTermRestore (&termOrig); -			return 0; +/*	get initial station from autostart setting or user input + */ +static void BarMainGetInitialStation (BarApp_t *app) { +	/* try to get autostart station */ +	if (app->settings.autostartStation != NULL) { +		app->curStation = PianoFindStationById (app->ph.stations, +				app->settings.autostartStation); +		if (app->curStation == NULL) { +			BarUiMsg (MSG_ERR, "Error: Autostart station not found.\n");  		}  	} +	/* no autostart? ask the user */ +	if (app->curStation == NULL) { +		app->curStation = BarUiSelectStation (&(app->ph), "Select station: ", +				app->settings.sortOrder, stdin); +	} +	if (app->curStation != NULL) { +		BarUiPrintStation (app->curStation); +	} +} + +/*	wait for user input + */ +static void BarMainHandleUserInput (BarApp_t *app) { +	struct timeval selectTimeout; +	fd_set readSetCopy; +	char buf = '\0'; + +	/* select modifies its arguments => copy the set */ +	memcpy (&readSetCopy, &app->readSet, sizeof (app->readSet)); +	selectTimeout.tv_sec = 1; +	selectTimeout.tv_usec = 0; -	{ -		PianoReturn_t pRet; -		WaitressReturn_t wRet; +	/* in the meantime: wait for user actions */ +	if (select (app->maxFd, &readSetCopy, NULL, NULL, &selectTimeout) > 0) { +		FILE *curFd = NULL; -		BarUiMsg (MSG_INFO, "Get stations... "); -		if (!BarUiPianoCall (&app, PIANO_REQUEST_GET_STATIONS, NULL, &pRet, -				&wRet)) { -			BarTermRestore (&termOrig); -			return 0; +		if (FD_ISSET(app->selectFds[0], &readSetCopy)) { +			curFd = stdin; +		} else if (app->selectFds[1] != -1 && FD_ISSET(app->selectFds[1], +				&readSetCopy)) { +			curFd = app->ctlFd; +		} +		buf = fgetc (curFd); + +		size_t i; +		for (i = 0; i < BAR_KS_COUNT; i++) { +			if (app->settings.keys[i] == buf) { +				static const BarKeyShortcutFunc_t idToF[] = {BarUiActHelp, +						BarUiActLoveSong, BarUiActBanSong, +						BarUiActAddMusic, BarUiActCreateStation, +						BarUiActDeleteStation, BarUiActExplain, +						BarUiActStationFromGenre, BarUiActHistory, +						BarUiActSongInfo, BarUiActAddSharedStation, +						BarUiActMoveSong, BarUiActSkipSong, BarUiActPause, +						BarUiActQuit, BarUiActRenameStation, +						BarUiActSelectStation, BarUiActTempBanSong, +						BarUiActPrintUpcoming, BarUiActSelectQuickMix, +						BarUiActDebug, BarUiActBookmark}; +				idToF[i] (app, curFd); +				break; +			}  		}  	} +} -	/* try to get autostart station */ -	if (app.settings.autostartStation != NULL) { -		app.curStation = PianoFindStationById (app.ph.stations, -				app.settings.autostartStation); -		if (app.curStation == NULL) { -			BarUiMsg (MSG_ERR, "Error: Autostart station not found.\n"); +/*	append current song to history list and move to the next song + */ +static void BarMainNextSong (BarApp_t *app) { +	if (app->settings.history != 0) { +		/* prepend song to history list */ +		PianoSong_t *tmpSong = app->songHistory; +		app->songHistory = app->playlist; +		/* select next song */ +		app->playlist = app->playlist->next; +		app->songHistory->next = tmpSong; + +		/* limit history's length */ +		/* start with 1, so we're stopping at n-1 and have the +		 * chance to set ->next = NULL */ +		unsigned int i = 1; +		tmpSong = app->songHistory; +		while (i < app->settings.history && tmpSong != NULL) { +			tmpSong = tmpSong->next; +			++i; +		} +		/* if too many songs in history... */ +		if (tmpSong != NULL) { +			PianoSong_t *delSong = tmpSong->next; +			tmpSong->next = NULL; +			if (delSong != NULL) { +				PianoDestroyPlaylist (delSong); +			}  		} +	} else { +		/* don't keep history */ +		app->playlist = app->playlist->next;  	} -	/* no autostart? ask the user */ -	if (app.curStation == NULL) { -		app.curStation = BarUiSelectStation (&app.ph, "Select station: ", -				app.settings.sortOrder, stdin); +} + +/*	fetch new playlist + */ +static void BarMainGetPlaylist (BarApp_t *app) { +	PianoReturn_t pRet; +	WaitressReturn_t wRet; +	PianoRequestDataGetPlaylist_t reqData; +	reqData.station = app->curStation; +	reqData.format = app->settings.audioFormat; + +	BarUiMsg (MSG_INFO, "Receiving new playlist... "); +	if (!BarUiPianoCall (app, PIANO_REQUEST_GET_PLAYLIST, +			&reqData, &pRet, &wRet)) { +		app->curStation = NULL; +	} else { +		app->playlist = reqData.retPlaylist; +		if (app->playlist == NULL) { +			BarUiMsg (MSG_INFO, "No tracks left.\n"); +			app->curStation = NULL; +		}  	} -	if (app.curStation != NULL) { -		BarUiPrintStation (app.curStation); +	BarUiStartEventCmd (&app->settings, "stationfetchplaylist", +			app->curStation, app->playlist, &app->player, pRet, +			wRet); +} + +/*	start new player thread + */ +static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) { +	BarUiPrintSong (&app->settings, app->playlist, app->curStation->isQuickMix ? +			PianoFindStationById (app->ph.stations, +			app->playlist->stationId) : NULL); + +	if (app->playlist->audioUrl == NULL) { +		BarUiMsg (MSG_ERR, "Invalid song url.\n"); +	} else { +		/* setup player */ +		memset (&app->player, 0, sizeof (app->player)); + +		WaitressInit (&app->player.waith); +		WaitressSetUrl (&app->player.waith, app->playlist->audioUrl); + +		/* set up global proxy, player is NULLed on songfinish */ +		if (app->settings.proxy != NULL) { +			char tmpPath[2]; +			WaitressSplitUrl (app->settings.proxy, +					app->player.waith.proxyHost, +					sizeof (app->player.waith.proxyHost), +					app->player.waith.proxyPort, +					sizeof (app->player.waith.proxyPort), tmpPath, +					sizeof (tmpPath)); +		} + +		app->player.gain = app->playlist->fileGain; +		app->player.audioFormat = app->playlist->audioFormat; + +		/* throw event */ +		BarUiStartEventCmd (&app->settings, "songstart", +				app->curStation, app->playlist, &app->player, +				PIANO_RET_OK, WAITRESS_RET_OK); + +		/* prevent race condition, mode must _not_ be FREED if +		 * thread has been started */ +		app->player.mode = PLAYER_STARTING; +		/* start player */ +		pthread_create (playerThread, NULL, BarPlayerThread, +				&app->player); +	} +} + +/*	player is done, clean up + */ +static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) { +	void *threadRet; + +	BarUiStartEventCmd (&app->settings, "songfinish", app->curStation, +			app->playlist, &app->player, PIANO_RET_OK, WAITRESS_RET_OK); + +	/* FIXME: pthread_join blocks everything if network connection +	 * is hung up e.g. */ +	pthread_join (*playerThread, &threadRet); + +	/* don't continue playback if thread reports error */ +	if (threadRet != (void *) PLAYER_RET_OK) { +		app->curStation = NULL; +	} + +	memset (&app->player, 0, sizeof (app->player)); +} + +/*	print song duration + */ +static void BarMainPrintTime (BarApp_t *app) { +	/* Ugly: songDuration is unsigned _long_ int! Lets hope this won't +	 * overflow */ +	int songRemaining = (signed long int) (app->player.songDuration - +			app->player.songPlayed) / BAR_PLAYER_MS_TO_S_FACTOR; +	enum {POSITIVE, NEGATIVE} sign = NEGATIVE; +	if (songRemaining < 0) { +		/* song is longer than expected */ +		sign = POSITIVE; +		songRemaining = -songRemaining; +	} +	BarUiMsg (MSG_TIME, "%c%02i:%02i/%02i:%02i\r", +			(sign == POSITIVE ? '+' : '-'), +			songRemaining / 60, songRemaining % 60, +			app->player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR / 60, +			app->player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR % 60); +} + +/*	main loop + */ +static void BarMainLoop (BarApp_t *app) { +	pthread_t playerThread; + +	BarMainGetLoginCredentials (&app->settings); + +	BarMainLoadProxy (&app->settings, &app->waith); + +	if (!BarMainLoginUser (app)) { +		return; +	} + +	if (!BarMainGetStations (app)) { +		return;  	} +	BarMainGetInitialStation (app); +  	/* little hack, needed to signal: hey! we need a playlist, but don't  	 * free anything (there is nothing to be freed yet) */ -	memset (&app.player, 0, sizeof (app.player)); +	memset (&app->player, 0, sizeof (app->player)); -	while (!app.doQuit) { +	while (!app->doQuit) {  		/* song finished playing, clean up things/scrobble song */ -		if (app.player.mode == PLAYER_FINISHED_PLAYBACK) { -			BarUiStartEventCmd (&app.settings, "songfinish", app.curStation, -					app.playlist, &app.player, PIANO_RET_OK, WAITRESS_RET_OK); -			/* FIXME: pthread_join blocks everything if network connection -			 * is hung up e.g. */ -			void *threadRet; -			pthread_join (playerThread, &threadRet); -			/* don't continue playback if thread reports error */ -			if (threadRet != (void *) PLAYER_RET_OK) { -				app.curStation = NULL; -			} -			memset (&app.player, 0, sizeof (app.player)); +		if (app->player.mode == PLAYER_FINISHED_PLAYBACK) { +			BarMainPlayerCleanup (app, &playerThread);  		}  		/* check whether player finished playing and start playing new  		 * song */ -		if (app.player.mode >= PLAYER_FINISHED_PLAYBACK || -				app.player.mode == PLAYER_FREED) { -			if (app.curStation != NULL) { +		if (app->player.mode >= PLAYER_FINISHED_PLAYBACK || +				app->player.mode == PLAYER_FREED) { +			if (app->curStation != NULL) {  				/* what's next? */ -				if (app.playlist != NULL) { -					if (app.settings.history != 0) { -						/* prepend song to history list */ -						PianoSong_t *tmpSong = app.songHistory; -						app.songHistory = app.playlist; -						/* select next song */ -						app.playlist = app.playlist->next; -						app.songHistory->next = tmpSong; - -						/* limit history's length */ -						/* start with 1, so we're stopping at n-1 and have the -						 * chance to set ->next = NULL */ -						unsigned int i = 1; -						tmpSong = app.songHistory; -						while (i < app.settings.history && tmpSong != NULL) { -							tmpSong = tmpSong->next; -							++i; -						} -						/* if too many songs in history... */ -						if (tmpSong != NULL) { -							PianoSong_t *delSong = tmpSong->next; -							tmpSong->next = NULL; -							if (delSong != NULL) { -								PianoDestroyPlaylist (delSong); -							} -						} -					} else { -						/* don't keep history */ -						app.playlist = app.playlist->next; -					} +				if (app->playlist != NULL) { +					BarMainNextSong (app);  				} -				if (app.playlist == NULL) { -					PianoReturn_t pRet; -					WaitressReturn_t wRet; -					PianoRequestDataGetPlaylist_t reqData; -					reqData.station = app.curStation; -					reqData.format = app.settings.audioFormat; - -					BarUiMsg (MSG_INFO, "Receiving new playlist... "); -					if (!BarUiPianoCall (&app, PIANO_REQUEST_GET_PLAYLIST, -							&reqData, &pRet, &wRet)) { -						app.curStation = NULL; -					} else { -						app.playlist = reqData.retPlaylist; -						if (app.playlist == NULL) { -							BarUiMsg (MSG_INFO, "No tracks left.\n"); -							app.curStation = NULL; -						} -					} -					BarUiStartEventCmd (&app.settings, "stationfetchplaylist", -							app.curStation, app.playlist, &app.player, pRet, -							wRet); +				if (app->playlist == NULL) { +					BarMainGetPlaylist (app);  				}  				/* song ready to play */ -				if (app.playlist != NULL) { -					BarUiPrintSong (&app.settings, app.playlist, -							app.curStation->isQuickMix ? -							PianoFindStationById (app.ph.stations, -							app.playlist->stationId) : NULL); - -					if (app.playlist->audioUrl == NULL) { -						BarUiMsg (MSG_ERR, "Invalid song url.\n"); -					} else { -						/* setup player */ -						memset (&app.player, 0, sizeof (app.player)); - -						WaitressInit (&app.player.waith); -						WaitressSetUrl (&app.player.waith, app.playlist->audioUrl); - -						/* set up global proxy, player is NULLed on songfinish */ -						if (app.settings.proxy != NULL) { -							char tmpPath[2]; -							WaitressSplitUrl (app.settings.proxy, -									app.player.waith.proxyHost, -									sizeof (app.player.waith.proxyHost), -									app.player.waith.proxyPort, -									sizeof (app.player.waith.proxyPort), tmpPath, -									sizeof (tmpPath)); -						} - -						app.player.gain = app.playlist->fileGain; -						app.player.audioFormat = app.playlist->audioFormat; -			 -						/* throw event */ -						BarUiStartEventCmd (&app.settings, "songstart", -								app.curStation, app.playlist, &app.player, -								PIANO_RET_OK, WAITRESS_RET_OK); - -						/* prevent race condition, mode must _not_ be FREED if -						 * thread has been started */ -						app.player.mode = PLAYER_STARTING; -						/* start player */ -						pthread_create (&playerThread, NULL, BarPlayerThread, -								&app.player); -					} /* end if audioUrl == NULL */ -				} /* end if playlist != NULL */ -			} /* end if curStation != NULL */ -		} - -		/* select modifies its arguments => copy the set */ -		memcpy (&readSetCopy, &readSet, sizeof (readSet)); -		selectTimeout.tv_sec = 1; -		selectTimeout.tv_usec = 0; - -		/* in the meantime: wait for user actions */ -		if (select (maxFd, &readSetCopy, NULL, NULL, &selectTimeout) > 0) { -			FILE *curFd = NULL; - -			if (FD_ISSET(selectFds[0], &readSetCopy)) { -				curFd = stdin; -			} else if (selectFds[1] != -1 && FD_ISSET(selectFds[1], &readSetCopy)) { -				curFd = ctlFd; -			} -			buf = fgetc (curFd); - -			size_t i; -			for (i = 0; i < BAR_KS_COUNT; i++) { -				if (app.settings.keys[i] == buf) { -					static const BarKeyShortcutFunc_t idToF[] = {BarUiActHelp, -							BarUiActLoveSong, BarUiActBanSong, -							BarUiActAddMusic, BarUiActCreateStation, -							BarUiActDeleteStation, BarUiActExplain, -							BarUiActStationFromGenre, BarUiActHistory, -							BarUiActSongInfo, BarUiActAddSharedStation, -							BarUiActMoveSong, BarUiActSkipSong, BarUiActPause, -							BarUiActQuit, BarUiActRenameStation, -							BarUiActSelectStation, BarUiActTempBanSong, -							BarUiActPrintUpcoming, BarUiActSelectQuickMix, -							BarUiActDebug, BarUiActBookmark}; -					idToF[i] (&app, curFd); -					break; +				if (app->playlist != NULL) { +					BarMainStartPlayback (app, &playerThread);  				}  			}  		} +		BarMainHandleUserInput (app); +  		/* show time */ -		if (app.player.mode >= PLAYER_SAMPLESIZE_INITIALIZED && -				app.player.mode < PLAYER_FINISHED_PLAYBACK) { -			/* Ugly: songDuration is unsigned _long_ int! Lets hope this won't -			 * overflow */ -			int songRemaining = (signed long int) (app.player.songDuration - -					app.player.songPlayed) / BAR_PLAYER_MS_TO_S_FACTOR; -			char pos = 0; -			if (songRemaining < 0) { -				/* Use plus sign if song is longer than expected */ -				pos = 1; -				songRemaining = -songRemaining; -			} -			BarUiMsg (MSG_TIME, "%c%02i:%02i/%02i:%02i\r", (pos ? '+' : '-'), -					songRemaining / 60, songRemaining % 60, -					app.player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR / 60, -					app.player.songDuration / BAR_PLAYER_MS_TO_S_FACTOR % 60); +		if (app->player.mode >= PLAYER_SAMPLESIZE_INITIALIZED && +				app->player.mode < PLAYER_FINISHED_PLAYBACK) { +			BarMainPrintTime (app);  		}  	} -	/* destroy everything (including the world...) */ -	if (app.player.mode != PLAYER_FREED) { +	if (app->player.mode != PLAYER_FREED) {  		pthread_join (playerThread, NULL);  	} -	if (ctlFd != NULL) { -		fclose (ctlFd); +} + +int main (int argc, char **argv) { +	static BarApp_t app; +	/* FIXME: max path length? */ +	char ctlPath[1024]; +	/* terminal attributes _before_ we started messing around with ~ECHO */ +	struct termios termOrig; + +	memset (&app, 0, sizeof (app)); + +	/* save terminal attributes, before disabling echoing */ +	BarTermSave (&termOrig); +	BarTermSetEcho (0); +	BarTermSetBuffer (0); + +	/* init some things */ +	ao_initialize (); +	PianoInit (&app.ph); + +	WaitressInit (&app.waith); +	strncpy (app.waith.host, PIANO_RPC_HOST, sizeof (app.waith.host)-1); +	strncpy (app.waith.port, PIANO_RPC_PORT, sizeof (app.waith.port)-1); + +	BarSettingsInit (&app.settings); +	BarSettingsRead (&app.settings); + +	BarUiMsg (MSG_NONE, "Welcome to " PACKAGE " (" VERSION ")! " +			"Press %c for a list of commands.\n", +			app.settings.keys[BAR_KS_HELP]); + +	/* init fds */ +	FD_ZERO(&app.readSet); +	app.selectFds[0] = fileno (stdin); +	FD_SET(app.selectFds[0], &app.readSet); + +	BarGetXdgConfigDir (PACKAGE "/ctl", ctlPath, sizeof (ctlPath)); +	/* FIXME: why is r_+_ required? */ +	app.ctlFd = fopen (ctlPath, "r+"); +	if (app.ctlFd != NULL) { +		app.selectFds[1] = fileno (app.ctlFd); +		FD_SET(app.selectFds[1], &app.readSet); +		BarUiMsg (MSG_INFO, "Control fifo at %s opened\n", ctlPath); +	} else { +		app.selectFds[1] = -1; +	} +	app.maxFd = app.selectFds[0] > app.selectFds[1] ? app.selectFds[0] : +			app.selectFds[1]; +	++app.maxFd; + +	BarMainLoop (&app); + +	if (app.ctlFd != NULL) { +		fclose (app.ctlFd);  	} +  	PianoDestroy (&app.ph);  	PianoDestroyPlaylist (app.songHistory);  	PianoDestroyPlaylist (app.playlist); @@ -377,3 +458,4 @@ int main (int argc, char **argv) {  	return 0;  } + @@ -27,6 +27,8 @@ THE SOFTWARE.  #include <piano.h>  #include <waitress.h> +#include <sys/select.h> +  #include "player.h"  #include "settings.h" @@ -40,6 +42,10 @@ typedef struct {  	PianoSong_t *songHistory;  	PianoStation_t *curStation;  	char doQuit; +	fd_set readSet; +	int maxFd; +	int selectFds[2]; +	FILE *ctlFd;  } BarApp_t;  #endif /* _MAIN_H */ | 
