Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge with pianobar-2012.09.07.

  • Loading branch information...
commit dfe00a4701882e05df4482fc97476b37713f6741 1 parent d0126f7
Joshua V. Dillon authored
View
9 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,
View
2  contrib/config-example
@@ -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
20 contrib/pianobarfly.1
@@ -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,14 +328,23 @@ 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
sorts by name from a to z, quickmix_01_name_za by type (quickmix at the
@@ -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
2  src/config.h
@@ -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
2  src/libpiano/crypt.c
@@ -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;
}
View
7 src/libwaitress/waitress.c
@@ -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
View
1  src/libwaitress/waitress.h
@@ -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
82 src/main.c
@@ -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
51 src/player.c
@@ -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) {
View
350 src/settings.c
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2008-2011
+Copyright (c) 2008-2012
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -89,6 +89,7 @@ void BarSettingsDestroy (BarSettings_t *settings) {
free (settings->proxy);
free (settings->username);
free (settings->password);
+ free (settings->passwordCmd);
free (settings->autostartStation);
free (settings->eventCmd);
free (settings->loveIcon);
@@ -101,6 +102,7 @@ void BarSettingsDestroy (BarSettings_t *settings) {
free (settings->listSongFormat);
free (settings->fifo);
free (settings->rpcHost);
+ free (settings->rpcTlsPort);
free (settings->partnerUser);
free (settings->partnerPassword);
free (settings->device);
@@ -118,9 +120,7 @@ void BarSettingsDestroy (BarSettings_t *settings) {
* @return nothing yet
*/
void BarSettingsRead (BarSettings_t *settings) {
- char configfile[PATH_MAX], key[256], val[256];
- FILE *configfd;
- static const char *formatMsgPrefix = "format_msg_";
+ char *configfiles[] = {PACKAGE "/state", PACKAGE "/config"};
assert (sizeof (settings->keys) / sizeof (*settings->keys) ==
sizeof (dispatchActions) / sizeof (*dispatchActions));
@@ -138,6 +138,7 @@ void BarSettingsRead (BarSettings_t *settings) {
settings->npStationFormat = strdup ("Station \"%n\" (%i)");
settings->listSongFormat = strdup ("%i) %a - %t%r");
settings->rpcHost = strdup (PIANO_RPC_HOST);
+ settings->rpcTlsPort = NULL;
settings->partnerUser = strdup ("android");
settings->partnerPassword = strdup ("AC7IBG09A3DTSYM4R41UJWL07VLN8JI7");
settings->device = strdup ("android-generic");
@@ -172,169 +173,183 @@ void BarSettingsRead (BarSettings_t *settings) {
settings->keys[i] = dispatchActions[i].defaultKey;
}
- BarGetXdgConfigDir (PACKAGE "/config", configfile, sizeof (configfile));
- if ((configfd = fopen (configfile, "r")) == NULL) {
- return;
- }
+ /* read config files */
+ for (size_t j = 0; j < sizeof (configfiles) / sizeof (*configfiles); j++) {
+ static const char *formatMsgPrefix = "format_msg_";
+ char key[256], val[256], path[PATH_MAX];
+ FILE *configfd;
- /* read config file */
- while (1) {
- char lwhite, rwhite;
- int scanRet = fscanf (configfd, "%255s%c=%c%255[^\n]", key, &lwhite, &rwhite, val);
- if (scanRet == EOF) {
- break;
- } else if (scanRet != 4 || lwhite != ' ' || rwhite != ' ') {
- /* invalid config line */
+ BarGetXdgConfigDir (configfiles[j], path, sizeof (path));
+ if ((configfd = fopen (path, "r")) == NULL) {
continue;
}
- if (streq ("control_proxy", key)) {
- settings->controlProxy = strdup (val);
- } else if (streq ("proxy", key)) {
- settings->proxy = strdup (val);
- } else if (streq ("user", key)) {
- settings->username = strdup (val);
- } else if (streq ("password", key)) {
- settings->password = strdup (val);
- } else if (streq ("rpc_host", key)) {
- free (settings->rpcHost);
- settings->rpcHost = strdup (val);
- } else if (streq ("partner_user", key)) {
- free (settings->partnerUser);
- settings->partnerUser = strdup (val);
- } else if (streq ("partner_password", key)) {
- free (settings->partnerPassword);
- settings->partnerPassword = strdup (val);
- } else if (streq ("device", key)) {
- free (settings->device);
- settings->device = strdup (val);
- } else if (streq ("encrypt_password", key)) {
- free (settings->outkey);
- settings->outkey = strdup (val);
- } else if (streq ("decrypt_password", key)) {
- free (settings->inkey);
- settings->inkey = strdup (val);
- } else if (memcmp ("act_", key, 4) == 0) {
- size_t i;
- /* keyboard shortcuts */
- for (i = 0; i < BAR_KS_COUNT; i++) {
- if (streq (dispatchActions[i].configKey, key)) {
- if (streq (val, "disabled")) {
- settings->keys[i] = BAR_KS_DISABLED;
- } else {
- settings->keys[i] = val[0];
+
+ while (1) {
+ char lwhite, rwhite;
+ int scanRet = fscanf (configfd, "%255s%c=%c%255[^\n]", key, &lwhite, &rwhite, val);
+ if (scanRet == EOF) {
+ break;
+ } else if (scanRet != 4 || lwhite != ' ' || rwhite != ' ') {
+ /* invalid config line */
+ continue;
+ }
+ if (streq ("control_proxy", key)) {
+ settings->controlProxy = strdup (val);
+ } else if (streq ("proxy", key)) {
+ settings->proxy = strdup (val);
+ } else if (streq ("user", key)) {
+ settings->username = strdup (val);
+ } else if (streq ("password", key)) {
+ settings->password = strdup (val);
+ } else if (streq ("password_command", key)) {
+ settings->passwordCmd = strdup (val);
+ } else if (streq ("rpc_host", key)) {
+ free (settings->rpcHost);
+ settings->rpcHost = strdup (val);
+ } else if (streq ("rpc_tls_port", key)) {
+ free (settings->rpcTlsPort);
+ settings->rpcTlsPort = strdup (val);
+ } else if (streq ("partner_user", key)) {
+ free (settings->partnerUser);
+ settings->partnerUser = strdup (val);
+ } else if (streq ("partner_password", key)) {
+ free (settings->partnerPassword);
+ settings->partnerPassword = strdup (val);
+ } else if (streq ("device", key)) {
+ free (settings->device);
+ settings->device = strdup (val);
+ } else if (streq ("encrypt_password", key)) {
+ free (settings->outkey);
+ settings->outkey = strdup (val);
+ } else if (streq ("decrypt_password", key)) {
+ free (settings->inkey);
+ settings->inkey = strdup (val);
+ } else if (memcmp ("act_", key, 4) == 0) {
+ size_t i;
+ /* keyboard shortcuts */
+ for (i = 0; i < BAR_KS_COUNT; i++) {
+ if (streq (dispatchActions[i].configKey, key)) {
+ if (streq (val, "disabled")) {
+ settings->keys[i] = BAR_KS_DISABLED;
+ } else {
+ settings->keys[i] = val[0];
+ }
+ break;
}
- break;
}
- }
- } else if (streq ("audio_quality", key)) {
- if (streq (val, "low")) {
- settings->audioQuality = PIANO_AQ_LOW;
- } else if (streq (val, "medium")) {
- settings->audioQuality = PIANO_AQ_MEDIUM;
- } else if (streq (val, "high")) {
- settings->audioQuality = PIANO_AQ_HIGH;
- }
- } else if (streq ("autostart_station", key)) {
- settings->autostartStation = strdup (val);
- } else if (streq ("event_command", key)) {
- settings->eventCmd = strdup (val);
- } else if (streq ("history", key)) {
- settings->history = atoi (val);
- } else if (streq ("audio_file_dir", key)) {
- free (settings->audioFileDir);
- settings->audioFileDir = strdup(val);
- } else if (streq ("audio_file_name", key)) {
- free (settings->audioFileName);
- settings->audioFileName = strdup(val);
- } else if (streq ("use_spaces", key)) {
- if (streq ("true", val)) {
- settings->useSpaces = true;
- }
- } else if (streq ("embed_cover", key)) {
- if (!streq ("true", val)) {
- settings->embedCover = false;
- }
- } else if (streq ("sort", key)) {
- size_t i;
- static const char *mapping[] = {"name_az",
- "name_za",
- "quickmix_01_name_az",
- "quickmix_01_name_za",
- "quickmix_10_name_az",
- "quickmix_10_name_za",
- };
- for (i = 0; i < BAR_SORT_COUNT; i++) {
- if (streq (mapping[i], val)) {
- settings->sortOrder = i;
- break;
+ } else if (streq ("audio_quality", key)) {
+ if (streq (val, "low")) {
+ settings->audioQuality = PIANO_AQ_LOW;
+ } else if (streq (val, "medium")) {
+ settings->audioQuality = PIANO_AQ_MEDIUM;
+ } else if (streq (val, "high")) {
+ settings->audioQuality = PIANO_AQ_HIGH;
}
- }
- } else if (streq ("love_icon", key)) {
- free (settings->loveIcon);
- settings->loveIcon = strdup (val);
- } else if (streq ("ban_icon", key)) {
- free (settings->banIcon);
- settings->banIcon = strdup (val);
- } else if (streq ("at_icon", key)) {
- free (settings->atIcon);
- settings->atIcon = strdup (val);
- } else if (streq ("volume", key)) {
- settings->volume = atoi (val);
- } else if (streq ("format_nowplaying_song", key)) {
- free (settings->npSongFormat);
- settings->npSongFormat = strdup (val);
- } else if (streq ("format_nowplaying_station", key)) {
- free (settings->npStationFormat);
- settings->npStationFormat = strdup (val);
- } else if (streq ("format_list_song", key)) {
- free (settings->listSongFormat);
- settings->listSongFormat = strdup (val);
- } else if (streq ("fifo", key)) {
- free (settings->fifo);
- settings->fifo = strdup (val);
- } else if (streq ("autoselect", key)) {
- settings->autoselect = atoi (val);
- } else if (streq ("tls_fingerprint", key)) {
- /* expects 40 byte hex-encoded sha1 */
- if (strlen (val) == 40) {
- for (size_t i = 0; i < 20; i++) {
- char hex[3];
- memcpy (hex, &val[i*2], 2);
- hex[2] = '\0';
- settings->tlsFingerprint[i] = strtol (hex, NULL, 16);
+ } else if (streq ("autostart_station", key)) {
+ free (settings->autostartStation);
+ settings->autostartStation = strdup (val);
+ } else if (streq ("event_command", key)) {
+ settings->eventCmd = strdup (val);
+ } else if (streq ("history", key)) {
+ settings->history = atoi (val);
+ } else if (streq ("audio_file_dir", key)) {
+ free (settings->audioFileDir);
+ settings->audioFileDir = strdup(val);
+ } else if (streq ("audio_file_name", key)) {
+ free (settings->audioFileName);
+ settings->audioFileName = strdup(val);
+ } else if (streq ("use_spaces", key)) {
+ if (streq ("true", val)) {
+ settings->useSpaces = true;
}
- }
- } else if (strncmp (formatMsgPrefix, key,
- strlen (formatMsgPrefix)) == 0) {
- static const char *mapping[] = {"none", "info", "nowplaying",
- "time", "err", "question", "list"};
- const char *typeStart = key + strlen (formatMsgPrefix);
- for (size_t i = 0; i < sizeof (mapping) / sizeof (*mapping); i++) {
- if (streq (typeStart, mapping[i])) {
- const char *formatPos = strstr (val, "%s");
-
- /* keep default if there is no format character */
- if (formatPos != NULL) {
- BarMsgFormatStr_t *format = &settings->msgFormat[i];
-
- free (format->prefix);
- free (format->postfix);
-
- const size_t prefixLen = formatPos - val;
- format->prefix = calloc (prefixLen + 1,
- sizeof (*format->prefix));
- memcpy (format->prefix, val, prefixLen);
-
- const size_t postfixLen = strlen (val) -
- (formatPos-val) - 2;
- format->postfix = calloc (postfixLen + 1,
- sizeof (*format->postfix));
- memcpy (format->postfix, formatPos+2, postfixLen);
+ } else if (streq ("embed_cover", key)) {
+ if (!streq ("true", val)) {
+ settings->embedCover = false;
+ }
+ } else if (streq ("sort", key)) {
+ size_t i;
+ static const char *mapping[] = {"name_az",
+ "name_za",
+ "quickmix_01_name_az",
+ "quickmix_01_name_za",
+ "quickmix_10_name_az",
+ "quickmix_10_name_za",
+ };
+ for (i = 0; i < BAR_SORT_COUNT; i++) {
+ if (streq (mapping[i], val)) {
+ settings->sortOrder = i;
+ break;
+ }
+ }
+ } else if (streq ("love_icon", key)) {
+ free (settings->loveIcon);
+ settings->loveIcon = strdup (val);
+ } else if (streq ("ban_icon", key)) {
+ free (settings->banIcon);
+ settings->banIcon = strdup (val);
+ } else if (streq ("at_icon", key)) {
+ free (settings->atIcon);
+ settings->atIcon = strdup (val);
+ } else if (streq ("volume", key)) {
+ settings->volume = atoi (val);
+ } else if (streq ("format_nowplaying_song", key)) {
+ free (settings->npSongFormat);
+ settings->npSongFormat = strdup (val);
+ } else if (streq ("format_nowplaying_station", key)) {
+ free (settings->npStationFormat);
+ settings->npStationFormat = strdup (val);
+ } else if (streq ("format_list_song", key)) {
+ free (settings->listSongFormat);
+ settings->listSongFormat = strdup (val);
+ } else if (streq ("fifo", key)) {
+ free (settings->fifo);
+ settings->fifo = strdup (val);
+ } else if (streq ("autoselect", key)) {
+ settings->autoselect = atoi (val);
+ } else if (streq ("tls_fingerprint", key)) {
+ /* expects 40 byte hex-encoded sha1 */
+ if (strlen (val) == 40) {
+ for (size_t i = 0; i < 20; i++) {
+ char hex[3];
+ memcpy (hex, &val[i*2], 2);
+ hex[2] = '\0';
+ settings->tlsFingerprint[i] = strtol (hex, NULL, 16);
+ }
+ }
+ } else if (strncmp (formatMsgPrefix, key,
+ strlen (formatMsgPrefix)) == 0) {
+ static const char *mapping[] = {"none", "info", "nowplaying",
+ "time", "err", "question", "list"};
+ const char *typeStart = key + strlen (formatMsgPrefix);
+ for (size_t i = 0; i < sizeof (mapping) / sizeof (*mapping); i++) {
+ if (streq (typeStart, mapping[i])) {
+ const char *formatPos = strstr (val, "%s");
+
+ /* keep default if there is no format character */
+ if (formatPos != NULL) {
+ BarMsgFormatStr_t *format = &settings->msgFormat[i];
+
+ free (format->prefix);
+ free (format->postfix);
+
+ const size_t prefixLen = formatPos - val;
+ format->prefix = calloc (prefixLen + 1,
+ sizeof (*format->prefix));
+ memcpy (format->prefix, val, prefixLen);
+
+ const size_t postfixLen = strlen (val) -
+ (formatPos-val) - 2;
+ format->postfix = calloc (postfixLen + 1,
+ sizeof (*format->postfix));
+ memcpy (format->postfix, formatPos+2, postfixLen);
+ }
+ break;
}
- break;
}
}
}
+
+ fclose (configfd);
}
/* check environment variable if proxy is not set explicitly */
@@ -344,6 +359,27 @@ void BarSettingsRead (BarSettings_t *settings) {
settings->proxy = strdup (tmpProxy);
}
}
+}
+
+/* write statefile
+ */
+void BarSettingsWrite (PianoStation_t *station, BarSettings_t *settings) {
+ char path[PATH_MAX];
+ FILE *fd;
+
+ assert (settings != NULL);
+
+ BarGetXdgConfigDir (PACKAGE "/state", path, sizeof (path));
+ if ((fd = fopen (path, "w")) == NULL) {
+ return;
+ }
- fclose (configfd);
+ fputs ("# do not edit this file\n", fd);
+ fprintf (fd, "volume = %i\n", settings->volume);
+ if (station != NULL) {
+ fprintf (fd, "autostart_station = %s\n", station->id);
+ }
+
+ fclose (fd);
}
+
View
7 src/settings.h
@@ -91,7 +91,7 @@ typedef struct {
int useSpaces;
int embedCover;
char *username;
- char *password;
+ char *password, *passwordCmd;
char *controlProxy; /* non-american listeners need this */
char *proxy;
char *autostartStation;
@@ -103,15 +103,18 @@ typedef struct {
char *npStationFormat;
char *listSongFormat;
char *fifo;
- char *rpcHost, *partnerUser, *partnerPassword, *device, *inkey, *outkey;
+ char *rpcHost, *rpcTlsPort, *partnerUser, *partnerPassword, *device, *inkey, *outkey;
char tlsFingerprint[20];
char keys[BAR_KS_COUNT];
BarMsgFormatStr_t msgFormat[MSG_COUNT];
} BarSettings_t;
+#include <piano.h>
+
void BarSettingsInit (BarSettings_t *);
void BarSettingsDestroy (BarSettings_t *);
void BarSettingsRead (BarSettings_t *);
+void BarSettingsWrite (PianoStation_t *, BarSettings_t *);
void BarGetXdgConfigDir (const char *, char *, size_t);
#endif /* _SETTINGS_H */
View
2  src/ui.c
@@ -894,6 +894,8 @@ void BarUiHistoryPrepend (BarApp_t *app, PianoSong_t *song) {
PianoDestroyPlaylist (delSong);
}
}
+ } else {
+ PianoDestroyPlaylist (song);
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.