summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcastlec <castlec@yahoo.com>2010-12-05 14:29:17 -0500
committerLars-Dominik Braun <lars@6xq.net>2010-12-14 19:08:20 +0100
commited8029f2dd2405da766c3cae716a94c40dde0115 (patch)
treeffeee622073a73aceee879aa36be61b3ce693830 /src
parent32eafb121f1cca1303518c85c3d12da9a7c5f16e (diff)
downloadpianobar-ed8029f2dd2405da766c3cae716a94c40dde0115.tar.gz
pianobar-ed8029f2dd2405da766c3cae716a94c40dde0115.tar.bz2
pianobar-ed8029f2dd2405da766c3cae716a94c40dde0115.zip
Refactored main()
No functional changes.
Diffstat (limited to 'src')
-rw-r--r--src/main.c608
-rw-r--r--src/main.h6
2 files changed, 351 insertions, 263 deletions
diff --git a/src/main.c b/src/main.c
index b582baf..89763d7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}
+
diff --git a/src/main.h b/src/main.h
index e22e2c0..6ab884a 100644
--- a/src/main.h
+++ b/src/main.h
@@ -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 */