Esempio n. 1
0
/*	read app settings from file; format is: key = value\n
 *	@param where to save these settings
 *	@return nothing yet
 */
void BarSettingsRead (BarSettings_t *settings) {
	char * const configfiles[] = { PACKAGE_STATE, PACKAGE_CONFIG };
	char * const userhome = BarSettingsGetHome ();
	assert (userhome != NULL);
	/* set xdg config path (if not set) */
	char * const defaultxdg = malloc (strlen ("XDG_CONFIG_HOME=") + strlen (userhome) + 1);
	sprintf (defaultxdg, "XDG_CONFIG_HOME=%s", userhome);
	_putenv (defaultxdg);
	free (defaultxdg);

	assert (sizeof (settings->keys) / sizeof (*settings->keys) ==
			sizeof (dispatchActions) / sizeof (*dispatchActions));

	/* apply defaults */
	settings->audioQuality = PIANO_AQ_HIGH;
	settings->autoselect = true;
	settings->history = 5;
	settings->volume = 0;
	settings->timeout = 30; /* seconds */
	settings->gainMul = 1.0;
	/* should be > 4, otherwise expired audio urls (403) can stop playback */
	settings->maxRetry = 5;
	settings->sortOrder = BAR_SORT_NAME_AZ;
	settings->loveIcon = strdup (" <3");
	settings->banIcon = strdup (" </3");
	settings->tiredIcon = strdup (" zZ");
	settings->atIcon = strdup (" @ ");
	settings->npSongFormat = strdup ("\"%t\" by \"%a\" on \"%l\"%r%@%s");
	settings->npStationFormat = strdup ("Station \"%n\" (%i)");
	settings->listSongFormat = strdup ("%i) %a - %t%r");
	settings->titleFormat = strdup (TITLE " - \"%t\" by \"%a\" on \"%l\"%r%@%s");
	settings->player = NULL;
	settings->rpcHost = strdup (PIANO_RPC_HOST);
	settings->rpcTlsPort = strdup ("443");
	settings->partnerUser = strdup ("android");
	settings->partnerPassword = strdup ("AC7IBG09A3DTSYM4R41UJWL07VLN8JI7");
	settings->device = strdup ("android-generic");
	settings->inkey = strdup ("R=U!LH$O2B#");
	settings->outkey = strdup ("6#26FRL$ZWD");
	settings->fifo = BarGetXdgConfigDir (PACKAGE_PIPE);
	assert (settings->fifo != NULL);

	settings->msgFormat[MSG_NONE].prefix = NULL;
	settings->msgFormat[MSG_NONE].postfix = NULL;
	settings->msgFormat[MSG_INFO].prefix = strdup ("(i) ");
	settings->msgFormat[MSG_INFO].postfix = NULL;
	settings->msgFormat[MSG_PLAYING].prefix = strdup ("|>  ");
	settings->msgFormat[MSG_PLAYING].postfix = NULL;
	settings->msgFormat[MSG_TIME].prefix = strdup ("#   ");
	settings->msgFormat[MSG_TIME].postfix = NULL;
	settings->msgFormat[MSG_ERR].prefix = strdup ("/!\\ ");
	settings->msgFormat[MSG_ERR].postfix = NULL;
	settings->msgFormat[MSG_QUESTION].prefix = strdup ("[?] ");
	settings->msgFormat[MSG_QUESTION].postfix = NULL;
	settings->msgFormat[MSG_LIST].prefix = strdup ("\t");
	settings->msgFormat[MSG_LIST].postfix = NULL;
	settings->msgFormat[MSG_DEBUG].prefix = NULL;
	settings->msgFormat[MSG_DEBUG].postfix = NULL;

	for (size_t i = 0; i < BAR_KS_COUNT; i++) {
		settings->keys[i] = dispatchActions[i].defaultKey;
	}

	/* read config files */
	for (size_t j = 0; j < sizeof (configfiles) / sizeof (*configfiles); j++) {
		static const char *formatMsgPrefix = "format_msg_";
		FILE *configfd;
		char line[512];
		size_t lineNum = 0;

		char * const path = BarGetXdgConfigDir (configfiles[j]);
		assert (path != NULL);
		if ((configfd = fopen (path, "r")) == NULL) {
			free (path);
			continue;
		}

		while (1) {
			++lineNum;
			char * const ret = fgets (line, sizeof (line), configfd);
			if (ret == NULL) {
				/* EOF or error */
				break;
			}
			if (strchr (line, '\n') == NULL && !feof (configfd)) {
				BarUiMsg (settings, MSG_INFO, "Line %s:%zu too long, "
						"ignoring\n", path, lineNum);
				continue;
			}
			/* parse lines that match "^\s*(.*?)\s?=\s?(.*)$". Windows and Unix
			 * line terminators are supported. */
			char *key = line;

			/* skip leading spaces */
			while (isspace ((unsigned char) key[0])) {
				++key;
			}

			/* skip comments */
			if (key[0] == '#') {
				continue;
			}

			/* search for delimiter and split key-value pair */
			char *val = strchr (line, '=');
			if (val == NULL) {
				/* no warning for empty lines */
				if (key[0] != '\0') {
					BarUiMsg (settings, MSG_INFO,
							"Invalid line at %s:%zu\n", path, lineNum);
				}
				/* invalid line */
				continue;
			}
			*val = '\0';
			++val;

			/* drop spaces at the end */
			char *keyend = &key[strlen (key)-1];
			while (keyend >= key && isspace ((unsigned char) *keyend)) {
				*keyend = '\0';
				--keyend;
			}

			/* strip at most one space, legacy cruft, required for values with
			 * leading spaces like love_icon */
			if (isspace ((unsigned char) val[0])) {
				++val;
			}
			/* drop trailing cr/lf */
			char *valend = &val[strlen (val)-1];
			while (valend >= val && (*valend == '\r' || *valend == '\n')) {
				*valend = '\0';
				--valend;
			}

			if (streq ("control_proxy", key)) {
				settings->controlProxy = strdup (val);
			} else if (streq ("proxy", key)) {
				settings->proxy = strdup (val);
			} else if (streq ("bind_to", key)) {
				settings->bindTo = 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 (streq ("ca_bundle", key)) {
				free (settings->caBundle);
				settings->caBundle = 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;
					}
				}
			} 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)) {
				free (settings->autostartStation);
				settings->autostartStation = strdup (val);
			} else if (streq ("event_command", key)) {
				settings->eventCmd = BarSettingsExpandTilde (val, userhome);
			} else if (streq ("history", key)) {
				settings->history = atoi (val);
			} else if (streq ("max_retry", key)) {
				settings->maxRetry = atoi (val);
			} else if (streq ("timeout", key)) {
				settings->timeout = atoi (val);
			} 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 ("tired_icon", key)) {
				free (settings->tiredIcon);
				settings->tiredIcon = 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 ("gain_mul", key)) {
				settings->gainMul = (float)atof (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 ("format_title", key)) {
				free (settings->titleFormat);
				settings->titleFormat = strdup (val);
			} else if (streq ("player", key)) {
				free (settings->player);
				settings->player = strdup (val);
			} else if (streq ("fifo", key)) {
				free (settings->fifo);
				settings->fifo = BarSettingsExpandTilde (val, userhome);
			} else if (streq ("autoselect", key)) {
				settings->autoselect = atoi (val);
			} else if (strncmp (formatMsgPrefix, key,
					strlen (formatMsgPrefix)) == 0) {
				static const char *mapping[] = {"none", "info", "nowplaying",
						"time", "err", "question", "list", "debug"};
				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;
					}
				}
			}
		}

		fclose (configfd);
		free (path);
	}

	/* check environment variable if proxy is not set explicitly */
	if (settings->proxy == NULL) {
		char *tmpProxy = getenv ("http_proxy");
		if (tmpProxy != NULL && strlen (tmpProxy) > 0) {
			settings->proxy = strdup (tmpProxy);
		}
	}

	free (userhome);
}
Esempio n. 2
0
/*	read app settings from file; format is: key = value\n
 *	@param where to save these settings
 *	@return nothing yet
 */
