From 4f43140468cefba39573d1efbded5258fcc56c93 Mon Sep 17 00:00:00 2001 From: Michał Cichoń Date: Tue, 25 Aug 2015 06:47:41 +0200 Subject: Port pianobar to Windows: - use newly introduced console.h instead of terminal.h which emulate some behavior of VT terminals - replace ffmpeg/libov player with more abstract one with DirectShow implementation --- src/main.c | 278 +++++++++++++++++++++---------------------------------------- 1 file changed, 95 insertions(+), 183 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index b113f4e..4800d2d 100644 --- a/src/main.c +++ b/src/main.c @@ -23,35 +23,11 @@ THE SOFTWARE. #include "config.h" -/* system includes */ -#include -#include -#include -/* fork () */ -#include -#include -#include -#include -/* open () */ -#include -#include -#include -/* tcset/getattr () */ -#include -#include #include -#include -#include -#include -/* waitpid () */ -#include -#include - -/* pandora.com library */ #include #include "main.h" -#include "terminal.h" +#include "console.h" #include "ui.h" #include "ui_dispatch.h" #include "ui_readline.h" @@ -79,14 +55,14 @@ static bool BarMainLoginUser (BarApp_t *app) { /* ask for username/password if none were provided in settings */ static bool BarMainGetLoginCredentials (BarSettings_t *settings, - BarReadlineFds_t *input) { + BarReadline_t rl) { bool usernameFromConfig = true; if (settings->username == NULL) { char nameBuf[100]; BarUiMsg (settings, MSG_QUESTION, "Email: "); - BarReadlineStr (nameBuf, sizeof (nameBuf), input, BAR_RL_DEFAULT); + BarReadlineStr (nameBuf, sizeof (nameBuf), rl, BAR_RL_DEFAULT); settings->username = strdup (nameBuf); usernameFromConfig = false; } @@ -100,58 +76,59 @@ static bool BarMainGetLoginCredentials (BarSettings_t *settings, if (settings->passwordCmd == NULL) { BarUiMsg (settings, MSG_QUESTION, "Password: "); - BarReadlineStr (passBuf, sizeof (passBuf), input, BAR_RL_NOECHO); + BarReadlineStr (passBuf, sizeof (passBuf), rl, BAR_RL_NOECHO); /* write missing newline */ puts (""); settings->password = strdup (passBuf); } else { - pid_t chld; - int pipeFd[2]; - - BarUiMsg (settings, MSG_INFO, "Requesting password from external helper... "); - - if (pipe (pipeFd) == -1) { - BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); - return false; - } - - chld = fork (); - if (chld == 0) { - /* child */ - close (pipeFd[0]); - dup2 (pipeFd[1], fileno (stdout)); - execl ("/bin/sh", "/bin/sh", "-c", settings->passwordCmd, (char *) NULL); - BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); - close (pipeFd[1]); - exit (1); - } else if (chld == -1) { - BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); - return false; - } else { - /* parent */ - int status; - - close (pipeFd[1]); - memset (passBuf, 0, sizeof (passBuf)); - read (pipeFd[0], passBuf, sizeof (passBuf)-1); - close (pipeFd[0]); - - /* drop trailing newlines */ - ssize_t len = strlen (passBuf)-1; - while (len >= 0 && passBuf[len] == '\n') { - passBuf[len] = '\0'; - --len; - } - - waitpid (chld, &status, 0); - if (WEXITSTATUS (status) == 0) { - settings->password = strdup (passBuf); - BarUiMsg (settings, MSG_NONE, "Ok.\n"); - } else { - BarUiMsg (settings, MSG_NONE, "Error: Exit status %i.\n", WEXITSTATUS (status)); - return false; - } - } + //pid_t chld; + //int pipeFd[2]; + + //BarUiMsg (settings, MSG_INFO, "Requesting password from external helper... "); + + //if (pipe (pipeFd) == -1) { + // BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); + // return false; + //} + + //chld = fork (); + //if (chld == 0) { + // /* child */ + // close (pipeFd[0]); + // dup2 (pipeFd[1], fileno (stdout)); + // execl ("/bin/sh", "/bin/sh", "-c", settings->passwordCmd, (char *) NULL); + // BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); + // close (pipeFd[1]); + // exit (1); + //} else if (chld == -1) { + // BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); + // return false; + //} else { + // /* parent */ + // int status; + + // close (pipeFd[1]); + // memset (passBuf, 0, sizeof (passBuf)); + // read (pipeFd[0], passBuf, sizeof (passBuf)-1); + // close (pipeFd[0]); + + // /* drop trailing newlines */ + // ssize_t len = strlen (passBuf)-1; + // while (len >= 0 && passBuf[len] == '\n') { + // passBuf[len] = '\0'; + // --len; + // } + + // waitpid (chld, &status, 0); + // if (WEXITSTATUS (status) == 0) { + // settings->password = strdup (passBuf); + // BarUiMsg (settings, MSG_NONE, "Ok.\n"); + // } else { + // BarUiMsg (settings, MSG_NONE, "Error: Exit status %i.\n", WEXITSTATUS (status)); + // return false; + // } + //} + return false; } /* end else passwordCmd */ } @@ -172,7 +149,7 @@ static bool BarMainGetStations (BarApp_t *app) { return ret; } -/* get initial station from autostart setting or user input +/* get initial station from autostart setting or user rl */ static void BarMainGetInitialStation (BarApp_t *app) { /* try to get autostart station */ @@ -194,11 +171,11 @@ static void BarMainGetInitialStation (BarApp_t *app) { } } -/* wait for user input +/* wait for user rl */ static void BarMainHandleUserInput (BarApp_t *app) { char buf[2]; - if (BarReadline (buf, sizeof (buf), NULL, &app->input, + if (BarReadline (buf, sizeof (buf), NULL, app->rl, BAR_RL_FULLRETURN | BAR_RL_NOECHO, 1) > 0) { BarUiDispatch (app, buf[0], app->curStation, app->playlist, true, BAR_DC_GLOBAL); @@ -232,9 +209,8 @@ static void BarMainGetPlaylist (BarApp_t *app) { /* start new player thread */ -static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) { +static void BarMainStartPlayback (BarApp_t *app) { assert (app != NULL); - assert (playerThread != NULL); const PianoSong_t * const curSong = app->playlist; assert (curSong != NULL); @@ -249,86 +225,66 @@ static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) { strncmp (curSong->audioUrl, httpPrefix, strlen (httpPrefix)) != 0) { BarUiMsg (&app->settings, MSG_ERR, "Invalid song url.\n"); } else { - /* setup player */ - memset (&app->player, 0, sizeof (app->player)); - - app->player.url = curSong->audioUrl; - app->player.gain = curSong->fileGain; - app->player.settings = &app->settings; - app->player.songDuration = curSong->length; - pthread_mutex_init (&app->player.pauseMutex, NULL); - pthread_cond_init (&app->player.pauseCond, NULL); + BarPlayer2Open(app->player, curSong->audioUrl); + BarPlayer2SetGain(app->player, curSong->fileGain); /* throw event */ BarUiStartEventCmd (&app->settings, "songstart", app->curStation, curSong, &app->player, app->ph.stations, PIANO_RET_OK, CURLE_OK); - /* prevent race condition, mode must _not_ be DEAD if - * thread has been started */ - app->player.mode = PLAYER_WAITING; - /* start player */ - pthread_create (playerThread, NULL, BarPlayerThread, - &app->player); + BarPlayer2Play(app->player); } } /* player is done, clean up */ -static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) { - void *threadRet; - +static void BarMainPlayerCleanup (BarApp_t *app) { BarUiStartEventCmd (&app->settings, "songfinish", app->curStation, app->playlist, &app->player, app->ph.stations, PIANO_RET_OK, CURLE_OK); - /* FIXME: pthread_join blocks everything if network connection - * is hung up e.g. */ - pthread_join (*playerThread, &threadRet); - pthread_cond_destroy (&app->player.pauseCond); - pthread_mutex_destroy (&app->player.pauseMutex); - - if (threadRet == (void *) PLAYER_RET_OK) { - app->playerErrors = 0; - } else if (threadRet == (void *) PLAYER_RET_SOFTFAIL) { - ++app->playerErrors; - if (app->playerErrors >= app->settings.maxPlayerErrors) { - /* don't continue playback if thread reports too many error */ - app->curStation = NULL; - } - } else { - app->curStation = NULL; - } - - memset (&app->player, 0, sizeof (app->player)); + BarPlayer2Finish(app->player); + + //if (threadRet == (void *) PLAYER_RET_OK) { + // app->playerErrors = 0; + //} else if (threadRet == (void *) PLAYER_RET_SOFTFAIL) { + // ++app->playerErrors; + // if (app->playerErrors >= app->settings.maxPlayerErrors) { + // /* don't continue playback if thread reports too many error */ + // app->curStation = NULL; + // } + //} else { + // app->curStation = NULL; + //} } /* print song duration */ static void BarMainPrintTime (BarApp_t *app) { - unsigned int songRemaining; + double songPlayed, songDuration, songRemaining; char sign; - if (app->player.songPlayed <= app->player.songDuration) { - songRemaining = app->player.songDuration - app->player.songPlayed; + songDuration = BarPlayer2GetDuration(app->player); + songPlayed = BarPlayer2GetTime(app->player); + + if (songPlayed <= songDuration) { + songRemaining = songDuration - songPlayed; sign = '-'; } else { /* longer than expected */ - songRemaining = app->player.songPlayed - app->player.songDuration; + songRemaining = songPlayed - songDuration; sign = '+'; } BarUiMsg (&app->settings, MSG_TIME, "%c%02u:%02u/%02u:%02u\r", - sign, songRemaining / 60, songRemaining % 60, - app->player.songDuration / 60, - app->player.songDuration % 60); + sign, (int)songRemaining / 60, (int)songRemaining % 60, + (int)songDuration / 60, (int)songDuration % 60); } /* main loop */ static void BarMainLoop (BarApp_t *app) { - pthread_t playerThread; - - if (!BarMainGetLoginCredentials (&app->settings, &app->input)) { + if (!BarMainGetLoginCredentials (&app->settings, app->rl)) { return; } @@ -342,19 +298,15 @@ static void BarMainLoop (BarApp_t *app) { 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)); - while (!app->doQuit) { /* song finished playing, clean up things/scrobble song */ - if (app->player.mode == PLAYER_FINISHED) { - BarMainPlayerCleanup (app, &playerThread); + if (BarPlayer2IsStopped(app->player)) { + BarMainPlayerCleanup (app); } /* check whether player finished playing and start playing new * song */ - if (app->player.mode == PLAYER_DEAD && app->curStation != NULL) { + if (BarPlayer2IsFinished(app->player) && app->curStation != NULL) { /* what's next? */ if (app->playlist != NULL) { PianoSong_t *histsong = app->playlist; @@ -367,21 +319,17 @@ static void BarMainLoop (BarApp_t *app) { } /* song ready to play */ if (app->playlist != NULL) { - BarMainStartPlayback (app, &playerThread); + BarMainStartPlayback (app); } } BarMainHandleUserInput (app); /* show time */ - if (app->player.mode == PLAYER_PLAYING) { + if (BarPlayer2IsPlaying(app->player) || BarPlayer2IsPaused(app->player)) { BarMainPrintTime (app); } } - - if (app->player.mode != PLAYER_DEAD) { - pthread_join (playerThread, NULL); - } } int main (int argc, char **argv) { @@ -389,17 +337,10 @@ int main (int argc, char **argv) { memset (&app, 0, sizeof (app)); - /* save terminal attributes, before disabling echoing */ - BarTermInit (); - - /* signals */ - signal (SIGPIPE, SIG_IGN); + BarConsoleInit (); /* init some things */ - gcry_check_version (NULL); - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); - BarPlayerInit (); + BarPlayer2Init (&app.player); BarSettingsInit (&app.settings); BarSettingsRead (&app.settings); @@ -414,7 +355,7 @@ int main (int argc, char **argv) { } BarUiMsg (&app.settings, MSG_NONE, - "Welcome to " PACKAGE " (" VERSION ")! "); + "Welcome to " PACKAGE " (" VERSION ")!\n"); if (app.settings.keys[BAR_KS_HELP] == BAR_KS_DISABLED) { BarUiMsg (&app.settings, MSG_NONE, "\n"); } else { @@ -427,38 +368,11 @@ int main (int argc, char **argv) { app.http = curl_easy_init (); assert (app.http != NULL); - /* init fds */ - FD_ZERO(&app.input.set); - app.input.fds[0] = STDIN_FILENO; - FD_SET(app.input.fds[0], &app.input.set); - - /* open fifo read/write so it won't EOF if nobody writes to it */ - assert (sizeof (app.input.fds) / sizeof (*app.input.fds) >= 2); - app.input.fds[1] = open (app.settings.fifo, O_RDWR); - if (app.input.fds[1] != -1) { - struct stat s; - - /* check for file type, must be fifo */ - fstat (app.input.fds[1], &s); - if (!S_ISFIFO (s.st_mode)) { - BarUiMsg (&app.settings, MSG_ERR, "File at %s is not a fifo\n", app.settings.fifo); - close (app.input.fds[1]); - app.input.fds[1] = -1; - } else { - FD_SET(app.input.fds[1], &app.input.set); - BarUiMsg (&app.settings, MSG_INFO, "Control fifo at %s opened\n", - app.settings.fifo); - } - } - app.input.maxfd = app.input.fds[0] > app.input.fds[1] ? app.input.fds[0] : - app.input.fds[1]; - ++app.input.maxfd; + BarReadlineInit (&app.rl); BarMainLoop (&app); - if (app.input.fds[1] != -1) { - close (app.input.fds[1]); - } + BarReadlineDestroy (app.rl); /* write statefile */ BarSettingsWrite (app.curStation, &app.settings); @@ -468,11 +382,9 @@ int main (int argc, char **argv) { PianoDestroyPlaylist (app.playlist); curl_easy_cleanup (app.http); curl_global_cleanup (); - BarPlayerDestroy (); + BarPlayer2Destroy (app.player); BarSettingsDestroy (&app.settings); - - /* restore terminal attributes, zsh doesn't need this, bash does... */ - BarTermRestore (); + BarConsoleDestroy (); return 0; } -- cgit v1.2.3