Permalink
Browse files

Merge with pianobar-2012.09.07.

  • Loading branch information...
Joshua V. Dillon
Joshua V. Dillon committed Nov 18, 2012
1 parent d0126f7 commit dfe00a4701882e05df4482fc97476b37713f6741
Showing with 347 additions and 188 deletions.
  1. +9 −0 ChangeLog
  2. +2 −0 contrib/config-example
  3. +15 −5 contrib/pianobarfly.1
  4. +1 −1 src/config.h
  5. +2 −0 src/libpiano/crypt.c
  6. +6 −1 src/libwaitress/waitress.c
  7. +1 −0 src/libwaitress/waitress.h
  8. +75 −7 src/main.c
  9. +36 −15 src/player.c
  10. +193 −157 src/settings.c
  11. +5 −2 src/settings.h
  12. +2 −0 src/ui.c
View
@@ -1,3 +1,12 @@
+Release 2012.09.07
+
+- Defunct move song (keybinding 'm') feature removed
+- Added feature: Create station from song (keybinding 'v')
+- '<space>' (setting act_songpause2) toggles pause too
+- Makefile: Auto-dependency generation
+- Correctly initialize libgcrypt
+- headless_pianobar wrapper added
+
Release 2012.06.24
- Removed setting audio_format, added audio_quality. libfaad (aac) is now required,
View
@@ -5,6 +5,8 @@
# User
#user = your@user.name
#password = password
+# or
+#password_command = gpg --decrypt ~/password
# Proxy (for those who are not living in the USA)
#control_proxy = http://127.0.0.1:9090/
View
@@ -115,6 +115,7 @@ Skip current song.
.TP
.B act_songpause = p
+.TQ
.B act_songpause2 = <Space>
Pause/Continue
@@ -210,7 +211,7 @@ or the key you defined in
Icon for banned songs.
.TP
-.B control_proxy = http://host:port/
+.B control_proxy = http://user:password@host:port/
Non-american users need a proxy to use pandora.com. Only the xmlrpc interface
will use this proxy. The music is streamed directly.
@@ -327,13 +328,22 @@ Icon for loved songs.
Your pandora.com password. Plain-text.
.TP
-.B proxy = http://host:port/
+.B password_command = gpg --decrypt ~/password
+Use output of command as password. This setting is overridden by specifying a
+password with
+.B password.
+
+.TP
+.B proxy = http://user:password@host:port/
Use a http proxy. Note that this setting overrides the http_proxy environment
-variable.
+variable. Only "Basic" http authentication is supported.
.TP
.B rpc_host = tuner.pandora.com
+.TP
+.B rpc_tls_port = 443
+
.TP
.B sort = {name_az, name_za, quickmix_01_name_az, quickmix_01_name_za, quickmix_10_name_az, quickmix_10_name_za}
Sort station list by name or type (is quickmix) and name. name_az for example
@@ -387,8 +397,8 @@ Another example:
can report certain "events" to an external application (see
.B CONFIGURATION
). This application is started with the event name as it's first argument. More
-information (artist, title, album, stationName, error code, error description,
-song length in milliseconds, rating, album art url) is supplied through stdin.
+information like error code and description, was well as song information
+related to the current event, is supplied through stdin.
Currently supported events are: artistbookmark, songban, songbookmark,
songexplain, songfinish, songlove, songmove, songshelf, songstart,
View
@@ -4,6 +4,6 @@
/* package name */
#define PACKAGE "pianobarfly"
-#define VERSION "2012.06.24-dev"
+#define VERSION "2012.09.07-dev"
#endif /* _CONFIG_H */
View
@@ -57,6 +57,7 @@ char *PianoDecryptString (gcry_cipher_hd_t h, const char * const input,
gret = gcry_cipher_decrypt (h, output, outputLen, NULL, 0);
if (gret) {
+ free (output);
return NULL;
}
@@ -82,6 +83,7 @@ char *PianoEncryptString (gcry_cipher_hd_t h, const char *s) {
gret = gcry_cipher_encrypt (h, paddedInput, paddedInputLen, NULL, 0);
if (gret) {
+ free (paddedInput);
return NULL;
}
@@ -39,6 +39,7 @@ THE SOFTWARE.
#include <poll.h>
#include <errno.h>
#include <assert.h>
+#include <stdint.h>
#include <gnutls/x509.h>
@@ -592,7 +593,11 @@ static bool WaitressFormatAuthorization (WaitressHandle_t *waith,
static const char *WaitressDefaultPort (const WaitressUrl_t * const url) {
assert (url != NULL);
- return url->port == NULL ? (url->tls ? "443" : "80") : url->port;
+ if (url->tls) {
+ return url->tlsPort == NULL ? "443" : url->tlsPort;
+ } else {
+ return url->port == NULL ? "80" : url->port;
+ }
}
/* get line from string
@@ -55,6 +55,7 @@ typedef struct {
const char *password;
const char *host;
const char *port;
+ const char *tlsPort;
const char *path; /* without leading '/' */
} WaitressUrl_t;
View
@@ -31,6 +31,7 @@ THE SOFTWARE.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+/* fork () */
#include <unistd.h>
#include <sys/select.h>
#include <time.h>
@@ -46,6 +47,10 @@ THE SOFTWARE.
#include <stdbool.h>
#include <limits.h>
#include <signal.h>
+/* waitpid () */
+#include <sys/types.h>
+#include <sys/wait.h>
+
/* pandora.com library */
#include <piano.h>
@@ -93,22 +98,78 @@ static bool BarMainLoginUser (BarApp_t *app) {
/* ask for username/password if none were provided in settings
*/
-static void BarMainGetLoginCredentials (BarSettings_t *settings,
+static bool BarMainGetLoginCredentials (BarSettings_t *settings,
BarReadlineFds_t *input) {
if (settings->username == NULL) {
char nameBuf[100];
+
BarUiMsg (settings, MSG_QUESTION, "Email: ");
BarReadlineStr (nameBuf, sizeof (nameBuf), input, BAR_RL_DEFAULT);
settings->username = strdup (nameBuf);
}
+
if (settings->password == NULL) {
char passBuf[100];
- BarUiMsg (settings, MSG_QUESTION, "Password: ");
- BarReadlineStr (passBuf, sizeof (passBuf), input, BAR_RL_NOECHO);
- /* write missing newline */
- puts ("");
- settings->password = strdup (passBuf);
+
+ if (settings->passwordCmd == NULL) {
+ BarUiMsg (settings, MSG_QUESTION, "Password: ");
+ BarReadlineStr (passBuf, sizeof (passBuf), input, 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));
+ status = 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 true;
}
/* get station list
@@ -278,7 +339,9 @@ static void BarMainPrintTime (BarApp_t *app) {
static void BarMainLoop (BarApp_t *app) {
pthread_t playerThread;
- BarMainGetLoginCredentials (&app->settings, &app->input);
+ if (!BarMainGetLoginCredentials (&app->settings, &app->input)) {
+ return;
+ }
BarMainLoadProxy (&app->settings, &app->waith);
@@ -309,6 +372,7 @@ static void BarMainLoop (BarApp_t *app) {
if (app->playlist != NULL) {
PianoSong_t *histsong = app->playlist;
app->playlist = app->playlist->next;
+ histsong->next = NULL;
BarUiHistoryPrepend (app, histsong);
}
if (app->playlist == NULL) {
@@ -374,6 +438,7 @@ int main (int argc, char **argv) {
WaitressInit (&app.waith);
app.waith.url.host = app.settings.rpcHost;
+ app.waith.url.tlsPort = app.settings.rpcTlsPort;
app.waith.tlsFingerprint = app.settings.tlsFingerprint;
/* init fds */
@@ -417,6 +482,9 @@ int main (int argc, char **argv) {
close (app.input.fds[1]);
}
+ /* write statefile */
+ BarSettingsWrite (app.curStation, &app.settings);
+
BarFlyClose (&app.player.fly, &app.settings);
BarFlyFinalize ();
PianoDestroy (&app.ph);
View
@@ -28,6 +28,7 @@ THE SOFTWARE.
#include <math.h>
#include <stdint.h>
#include <limits.h>
+#include <assert.h>
#include <arpa/inet.h>
#include "player.h"
@@ -143,17 +144,31 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size,
NeAACDecFrameInfo frameInfo;
size_t i;
- while ((player->bufferFilled - player->bufferRead) >
- player->sampleSize[player->sampleSizeCurr]) {
+ while (player->sampleSizeCurr < player->sampleSizeN &&
+ (player->bufferFilled - player->bufferRead) >=
+ player->sampleSize[player->sampleSizeCurr]) {
+ /* going through this loop can take up to a few seconds =>
+ * allow earlier thread abort */
+ QUIT_PAUSE_CHECK;
+
/* decode frame */
aacDecoded = NeAACDecDecode(player->aacHandle, &frameInfo,
- player->buffer + player->bufferRead,
+ &player->buffer[player->bufferRead],
player->sampleSize[player->sampleSizeCurr]);
+ player->bufferRead += player->sampleSize[player->sampleSizeCurr];
+ ++player->sampleSizeCurr;
+
if (frameInfo.error != 0) {
+ /* skip this frame, songPlayed will be slightly off if this
+ * happens */
BarUiMsg (player->settings, MSG_ERR, "Decoding error: %s\n",
NeAACDecGetErrorMessage (frameInfo.error));
- break;
+ continue;
}
+ /* assuming data in stsz atom is correct */
+ assert (frameInfo.bytesconsumed ==
+ player->sampleSize[player->sampleSizeCurr-1]);
+
for (i = 0; i < frameInfo.samples; i++) {
aacDecoded[i] = applyReplayGain (aacDecoded[i], player->scale);
}
@@ -165,11 +180,10 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size,
(unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR /
(unsigned long long int) player->samplerate /
(unsigned long long int) player->channels;
- player->bufferRead += frameInfo.bytesconsumed;
- player->sampleSizeCurr++;
- /* going through this loop can take up to a few seconds =>
- * allow earlier thread abort */
- QUIT_PAUSE_CHECK;
+ }
+ if (player->sampleSizeCurr >= player->sampleSizeN) {
+ /* no more frames, drop data */
+ player->bufferRead = player->bufferFilled;
}
} else {
if (player->mode == PLAYER_INITIALIZED) {
@@ -243,12 +257,15 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size,
/* how many frames do we have? */
if (player->sampleSizeN == 0) {
/* mp4 uses big endian, convert */
+ memcpy (&player->sampleSizeN, player->buffer +
+ player->bufferRead, sizeof (uint32_t));
player->sampleSizeN =
- bigToHostEndian32 (*((uint32_t *) (player->buffer +
- player->bufferRead)));
+ bigToHostEndian32 (player->sampleSizeN);
+
player->sampleSize = malloc (player->sampleSizeN *
sizeof (*player->sampleSize));
- player->bufferRead += 4;
+ assert (player->sampleSize != NULL);
+ player->bufferRead += sizeof (uint32_t);
player->sampleSizeCurr = 0;
/* set up song duration (assuming one frame always contains
* the same number of samples)
@@ -261,11 +278,15 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size,
(unsigned long long int) player->channels;
break;
} else {
+ memcpy (&player->sampleSize[player->sampleSizeCurr],
+ player->buffer + player->bufferRead,
+ sizeof (uint32_t));
player->sampleSize[player->sampleSizeCurr] =
- bigToHostEndian32 (*((uint32_t *) (player->buffer +
- player->bufferRead)));
+ bigToHostEndian32 (
+ player->sampleSize[player->sampleSizeCurr]);
+
player->sampleSizeCurr++;
- player->bufferRead += 4;
+ player->bufferRead += sizeof (uint32_t);
}
/* all sizes read, nearly ready for data mode */
if (player->sampleSizeCurr >= player->sampleSizeN) {
Oops, something went wrong.

0 comments on commit dfe00a4

Please sign in to comment.