Skip to content
This repository has been archived by the owner on Aug 10, 2022. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge with pianobar-2012.09.07.
  • Loading branch information
Joshua V. Dillon committed Nov 18, 2012
1 parent d0126f7 commit dfe00a4
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 188 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
@@ -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,
Expand Down
2 changes: 2 additions & 0 deletions contrib/config-example
Expand Up @@ -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/
Expand Down
20 changes: 15 additions & 5 deletions contrib/pianobarfly.1
Expand Up @@ -115,6 +115,7 @@ Skip current song.

.TP
.B act_songpause = p
.TQ
.B act_songpause2 = <Space>
Pause/Continue

Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/config.h
Expand Up @@ -4,6 +4,6 @@
/* package name */
#define PACKAGE "pianobarfly"

#define VERSION "2012.06.24-dev"
#define VERSION "2012.09.07-dev"

#endif /* _CONFIG_H */
2 changes: 2 additions & 0 deletions src/libpiano/crypt.c
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
7 changes: 6 additions & 1 deletion src/libwaitress/waitress.c
Expand Up @@ -39,6 +39,7 @@ THE SOFTWARE.
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <stdint.h>

#include <gnutls/x509.h>

Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/libwaitress/waitress.h
Expand Up @@ -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;

Expand Down
82 changes: 75 additions & 7 deletions src/main.c
Expand Up @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
51 changes: 36 additions & 15 deletions src/player.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand Down

0 comments on commit dfe00a4

Please sign in to comment.