void BarSettingsRead (BarSettings_t *settings) {
	char * const configfiles[] = { PACKAGE_STATE, PACKAGE_CONFIG };
	char * const userhome = BarSettingsGetHome ();
	assert (userhome != NULL);
	/* set xdg config path (if not set) */
	char * const defaultxdg = malloc (strlen ("XDG_CONFIG_HOME=") + strlen (userhome) + 1);
	sprintf (defaultxdg, "XDG_CONFIG_HOME=%s", userhome);
	_putenv (defaultxdg);
	free (defaultxdg);

	assert (sizeof (settings->keys) / sizeof (*settings->keys) ==
			sizeof (dispatchActions) / sizeof (*dispatchActions));

	/* apply defaults */
	settings->audioQuality = PIANO_AQ_HIGH;
	settings->autoselect = true;
	settings->history = 5;
	settings->volume = 0;
	settings->maxPlayerErrors = 5;
	settings->sortOrder = BAR_SORT_NAME_AZ;
	settings->loveIcon = strdup (" <3");
	settings->banIcon = strdup (" </3");
	settings->atIcon = strdup (" @ ");
	settings->npSongFormat = strdup ("\"%t\" by \"%a\" on \"%l\"%r%@%s");
	settings->npStationFormat = strdup ("Station \"%n\" (%i)");
	settings->listSongFormat = strdup ("%i) %a - %t%r");
	settings->titleFormat = strdup (TITLE " - \"%t\" by \"%a\" on \"%l\"%r%@%s");
	settings->player = NULL;
	settings->rpcHost = strdup (PIANO_RPC_HOST);
	settings->rpcTlsPort = NULL;
	settings->partnerUser = strdup ("android");
	settings->partnerPassword = strdup ("AC7IBG09A3DTSYM4R41UJWL07VLN8JI7");
	settings->device = strdup ("android-generic");
	settings->inkey = strdup ("R=U!LH$O2B#");
	settings->outkey = strdup ("6#26FRL$ZWD");
	settings->fifo = BarGetXdgConfigDir (PACKAGE_PIPE);
	assert (settings->fifo != NULL);

	settings->msgFormat[MSG_NONE].prefix = NULL;
	settings->msgFormat[MSG_NONE].postfix = NULL;
	settings->msgFormat[MSG_INFO].prefix = strdup ("(i) ");
	settings->msgFormat[MSG_INFO].postfix = NULL;
	settings->msgFormat[MSG_PLAYING].prefix = strdup ("|>  ");
	settings->msgFormat[MSG_PLAYING].postfix = NULL;
	settings->msgFormat[MSG_TIME].prefix = strdup ("#   ");
	settings->msgFormat[MSG_TIME].postfix = NULL;
	settings->msgFormat[MSG_ERR].prefix = strdup ("/!\\ ");
	settings->msgFormat[MSG_ERR].postfix = NULL;
	settings->msgFormat[MSG_QUESTION].prefix = strdup ("[?] ");
	settings->msgFormat[MSG_QUESTION].postfix = NULL;
	settings->msgFormat[MSG_LIST].prefix = strdup ("\t");
	settings->msgFormat[MSG_LIST].postfix = NULL;
	settings->msgFormat[MSG_DEBUG].prefix = NULL;
	settings->msgFormat[MSG_DEBUG].postfix = NULL;

	for (size_t i = 0; i < BAR_KS_COUNT; i++) {
		settings->keys[i] = dispatchActions[i].defaultKey;
	}

	/* 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];
		FILE *configfd;

		char * const path = BarGetXdgConfigDir (configfiles[j]);
		assert (path != NULL);
		if ((configfd = fopen (path, "r")) == NULL) {
			free (path);
			continue;
		}

		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 (streq ("ca_bundle", key)) {
				free (settings->caBundle);
				settings->caBundle = 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;
					}
				}
			} 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)) {
				free (settings->autostartStation);
				settings->autostartStation = strdup (val);
			} else if (streq ("event_command", key)) {
				settings->eventCmd = BarSettingsExpandTilde (val, userhome);
			} else if (streq ("history", key)) {
				settings->history = atoi (val);
			} else if (streq ("max_player_errors", key)) {
				settings->maxPlayerErrors = atoi (val);
			} 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 ("format_title", key)) {
				free (settings->titleFormat);
				settings->titleFormat = strdup (val);
			} else if (streq ("player", key)) {
				free (settings->player);
				settings->player = strdup (val);
			} else if (streq ("fifo", key)) {
				free (settings->fifo);
				settings->fifo = BarSettingsExpandTilde (val, userhome);
			} else if (streq ("autoselect", key)) {
				settings->autoselect = atoi (val);
			} else if (strncmp (formatMsgPrefix, key,
					strlen (formatMsgPrefix)) == 0) {
				static const char *mapping[] = {"none", "info", "nowplaying",
						"time", "err", "question", "list", "debug"};
				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;
					}
				}
			}
		}

		fclose (configfd);
		free (path);
	}

	/* check environment variable if proxy is not set explicitly */
	if (settings->proxy == NULL) {
		char *tmpProxy = getenv ("http_proxy");
		if (tmpProxy != NULL && strlen (tmpProxy) > 0) {
			settings->proxy = strdup (tmpProxy);
		}
	}

	free (userhome);
}