merge shank-rewrite-config changes
git-svn-id: https://svn.musicpd.org/mpd/trunk@2375 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
8f40569aee
commit
58dbe4bb5d
2
TODO
2
TODO
@ -1,5 +1,7 @@
|
|||||||
0.12
|
0.12
|
||||||
----
|
----
|
||||||
|
*) Fix id3v1 encoding
|
||||||
|
|
||||||
*) Abstract audio stuff into a plugin oriented thing
|
*) Abstract audio stuff into a plugin oriented thing
|
||||||
*) audio_ao & audio_oss & audio_shout
|
*) audio_ao & audio_oss & audio_shout
|
||||||
*) allow for sending to multiple audio devices
|
*) allow for sending to multiple audio devices
|
||||||
|
@ -71,28 +71,25 @@ error_file "~/.mpd/mpd.error"
|
|||||||
################## AUDIO OUTPUT ##########################
|
################## AUDIO OUTPUT ##########################
|
||||||
#
|
#
|
||||||
# libao (ao_driver) supports any of the following:
|
# libao (ao_driver) supports any of the following:
|
||||||
#
|
|
||||||
# * Null output (handy for testing without a sound device)
|
|
||||||
# * WAV files
|
|
||||||
# * AU files
|
|
||||||
# * OSS (Open Sound System, used on Linux and FreeBSD)
|
|
||||||
# * aRts
|
|
||||||
# * esd (ESounD or Enlighten Sound Daemon)
|
|
||||||
# * ALSA (Advanced Linux Sound Architecture)
|
|
||||||
# * AIX
|
|
||||||
# * Sun/NetBSD/OpenBSD
|
|
||||||
# * IRIX
|
|
||||||
# * NAS (Network Audio Server)
|
|
||||||
#
|
|
||||||
# Refer to libao documentation for more information
|
# Refer to libao documentation for more information
|
||||||
#
|
#
|
||||||
# OSS Audio Output
|
# OSS Audio Output
|
||||||
#ao_driver "oss"
|
#audio_output {
|
||||||
#ao_driver_options "dsp=/dev/dsp"
|
# type "ao"
|
||||||
|
# name "my OSS device"
|
||||||
|
# driver "oss"
|
||||||
|
# options "dsp=/dev/dsp"
|
||||||
|
# write_size "1024"
|
||||||
|
#}
|
||||||
#
|
#
|
||||||
# ALSA Audio Output
|
# ALSA Audio Output
|
||||||
#ao_driver "alsa09"
|
#audio_output {
|
||||||
#ao_driver_options "dev=hw:0,0"
|
# type "ao"
|
||||||
|
# name "my ALSA device"
|
||||||
|
# driver "alsa09"
|
||||||
|
# options "dev=hw:0,0"
|
||||||
|
# write_size "1024"
|
||||||
|
#}
|
||||||
#
|
#
|
||||||
# Set this if you have problems
|
# Set this if you have problems
|
||||||
# playing audio files.
|
# playing audio files.
|
||||||
@ -101,11 +98,24 @@ error_file "~/.mpd/mpd.error"
|
|||||||
#
|
#
|
||||||
#audio_output_format "44100:16:2"
|
#audio_output_format "44100:16:2"
|
||||||
#
|
#
|
||||||
# You should not need mess with
|
##########################################################
|
||||||
# this value unless you know
|
|
||||||
# what you're doing.
|
|
||||||
|
################# SHOUT STREAMING ########################
|
||||||
#
|
#
|
||||||
#audio_write_size "1024"
|
# Set this to allow mpd to stream its output to icecast2
|
||||||
|
# (i.e. mpd is a icecast2 source)
|
||||||
|
#
|
||||||
|
#audio_output {
|
||||||
|
# type "shout"
|
||||||
|
# name "my cool stream"
|
||||||
|
# host "hostname"
|
||||||
|
# port "8000"
|
||||||
|
# user "source"
|
||||||
|
# password "hackme"
|
||||||
|
# quality "5.0"
|
||||||
|
# format "44100:16:1"
|
||||||
|
#}
|
||||||
#
|
#
|
||||||
##########################################################
|
##########################################################
|
||||||
|
|
||||||
@ -179,20 +189,6 @@ error_file "~/.mpd/mpd.error"
|
|||||||
##########################################
|
##########################################
|
||||||
|
|
||||||
|
|
||||||
################ SHOUT OPTIONS #####################
|
|
||||||
#
|
|
||||||
#shout_host "host"
|
|
||||||
#shout_port "8000"
|
|
||||||
#shout_user "source"
|
|
||||||
#shout_password "hackme"
|
|
||||||
#shout_name "My MPD!"
|
|
||||||
#shout_mount "/mpd.ogg"
|
|
||||||
#shout_quality "0.5"
|
|
||||||
#shout_format "44100:16:1"
|
|
||||||
#
|
|
||||||
####################################################
|
|
||||||
|
|
||||||
|
|
||||||
################ MISCELLANEOUS OPTIONS ###################
|
################ MISCELLANEOUS OPTIONS ###################
|
||||||
#
|
#
|
||||||
# This setting exists as precaution against attacks.
|
# This setting exists as precaution against attacks.
|
||||||
|
107
src/audio.c
107
src/audio.c
@ -31,9 +31,6 @@ static AudioFormat audio_format;
|
|||||||
|
|
||||||
static AudioFormat * audio_configFormat = NULL;
|
static AudioFormat * audio_configFormat = NULL;
|
||||||
|
|
||||||
static AudioOutput * aoOutput = NULL;
|
|
||||||
static AudioOutput * shoutOutput = NULL;
|
|
||||||
|
|
||||||
void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
|
void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
|
||||||
if(!src) return;
|
if(!src) return;
|
||||||
|
|
||||||
@ -42,17 +39,34 @@ void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
|
|||||||
dest->channels = src->channels;
|
dest->channels = src->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AudioOutput ** audioOutputArray = NULL;
|
||||||
|
static int audioOutputArraySize = 0;
|
||||||
|
|
||||||
extern AudioOutputPlugin aoPlugin;
|
extern AudioOutputPlugin aoPlugin;
|
||||||
extern AudioOutputPlugin shoutPlugin;
|
extern AudioOutputPlugin shoutPlugin;
|
||||||
|
|
||||||
void initAudioDriver() {
|
void initAudioDriver() {
|
||||||
|
ConfigParam * param = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
initAudioOutputPlugins();
|
initAudioOutputPlugins();
|
||||||
loadAudioOutputPlugin(&aoPlugin);
|
loadAudioOutputPlugin(&aoPlugin);
|
||||||
loadAudioOutputPlugin(&shoutPlugin);
|
loadAudioOutputPlugin(&shoutPlugin);
|
||||||
|
|
||||||
aoOutput = newAudioOutput("ao");
|
while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) {
|
||||||
assert(aoOutput);
|
i = audioOutputArraySize++;
|
||||||
shoutOutput = newAudioOutput("shout");
|
|
||||||
|
audioOutputArray = realloc(audioOutputArray,
|
||||||
|
audioOutputArraySize*sizeof(AudioOutput *));
|
||||||
|
|
||||||
|
audioOutputArray[i] = newAudioOutput(param);
|
||||||
|
|
||||||
|
if(!audioOutputArray[i]) {
|
||||||
|
ERROR("problems configuring output device defined at "
|
||||||
|
"line %i\n", param->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void getOutputAudioFormat(AudioFormat * inAudioFormat,
|
void getOutputAudioFormat(AudioFormat * inAudioFormat,
|
||||||
@ -65,13 +79,17 @@ void getOutputAudioFormat(AudioFormat * inAudioFormat,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initAudioConfig() {
|
void initAudioConfig() {
|
||||||
char * conf = getConf()[CONF_AUDIO_OUTPUT_FORMAT];
|
ConfigParam * param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT);
|
||||||
|
|
||||||
if(NULL == conf) return;
|
if(NULL == param || NULL == param->value) return;
|
||||||
|
|
||||||
audio_configFormat = malloc(sizeof(AudioFormat));
|
audio_configFormat = malloc(sizeof(AudioFormat));
|
||||||
|
|
||||||
if(0 != parseAudioConfig(audio_configFormat, conf)) exit(EXIT_FAILURE);
|
if(0 != parseAudioConfig(audio_configFormat, param->value)) {
|
||||||
|
ERROR("error parsing \"%s\" at line %i\n",
|
||||||
|
CONF_AUDIO_OUTPUT_FORMAT, param->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
|
int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
|
||||||
@ -145,10 +163,15 @@ void finishAudioConfig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void finishAudioDriver() {
|
void finishAudioDriver() {
|
||||||
finishAudioOutput(aoOutput);
|
int i;
|
||||||
if(shoutOutput) finishAudioOutput(shoutOutput);
|
|
||||||
shoutOutput = NULL;
|
for(i = 0; i < audioOutputArraySize; i++) {
|
||||||
aoOutput = NULL;
|
finishAudioOutput(audioOutputArray[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(audioOutputArray);
|
||||||
|
audioOutputArray = NULL;
|
||||||
|
audioOutputArraySize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int isCurrentAudioFormat(AudioFormat * audioFormat) {
|
int isCurrentAudioFormat(AudioFormat * audioFormat) {
|
||||||
@ -160,29 +183,65 @@ int isCurrentAudioFormat(AudioFormat * audioFormat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int openAudioDevice(AudioFormat * audioFormat) {
|
int openAudioDevice(AudioFormat * audioFormat) {
|
||||||
if(!aoOutput->open || !isCurrentAudioFormat(audioFormat)) {
|
int isCurrentFormat = isCurrentAudioFormat(audioFormat);
|
||||||
if(audioFormat) copyAudioFormat(&audio_format, audioFormat);
|
int ret = -1;
|
||||||
if(shoutOutput) openAudioOutput(shoutOutput, &audio_format);
|
int i;
|
||||||
return openAudioOutput(aoOutput, &audio_format);
|
|
||||||
|
if(!audioOutputArray) return -1;
|
||||||
|
|
||||||
|
if(!isCurrentFormat) {
|
||||||
|
copyAudioFormat(&audio_format, audioFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
for(i = 0; i < audioOutputArraySize; i++) {
|
||||||
|
if(!audioOutputArray[i]->open || !isCurrentFormat) {
|
||||||
|
if(0 == openAudioOutput(audioOutputArray[i],
|
||||||
|
&audio_format))
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int playAudio(char * playChunk, int size) {
|
int playAudio(char * playChunk, int size) {
|
||||||
if(shoutOutput) playAudioOutput(shoutOutput, playChunk, size);
|
int ret = -1;
|
||||||
return playAudioOutput(aoOutput, playChunk, size);
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < audioOutputArraySize; i++) {
|
||||||
|
if(0 == playAudioOutput(audioOutputArray[i], playChunk, size)) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int isAudioDeviceOpen() {
|
int isAudioDeviceOpen() {
|
||||||
return aoOutput->open;
|
int ret = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < audioOutputArraySize; i++) {
|
||||||
|
ret |= audioOutputArray[i]->open;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeAudioDevice() {
|
void closeAudioDevice() {
|
||||||
if(shoutOutput) closeAudioOutput(shoutOutput);
|
int i;
|
||||||
closeAudioOutput(aoOutput);
|
|
||||||
|
for(i = 0; i < audioOutputArraySize; i++) {
|
||||||
|
closeAudioOutput(audioOutputArray[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMetadataToAudioDevice(MpdTag * tag) {
|
void sendMetadataToAudioDevice(MpdTag * tag) {
|
||||||
if(shoutOutput) sendMetadataToAudioOutput(shoutOutput, tag);
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < audioOutputArraySize; i++) {
|
||||||
|
sendMetadataToAudioOutput(audioOutputArray[i], tag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#include <audioOutput.h>
|
#include "audioOutput.h"
|
||||||
|
|
||||||
#include <list.h>
|
#include "list.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define AUDIO_OUTPUT_TYPE "type"
|
||||||
|
#define AUDIO_OUTPUT_NAME "name"
|
||||||
|
|
||||||
static List * audioOutputPluginList;
|
static List * audioOutputPluginList;
|
||||||
|
|
||||||
@ -21,13 +27,32 @@ void finishAudioOutputPlugins() {
|
|||||||
freeList(audioOutputPluginList);
|
freeList(audioOutputPluginList);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioOutput * newAudioOutput(char * name) {
|
#define getBlockParam(name, str) { \
|
||||||
|
BlockParam * bp; \
|
||||||
|
bp = getBlockParam(param, name); \
|
||||||
|
if(bp == NULL) { \
|
||||||
|
ERROR("couldn't find parameter \"%s\" in audio output " \
|
||||||
|
"definition begining at %i\n", \
|
||||||
|
name, param->line); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
str = bp->value; \
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioOutput * newAudioOutput(ConfigParam * param) {
|
||||||
AudioOutput * ret = NULL;
|
AudioOutput * ret = NULL;
|
||||||
void * data = NULL;
|
void * data = NULL;
|
||||||
|
char * name = NULL;
|
||||||
|
char * type = NULL;
|
||||||
|
|
||||||
if(findInList(audioOutputPluginList, name, &data)) {
|
getBlockParam(AUDIO_OUTPUT_NAME, name);
|
||||||
|
getBlockParam(AUDIO_OUTPUT_TYPE, type);
|
||||||
|
|
||||||
|
if(findInList(audioOutputPluginList, type, &data)) {
|
||||||
AudioOutputPlugin * plugin = (AudioOutputPlugin *) data;
|
AudioOutputPlugin * plugin = (AudioOutputPlugin *) data;
|
||||||
ret = malloc(sizeof(AudioOutput));
|
ret = malloc(sizeof(AudioOutput));
|
||||||
|
ret->name = strdup(name);
|
||||||
|
ret->type = strdup(type);
|
||||||
ret->finishDriverFunc = plugin->finishDriverFunc;
|
ret->finishDriverFunc = plugin->finishDriverFunc;
|
||||||
ret->openDeviceFunc = plugin->openDeviceFunc;
|
ret->openDeviceFunc = plugin->openDeviceFunc;
|
||||||
ret->playFunc = plugin->playFunc;
|
ret->playFunc = plugin->playFunc;
|
||||||
@ -35,11 +60,16 @@ AudioOutput * newAudioOutput(char * name) {
|
|||||||
ret->sendMetdataFunc = plugin->sendMetdataFunc;
|
ret->sendMetdataFunc = plugin->sendMetdataFunc;
|
||||||
ret->open = 0;
|
ret->open = 0;
|
||||||
|
|
||||||
if(plugin->initDriverFunc(ret) != 0) {
|
if(plugin->initDriverFunc(ret, param) != 0) {
|
||||||
free(ret);
|
free(ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
ERROR("couldn't find audio output plugin for type \"%s\" at "
|
||||||
|
"line %i", type, param->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,14 @@
|
|||||||
#include "mpd_types.h"
|
#include "mpd_types.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
#define AUDIO_AO_DRIVER_DEFAULT "default"
|
#define AUDIO_AO_DRIVER_DEFAULT "default"
|
||||||
|
|
||||||
typedef struct _AudioOutput AudioOutput;
|
typedef struct _AudioOutput AudioOutput;
|
||||||
|
|
||||||
typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput);
|
typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput,
|
||||||
|
ConfigParam * param);
|
||||||
|
|
||||||
typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput);
|
typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput);
|
||||||
|
|
||||||
@ -46,6 +48,8 @@ typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput,
|
|||||||
|
|
||||||
struct _AudioOutput {
|
struct _AudioOutput {
|
||||||
int open;
|
int open;
|
||||||
|
char * name;
|
||||||
|
char * type;
|
||||||
|
|
||||||
AudioOutputFinishDriverFunc finishDriverFunc;
|
AudioOutputFinishDriverFunc finishDriverFunc;
|
||||||
AudioOutputOpenDeviceFunc openDeviceFunc;
|
AudioOutputOpenDeviceFunc openDeviceFunc;
|
||||||
@ -73,7 +77,7 @@ void finishAudioOutputPlugins();
|
|||||||
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
|
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
|
||||||
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
|
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
|
||||||
|
|
||||||
AudioOutput * newAudioOutput(char * name);
|
AudioOutput * newAudioOutput(ConfigParam * param);
|
||||||
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat);
|
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat);
|
||||||
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size);
|
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size);
|
||||||
void closeAudioOutput(AudioOutput * audioOutput);
|
void closeAudioOutput(AudioOutput * audioOutput);
|
||||||
|
@ -56,7 +56,9 @@ static void audioOutputAo_error() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audioOutputAo_initDriver(AudioOutput * audioOutput) {
|
static int audioOutputAo_initDriver(AudioOutput * audioOutput,
|
||||||
|
ConfigParam * param)
|
||||||
|
{
|
||||||
ao_info * ai;
|
ao_info * ai;
|
||||||
char * dup;
|
char * dup;
|
||||||
char * stk1;
|
char * stk1;
|
||||||
@ -66,38 +68,51 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput) {
|
|||||||
char * value;
|
char * value;
|
||||||
char * test;
|
char * test;
|
||||||
AoData * ad = newAoData();
|
AoData * ad = newAoData();
|
||||||
|
BlockParam * blockParam;
|
||||||
|
|
||||||
audioOutput->data = ad;
|
audioOutput->data = ad;
|
||||||
|
|
||||||
ad->writeSize = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10);
|
if((blockParam = getBlockParam(param, "write_size"))) {
|
||||||
|
ad->writeSize = strtol(blockParam->value, &test, 10);
|
||||||
if (*test!='\0') {
|
if (*test!='\0') {
|
||||||
ERROR("\"%s\" is not a valid write size\n",
|
ERROR("\"%s\" is not a valid write size at line %i\n",
|
||||||
(getConf())[CONF_AUDIO_WRITE_SIZE]);
|
blockParam->value, blockParam->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else ad->writeSize = 1024;
|
||||||
|
|
||||||
if(driverInitCount == 0) {
|
if(driverInitCount == 0) {
|
||||||
ao_initialize();
|
ao_initialize();
|
||||||
}
|
}
|
||||||
driverInitCount++;
|
driverInitCount++;
|
||||||
|
|
||||||
if(strcmp(AUDIO_AO_DRIVER_DEFAULT,(getConf())[CONF_AO_DRIVER])==0) {
|
blockParam = getBlockParam(param, "driver");
|
||||||
|
|
||||||
|
if(!blockParam || 0 == strcmp(blockParam->value,"default")) {
|
||||||
ad->driverId = ao_default_driver_id();
|
ad->driverId = ao_default_driver_id();
|
||||||
}
|
}
|
||||||
else if((ad->driverId =
|
else if((ad->driverId =
|
||||||
ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) {
|
ao_driver_id(blockParam->value))<0) {
|
||||||
ERROR("\"%s\" is not a valid ao driver\n",
|
ERROR("\"%s\" is not a valid ao driver at line %i\n",
|
||||||
(getConf())[CONF_AO_DRIVER]);
|
blockParam->value, blockParam->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((ai = ao_driver_info(ad->driverId))==NULL) {
|
if((ai = ao_driver_info(ad->driverId))==NULL) {
|
||||||
ERROR("problems getting ao_driver_info\n");
|
ERROR("problems getting driver info for device defined at "
|
||||||
|
"line %i\n", param->line);
|
||||||
ERROR("you may not have permission to the audio device\n");
|
ERROR("you may not have permission to the audio device\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
dup = strdup((getConf())[CONF_AO_DRIVER_OPTIONS]);
|
blockParam = getBlockParam(param, "options");
|
||||||
|
|
||||||
|
if(blockParam) {
|
||||||
|
dup = strdup(blockParam->value);
|
||||||
|
}
|
||||||
|
else dup = strdup("");
|
||||||
|
|
||||||
if(strlen(dup)) {
|
if(strlen(dup)) {
|
||||||
stk1 = NULL;
|
stk1 = NULL;
|
||||||
n1 = strtok_r(dup,";",&stk1);
|
n1 = strtok_r(dup,";",&stk1);
|
||||||
|
@ -88,7 +88,16 @@ static void freeShoutData(ShoutData * sd) {
|
|||||||
free(sd);
|
free(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shout_initDriver(AudioOutput * audioOutput) {
|
#define checkBlockParam(name) { \
|
||||||
|
blockParam = getBlockParam(param, name); \
|
||||||
|
if(!blockParam) { \
|
||||||
|
ERROR("no \"%s\" defined for shout device defined at line " \
|
||||||
|
"%i\n", name, param->line); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int shout_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
|
||||||
ShoutData * sd;
|
ShoutData * sd;
|
||||||
char * test;
|
char * test;
|
||||||
int port;
|
int port;
|
||||||
@ -97,73 +106,50 @@ static int shout_initDriver(AudioOutput * audioOutput) {
|
|||||||
char * passwd;
|
char * passwd;
|
||||||
char * user;
|
char * user;
|
||||||
char * name;
|
char * name;
|
||||||
|
BlockParam * blockParam;
|
||||||
if(!getConf()[CONF_SHOUT_HOST]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sd = newShoutData();
|
sd = newShoutData();
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_MOUNT]) {
|
checkBlockParam("host");
|
||||||
ERROR("shout host defined but not shout mount point\n");
|
host = blockParam->value;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_PORT]) {
|
checkBlockParam("mount");
|
||||||
ERROR("shout host defined but not shout port\n");
|
mount = blockParam->value;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_PASSWD]) {
|
checkBlockParam("port");
|
||||||
ERROR("shout host defined but not shout password\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_NAME]) {
|
port = strtol(blockParam->value, &test, 10);
|
||||||
ERROR("shout host defined but not shout name\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_USER]) {
|
|
||||||
ERROR("shout host defined but not shout user\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_QUALITY]) {
|
|
||||||
ERROR("shout host defined but not shout quality\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_SHOUT_FORMAT]) {
|
|
||||||
ERROR("shout host defined but not shout format\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
host = getConf()[CONF_SHOUT_HOST];
|
|
||||||
passwd = getConf()[CONF_SHOUT_PASSWD];
|
|
||||||
user = getConf()[CONF_SHOUT_USER];
|
|
||||||
mount = getConf()[CONF_SHOUT_MOUNT];
|
|
||||||
name = getConf()[CONF_SHOUT_NAME];
|
|
||||||
|
|
||||||
port = strtol(getConf()[CONF_SHOUT_PORT], &test, 10);
|
|
||||||
|
|
||||||
if(*test != '\0' || port <= 0) {
|
if(*test != '\0' || port <= 0) {
|
||||||
ERROR("shout port \"%s\" is not a positive integer\n",
|
ERROR("shout port \"%s\" is not a positive integer, line %i\n",
|
||||||
getConf()[CONF_SHOUT_PORT]);
|
blockParam->value, blockParam->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sd->quality = strtod(getConf()[CONF_SHOUT_QUALITY], &test);
|
checkBlockParam("password");
|
||||||
|
passwd = blockParam->value;
|
||||||
|
|
||||||
|
checkBlockParam("name");
|
||||||
|
name = blockParam->value;
|
||||||
|
|
||||||
|
checkBlockParam("user");
|
||||||
|
user = blockParam->value;
|
||||||
|
|
||||||
|
checkBlockParam("quality");
|
||||||
|
|
||||||
|
sd->quality = strtod(blockParam->value, &test);
|
||||||
|
|
||||||
if(*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) {
|
if(*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) {
|
||||||
ERROR("shout quality \"%s\" is not a number in the range "
|
ERROR("shout quality \"%s\" is not a number in the range "
|
||||||
"0-10\n", getConf()[CONF_SHOUT_QUALITY]);
|
"0-10, line %i\n", blockParam->value,
|
||||||
|
blockParam->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 != parseAudioConfig(&(sd->outAudioFormat),
|
checkBlockParam("format");
|
||||||
getConf()[CONF_SHOUT_FORMAT]) )
|
|
||||||
{
|
if(0 != parseAudioConfig(&(sd->outAudioFormat), blockParam->value)) {
|
||||||
|
ERROR("error parsing format at line %i\n", blockParam->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +262,7 @@ static int initEncoder(ShoutData * sd) {
|
|||||||
vorbis_info_init(&(sd->vi));
|
vorbis_info_init(&(sd->vi));
|
||||||
|
|
||||||
if( 0 != vorbis_encode_init_vbr(&(sd->vi), sd->outAudioFormat.channels,
|
if( 0 != vorbis_encode_init_vbr(&(sd->vi), sd->outAudioFormat.channels,
|
||||||
sd->outAudioFormat.sampleRate, sd->quality) )
|
sd->outAudioFormat.sampleRate, sd->quality/10.0) )
|
||||||
{
|
{
|
||||||
ERROR("problem seting up vorbis encoder for shout\n");
|
ERROR("problem seting up vorbis encoder for shout\n");
|
||||||
vorbis_info_clear(&(sd->vi));
|
vorbis_info_clear(&(sd->vi));
|
||||||
|
526
src/conf.c
526
src/conf.c
@ -22,8 +22,7 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "buffer2array.h"
|
#include "buffer2array.h"
|
||||||
#include "audio.h"
|
#include "list.h"
|
||||||
#include "volume.h"
|
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -36,232 +35,359 @@
|
|||||||
#define MAX_STRING_SIZE MAXPATHLEN+80
|
#define MAX_STRING_SIZE MAXPATHLEN+80
|
||||||
|
|
||||||
#define CONF_COMMENT '#'
|
#define CONF_COMMENT '#'
|
||||||
|
#define CONF_BLOCK_BEGIN "{"
|
||||||
|
#define CONF_BLOCK_END "}"
|
||||||
|
|
||||||
#define CONF_NUMBER_OF_PARAMS 43
|
#define CONF_REPEATABLE_MASK 0x01
|
||||||
#define CONF_NUMBER_OF_PATHS 6
|
#define CONF_BLOCK_MASK 0x02
|
||||||
#define CONF_NUMBER_OF_REQUIRED 5
|
|
||||||
#define CONF_NUMBER_OF_ALLOW_CATS 1
|
|
||||||
|
|
||||||
#define CONF_CONNECTION_TIMEOUT_DEFAULT "60"
|
typedef struct _configEntry {
|
||||||
#define CONF_MAX_CONNECTIONS_DEFAULT "5"
|
unsigned char mask;
|
||||||
#define CONF_MAX_PLAYLIST_LENGTH_DEFAULT "16384"
|
List * configParamList;
|
||||||
#define CONF_BUFFER_BEFORE_PLAY_DEFAULT "25%"
|
} ConfigEntry;
|
||||||
#define CONF_MAX_COMMAND_LIST_SIZE_DEFAULT "2048"
|
|
||||||
#define CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT "2048"
|
|
||||||
#define CONF_AO_DRIVER_DEFAULT AUDIO_AO_DRIVER_DEFAULT
|
|
||||||
#define CONF_AO_DRIVER_OPTIONS_DEFAULT ""
|
|
||||||
#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT "no"
|
|
||||||
#define CONF_BIND_TO_ADDRESS_DEFAULT "any"
|
|
||||||
#define CONF_USER_DEFAULT ""
|
|
||||||
#define CONF_LOG_LEVEL_DEFAULT "default"
|
|
||||||
#define CONF_AUDIO_WRITE_SIZE_DEFAULT "1024"
|
|
||||||
#define CONF_BUFFER_SIZE_DEFAULT "2048"
|
|
||||||
#ifndef NO_OSS_MIXER
|
|
||||||
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_OSS
|
|
||||||
#define CONF_MIXER_DEVICE_DEFAULT ""
|
|
||||||
#else
|
|
||||||
#ifdef HAVE_ALSA
|
|
||||||
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_ALSA
|
|
||||||
#define CONF_MIXER_DEVICE_DEFAULT ""
|
|
||||||
#else
|
|
||||||
#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_SOFTWARE
|
|
||||||
#define CONF_MIXER_DEVICE_DEFAULT ""
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char * conf_params[CONF_NUMBER_OF_PARAMS];
|
static List * configEntriesList = NULL;
|
||||||
|
|
||||||
void initConf() {
|
static ConfigParam * newConfigParam(char * value, int line) {
|
||||||
int i;
|
ConfigParam * ret = malloc(sizeof(ConfigParam));
|
||||||
|
|
||||||
for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) conf_params[i] = NULL;
|
if(!value) ret->value = NULL;
|
||||||
|
else ret->value = strdup(value);
|
||||||
|
|
||||||
/* we don't specify these on the command line */
|
ret->line = line;
|
||||||
conf_params[CONF_CONNECTION_TIMEOUT] = strdup(CONF_CONNECTION_TIMEOUT_DEFAULT);
|
|
||||||
conf_params[CONF_MIXER_DEVICE] = strdup(CONF_MIXER_DEVICE_DEFAULT);
|
ret->numberOfBlockParams = 0;
|
||||||
conf_params[CONF_MAX_CONNECTIONS] = strdup(CONF_MAX_CONNECTIONS_DEFAULT);
|
ret->blockParams = NULL;
|
||||||
conf_params[CONF_MAX_PLAYLIST_LENGTH] = strdup(CONF_MAX_PLAYLIST_LENGTH_DEFAULT);
|
|
||||||
conf_params[CONF_BUFFER_BEFORE_PLAY] = strdup(CONF_BUFFER_BEFORE_PLAY_DEFAULT);
|
return ret;
|
||||||
conf_params[CONF_MAX_COMMAND_LIST_SIZE] = strdup(CONF_MAX_COMMAND_LIST_SIZE_DEFAULT);
|
|
||||||
conf_params[CONF_MAX_OUTPUT_BUFFER_SIZE] = strdup(CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT);
|
|
||||||
conf_params[CONF_AO_DRIVER] = strdup(CONF_AO_DRIVER_DEFAULT);
|
|
||||||
conf_params[CONF_AO_DRIVER_OPTIONS] = strdup(CONF_AO_DRIVER_OPTIONS_DEFAULT);
|
|
||||||
conf_params[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS] = strdup(CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT);
|
|
||||||
conf_params[CONF_BIND_TO_ADDRESS] = strdup(CONF_BIND_TO_ADDRESS_DEFAULT);
|
|
||||||
conf_params[CONF_MIXER_TYPE] = strdup(CONF_MIXER_TYPE_DEFAULT);
|
|
||||||
conf_params[CONF_USER] = strdup(CONF_USER_DEFAULT);
|
|
||||||
conf_params[CONF_LOG_LEVEL] = strdup(CONF_LOG_LEVEL_DEFAULT);
|
|
||||||
conf_params[CONF_AUDIO_WRITE_SIZE] = strdup(CONF_AUDIO_WRITE_SIZE_DEFAULT);
|
|
||||||
conf_params[CONF_BUFFER_SIZE] = strdup(CONF_BUFFER_SIZE_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char ** readConf(char * file) {
|
static void freeConfigParam(ConfigParam * param) {
|
||||||
char * conf_strings[CONF_NUMBER_OF_PARAMS] = {
|
int i;
|
||||||
"port",
|
|
||||||
"music_directory",
|
|
||||||
"playlist_directory",
|
|
||||||
"log_file",
|
|
||||||
"error_file",
|
|
||||||
"connection_timeout",
|
|
||||||
"mixer_device",
|
|
||||||
"max_connections",
|
|
||||||
"max_playlist_length",
|
|
||||||
"buffer_before_play",
|
|
||||||
"max_command_list_size",
|
|
||||||
"max_output_buffer_size",
|
|
||||||
"ao_driver",
|
|
||||||
"ao_driver_options",
|
|
||||||
"save_absolute_paths_in_playlists",
|
|
||||||
"bind_to_address",
|
|
||||||
"mixer_type",
|
|
||||||
"state_file",
|
|
||||||
"user",
|
|
||||||
"db_file",
|
|
||||||
"log_level",
|
|
||||||
"mixer_control",
|
|
||||||
"audio_write_size",
|
|
||||||
"filesystem_charset",
|
|
||||||
"password",
|
|
||||||
"default_permissions",
|
|
||||||
"audio_buffer_size",
|
|
||||||
"replaygain",
|
|
||||||
"audio_output_format",
|
|
||||||
"http_proxy_host",
|
|
||||||
"http_proxy_port",
|
|
||||||
"http_proxy_user",
|
|
||||||
"http_proxy_password",
|
|
||||||
"replaygain_preamp",
|
|
||||||
"shout_host",
|
|
||||||
"shout_port",
|
|
||||||
"shout_password",
|
|
||||||
"shout_mount",
|
|
||||||
"shout_name",
|
|
||||||
"shout_user",
|
|
||||||
"shout_quality",
|
|
||||||
"id3v1_encoding",
|
|
||||||
"shout_format"
|
|
||||||
};
|
|
||||||
|
|
||||||
int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = {
|
if(param->value) free(param->value);
|
||||||
CONF_MUSIC_DIRECTORY,
|
|
||||||
CONF_PLAYLIST_DIRECTORY,
|
|
||||||
CONF_LOG_FILE,
|
|
||||||
CONF_ERROR_FILE,
|
|
||||||
CONF_STATE_FILE,
|
|
||||||
CONF_DB_FILE
|
|
||||||
};
|
|
||||||
|
|
||||||
int conf_required[CONF_NUMBER_OF_REQUIRED] = {
|
for(i=0; i<param->numberOfBlockParams; i++) {
|
||||||
CONF_MUSIC_DIRECTORY,
|
if(param->blockParams[i].name) {
|
||||||
CONF_PLAYLIST_DIRECTORY,
|
free(param->blockParams[i].name);
|
||||||
CONF_LOG_FILE,
|
}
|
||||||
CONF_ERROR_FILE,
|
if(param->blockParams[i].value) {
|
||||||
CONF_PORT
|
free(param->blockParams[i].value);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
short conf_allowCat[CONF_NUMBER_OF_ALLOW_CATS] = {
|
if(param->numberOfBlockParams) free(param->blockParams);
|
||||||
CONF_PASSWORD
|
|
||||||
};
|
|
||||||
|
|
||||||
|
free(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigEntry * newConfigEntry(int repeatable, int block) {
|
||||||
|
ConfigEntry * ret = malloc(sizeof(ConfigEntry));
|
||||||
|
|
||||||
|
ret->mask = 0;
|
||||||
|
ret->configParamList = makeList((ListFreeDataFunc *)freeConfigParam);
|
||||||
|
|
||||||
|
if(repeatable) ret->mask |= CONF_REPEATABLE_MASK;
|
||||||
|
if(block) ret->mask |= CONF_BLOCK_MASK;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeConfigEntry(ConfigEntry * entry) {
|
||||||
|
freeList(entry->configParamList);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerConfigParam(char * name, int repeatable, int block) {
|
||||||
|
ConfigEntry * entry;
|
||||||
|
|
||||||
|
if(findInList(configEntriesList, name, NULL)) {
|
||||||
|
ERROR("config parameter \"%s\" already registered\n", name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = newConfigEntry(repeatable, block);
|
||||||
|
|
||||||
|
insertInList(configEntriesList, name, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initConf() {
|
||||||
|
configEntriesList = makeList((ListFreeDataFunc *)freeConfigEntry);
|
||||||
|
|
||||||
|
registerConfigParam(CONF_PORT, 0, 0);
|
||||||
|
registerConfigParam(CONF_MUSIC_DIR, 0, 0);
|
||||||
|
registerConfigParam(CONF_PLAYLIST_DIR, 0, 0);
|
||||||
|
registerConfigParam(CONF_LOG_FILE, 0, 0);
|
||||||
|
registerConfigParam(CONF_ERROR_FILE, 0, 0);
|
||||||
|
registerConfigParam(CONF_CONN_TIMEOUT, 0, 0);
|
||||||
|
registerConfigParam(CONF_MIXER_DEVICE, 0, 0);
|
||||||
|
registerConfigParam(CONF_MAX_CONN, 0, 0);
|
||||||
|
registerConfigParam(CONF_MAX_PLAYLIST_LENGTH, 0, 0);
|
||||||
|
registerConfigParam(CONF_BUFFER_BEFORE_PLAY, 0, 0);
|
||||||
|
registerConfigParam(CONF_MAX_COMMAND_LIST_SIZE, 0, 0);
|
||||||
|
registerConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE, 0, 0);
|
||||||
|
registerConfigParam(CONF_AUDIO_OUTPUT, 1, 1);
|
||||||
|
registerConfigParam(CONF_SAVE_ABSOLUTE_PATHS, 0, 0);
|
||||||
|
registerConfigParam(CONF_BIND_TO_ADDRESS, 1, 0);
|
||||||
|
registerConfigParam(CONF_MIXER_TYPE, 0, 0);
|
||||||
|
registerConfigParam(CONF_STATE_FILE, 0, 0);
|
||||||
|
registerConfigParam(CONF_USER, 0, 0);
|
||||||
|
registerConfigParam(CONF_DB_FILE, 0, 0);
|
||||||
|
registerConfigParam(CONF_LOG_LEVEL, 0, 0);
|
||||||
|
registerConfigParam(CONF_MIXER_CONTROL, 0, 0);
|
||||||
|
registerConfigParam(CONF_AUDIO_WRITE_SIZE, 0, 0);
|
||||||
|
registerConfigParam(CONF_FS_CHARSET, 0, 0);
|
||||||
|
registerConfigParam(CONF_PASSWORD, 1, 0);
|
||||||
|
registerConfigParam(CONF_DEFAULT_PERMS, 0, 0);
|
||||||
|
registerConfigParam(CONF_AUDIO_BUFFER_SIZE, 0, 0);
|
||||||
|
registerConfigParam(CONF_REPLAYGAIN, 0, 0);
|
||||||
|
registerConfigParam(CONF_AUDIO_OUTPUT_FORMAT, 0, 0);
|
||||||
|
registerConfigParam(CONF_HTTP_PROXY_HOST, 0, 0);
|
||||||
|
registerConfigParam(CONF_HTTP_PROXY_PORT, 0, 0);
|
||||||
|
registerConfigParam(CONF_HTTP_PROXY_USER, 0, 0);
|
||||||
|
registerConfigParam(CONF_HTTP_PROXY_PASSWORD, 0, 0);
|
||||||
|
registerConfigParam(CONF_REPLAYGAIN_PREAMP, 0, 0);
|
||||||
|
registerConfigParam(CONF_ID3V1_ENCODING, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addBlockParam(ConfigParam * param, char * name, char * value,
|
||||||
|
int line)
|
||||||
|
{
|
||||||
|
param->numberOfBlockParams++;
|
||||||
|
|
||||||
|
param->blockParams = realloc(param->blockParams,
|
||||||
|
param->numberOfBlockParams*sizeof(BlockParam));
|
||||||
|
|
||||||
|
param->blockParams[param->numberOfBlockParams-1].name = strdup(name);
|
||||||
|
param->blockParams[param->numberOfBlockParams-1].value = strdup(value);
|
||||||
|
param->blockParams[param->numberOfBlockParams-1].line = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) {
|
||||||
|
ConfigParam * ret = newConfigParam(NULL, *count);
|
||||||
|
|
||||||
|
char ** array;
|
||||||
|
int i;
|
||||||
|
int numberOfArgs;
|
||||||
|
int argsMinusComment;
|
||||||
|
|
||||||
|
while(myFgets(string, MAX_STRING_SIZE ,fp)) {
|
||||||
|
(*count)++;
|
||||||
|
|
||||||
|
numberOfArgs = buffer2array(string, &array);
|
||||||
|
|
||||||
|
for(i=0; i<numberOfArgs; i++) {
|
||||||
|
if(array[i][0] == CONF_COMMENT) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
argsMinusComment = i;
|
||||||
|
|
||||||
|
if(0 == argsMinusComment) continue;
|
||||||
|
|
||||||
|
if(1 == argsMinusComment &&
|
||||||
|
0 == strcmp(array[0], CONF_BLOCK_END))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(2 != argsMinusComment) {
|
||||||
|
ERROR("improperly formated config file at line %i:"
|
||||||
|
" %s\n", count, string);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0 == strcmp(array[0], CONF_BLOCK_BEGIN) ||
|
||||||
|
0 == strcmp(array[1], CONF_BLOCK_BEGIN) ||
|
||||||
|
0 == strcmp(array[0], CONF_BLOCK_END) ||
|
||||||
|
0 == strcmp(array[1], CONF_BLOCK_END))
|
||||||
|
{
|
||||||
|
ERROR("improperly formated config file at line %i:"
|
||||||
|
" %s\n", count, string);
|
||||||
|
ERROR("in block begging at line %i\n", ret->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
addBlockParam(ret, array[0], array[1], *count);
|
||||||
|
|
||||||
|
freeArgArray(array, numberOfArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void readConf(char * file) {
|
||||||
FILE * fp;
|
FILE * fp;
|
||||||
char string[MAX_STRING_SIZE+1];
|
char string[MAX_STRING_SIZE+1];
|
||||||
char ** array;
|
char ** array;
|
||||||
int i;
|
int i;
|
||||||
int numberOfArgs;
|
int numberOfArgs;
|
||||||
short allowCat[CONF_NUMBER_OF_PARAMS];
|
int argsMinusComment;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
ConfigEntry * entry;
|
||||||
for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) allowCat[i] = 0;
|
void * voidPtr;
|
||||||
|
ConfigParam * param;
|
||||||
for(i=0;i<CONF_NUMBER_OF_ALLOW_CATS;i++) allowCat[conf_allowCat[i]] = 1;
|
|
||||||
|
|
||||||
if(!(fp=fopen(file,"r"))) {
|
if(!(fp=fopen(file,"r"))) {
|
||||||
ERROR("problems opening file %s for reading\n",file);
|
ERROR("problems opening file %s for reading\n",file);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(myFgets(string,sizeof(string),fp)) {
|
while(myFgets(string, MAX_STRING_SIZE, fp)) {
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if(string[0]==CONF_COMMENT) continue;
|
numberOfArgs = buffer2array(string, &array);
|
||||||
numberOfArgs = buffer2array(string,&array);
|
|
||||||
if(numberOfArgs==0) continue;
|
for(i=0; i<numberOfArgs; i++) {
|
||||||
if(2!=numberOfArgs) {
|
if(array[i][0] == CONF_COMMENT) break;
|
||||||
ERROR("improperly formated config file at line %i: %s\n",count,string);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
i = 0;
|
|
||||||
while(i<CONF_NUMBER_OF_PARAMS && 0!=strcmp(conf_strings[i],array[0])) i++;
|
argsMinusComment = i;
|
||||||
if(i>=CONF_NUMBER_OF_PARAMS) {
|
|
||||||
ERROR("unrecognized paramater in conf at line %i: %s\n",count,string);
|
if(0 == argsMinusComment) continue;
|
||||||
|
|
||||||
|
if(2 != argsMinusComment) {
|
||||||
|
ERROR("improperly formated config file at line %i:"
|
||||||
|
" %s\n", count, string);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(conf_params[i]!=NULL) {
|
if(!findInList(configEntriesList, array[0], &voidPtr)) {
|
||||||
if(allowCat[i]) {
|
ERROR("unrecognized paramater in config file at line "
|
||||||
conf_params[i] = realloc(conf_params[i],
|
"%i: %s\n", count, string);
|
||||||
strlen(conf_params[i])+
|
|
||||||
strlen(CONF_CAT_CHAR)+
|
|
||||||
strlen(array[1])+1);
|
|
||||||
strcat(conf_params[i],CONF_CAT_CHAR);
|
|
||||||
strcat(conf_params[i],array[1]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
free(conf_params[i]);
|
|
||||||
conf_params[i] = strdup(array[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else conf_params[i] = strdup(array[1]);
|
|
||||||
free(array[0]);
|
|
||||||
free(array[1]);
|
|
||||||
free(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
for(i=0;i<CONF_NUMBER_OF_REQUIRED;i++) {
|
|
||||||
if(conf_params[conf_required[i]] == NULL) {
|
|
||||||
ERROR("%s is unassigned in conf file\n",
|
|
||||||
conf_strings[conf_required[i]]);
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<CONF_NUMBER_OF_PATHS;i++) {
|
entry = (ConfigEntry *) voidPtr;
|
||||||
if(conf_params[conf_absolutePaths[i]] &&
|
|
||||||
conf_params[conf_absolutePaths[i]][0]!='/' &&
|
if( !(entry->mask & CONF_REPEATABLE_MASK) &&
|
||||||
conf_params[conf_absolutePaths[i]][0]!='~')
|
entry->configParamList->numberOfNodes)
|
||||||
{
|
{
|
||||||
ERROR("\"%s\" is not an absolute path\n",
|
param = entry->configParamList->firstNode->data;
|
||||||
conf_params[conf_absolutePaths[i]]);
|
ERROR("config paramter \"%s\" is first defined on line "
|
||||||
|
"%i and redefined on line %i\n",
|
||||||
|
array[0], param->line, count);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
/* Parse ~ in path */
|
|
||||||
else if(conf_params[conf_absolutePaths[i]] &&
|
if(entry->mask & CONF_BLOCK_MASK) {
|
||||||
conf_params[conf_absolutePaths[i]][0]=='~')
|
if(0 != strcmp(array[1], CONF_BLOCK_BEGIN)) {
|
||||||
{
|
ERROR("improperly formated config file at "
|
||||||
struct passwd * pwd = NULL;
|
"line %i: %s\n", count, string);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
param = readConfigBlock(fp, &count, string);
|
||||||
|
}
|
||||||
|
else param = newConfigParam(array[1], count);
|
||||||
|
|
||||||
|
insertInListWithoutKey(entry->configParamList, param);
|
||||||
|
|
||||||
|
freeArgArray(array, numberOfArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigParam * getNextConfigParam(char * name, ConfigParam * last) {
|
||||||
|
void * voidPtr;
|
||||||
|
ConfigEntry * entry;
|
||||||
|
ListNode * node;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
|
if(!findInList(configEntriesList, name, &voidPtr)) return NULL;
|
||||||
|
|
||||||
|
entry = voidPtr;
|
||||||
|
|
||||||
|
node = entry->configParamList->firstNode;
|
||||||
|
|
||||||
|
if(last) {
|
||||||
|
while(node!=NULL) {
|
||||||
|
param = node->data;
|
||||||
|
node = node->nextNode;
|
||||||
|
if(param == last) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node == NULL) return NULL;
|
||||||
|
|
||||||
|
param = node->data;
|
||||||
|
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * getConfigParamValue(char * name) {
|
||||||
|
ConfigParam * param = getConfigParam(name);
|
||||||
|
|
||||||
|
if(!param) return NULL;
|
||||||
|
|
||||||
|
return param->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * forceAndGetConfigParamValue(char * name) {
|
||||||
|
ConfigParam * param = getConfigParam(name);
|
||||||
|
|
||||||
|
if(!param) {
|
||||||
|
ERROR("\"%s\" not found in config file\n", name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return param->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockParam * getBlockParam(ConfigParam * param, char * name) {
|
||||||
|
BlockParam * ret = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < param->numberOfBlockParams; i++) {
|
||||||
|
if(0 == strcmp(name, param->blockParams[i].name)) {
|
||||||
|
if(ret) {
|
||||||
|
ERROR("\"%s\" first defined on line %i, and "
|
||||||
|
"redefined on line %i\n", name,
|
||||||
|
ret->line, param->blockParams[i].line);
|
||||||
|
}
|
||||||
|
ret = param->blockParams+i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * parseConfigFilePath(char * name, int force) {
|
||||||
|
ConfigParam * param = getConfigParam(name);
|
||||||
char * path;
|
char * path;
|
||||||
|
|
||||||
|
if(!param && force) {
|
||||||
|
ERROR("config parameter \"%s\" not found\n", name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!param) return NULL;
|
||||||
|
|
||||||
|
path = param->value;
|
||||||
|
|
||||||
|
if(path[0] != '/' && path[0] != '~') {
|
||||||
|
ERROR("\"%s\" is not an absolute path at line %i\n",
|
||||||
|
param->value, param->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// Parse ~ in path
|
||||||
|
else if(path[0] == '~') {
|
||||||
|
struct passwd * pwd = NULL;
|
||||||
|
char * newPath;
|
||||||
int pos = 1;
|
int pos = 1;
|
||||||
if(conf_params[conf_absolutePaths[i]][1]=='/' ||
|
if(path[1]=='/' || path[1] == '\0') {
|
||||||
conf_params[conf_absolutePaths[i]][1]=='\0')
|
ConfigParam * userParam = getConfigParam(CONF_USER);
|
||||||
{
|
|
||||||
if(conf_params[CONF_USER] &&
|
if(userParam) {
|
||||||
strlen(conf_params[CONF_USER]))
|
pwd = getpwnam(userParam->value);
|
||||||
{
|
|
||||||
pwd = getpwnam(
|
|
||||||
conf_params[CONF_USER]);
|
|
||||||
if(!pwd) {
|
if(!pwd) {
|
||||||
ERROR("no such user: %s\n",
|
ERROR("no such user %s at line %i\n",
|
||||||
conf_params[CONF_USER]);
|
userParam->value,
|
||||||
|
userParam->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uid_t uid = geteuid();
|
uid_t uid = geteuid();
|
||||||
if((pwd = getpwuid(uid)) == NULL) {
|
if((pwd = getpwuid(uid)) == NULL) {
|
||||||
ERROR("problems getting passwd "
|
ERROR("problems getting passwd entry "
|
||||||
"entry "
|
|
||||||
"for current user\n");
|
"for current user\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -269,36 +395,24 @@ char ** readConf(char * file) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int foundSlash = 0;
|
int foundSlash = 0;
|
||||||
char * ch = &(
|
char * ch = path+1;
|
||||||
conf_params[conf_absolutePaths[i]][1]);
|
|
||||||
for(;*ch!='\0' && *ch!='/';ch++);
|
for(;*ch!='\0' && *ch!='/';ch++);
|
||||||
if(*ch=='/') foundSlash = 1;
|
if(*ch=='/') foundSlash = 1;
|
||||||
* ch = '\0';
|
* ch = '\0';
|
||||||
pos+= ch-
|
pos+= ch-path+1;
|
||||||
&(conf_params[
|
if((pwd = getpwnam(path+1)) == NULL) {
|
||||||
conf_absolutePaths[i]][1]);
|
ERROR("user \"%s\" not found at line %i\n",
|
||||||
if((pwd = getpwnam(&(conf_params[
|
path+1, param->line);
|
||||||
conf_absolutePaths[i]][1]))) == NULL)
|
|
||||||
{
|
|
||||||
ERROR("user \"%s\" not found\n",
|
|
||||||
&(conf_params[
|
|
||||||
conf_absolutePaths[i]][1]));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if(foundSlash) *ch = '/';
|
if(foundSlash) *ch = '/';
|
||||||
}
|
}
|
||||||
path = malloc(strlen(pwd->pw_dir)+strlen(
|
newPath = malloc(strlen(pwd->pw_dir)+strlen(path+pos)+1);
|
||||||
&(conf_params[conf_absolutePaths[i]][pos]))+1);
|
strcpy(newPath, pwd->pw_dir);
|
||||||
strcpy(path,pwd->pw_dir);
|
strcat(newPath, path+pos);
|
||||||
strcat(path,&(conf_params[conf_absolutePaths[i]][pos]));
|
free(param->value);
|
||||||
free(conf_params[conf_absolutePaths[i]]);
|
param->value = newPath;
|
||||||
conf_params[conf_absolutePaths[i]] = path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf_params;
|
return param->value;
|
||||||
}
|
|
||||||
|
|
||||||
char ** getConf() {
|
|
||||||
return conf_params;
|
|
||||||
}
|
}
|
||||||
|
111
src/conf.h
111
src/conf.h
@ -21,59 +21,72 @@
|
|||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
#define CONF_PORT 0
|
#define CONF_PORT "port"
|
||||||
#define CONF_MUSIC_DIRECTORY 1
|
#define CONF_MUSIC_DIR "music_directory"
|
||||||
#define CONF_PLAYLIST_DIRECTORY 2
|
#define CONF_PLAYLIST_DIR "playlist_directory"
|
||||||
#define CONF_LOG_FILE 3
|
#define CONF_LOG_FILE "log_file"
|
||||||
#define CONF_ERROR_FILE 4
|
#define CONF_ERROR_FILE "error_file"
|
||||||
#define CONF_CONNECTION_TIMEOUT 5
|
#define CONF_CONN_TIMEOUT "connection_timeout"
|
||||||
#define CONF_MIXER_DEVICE 6
|
#define CONF_MIXER_DEVICE "mixer_device"
|
||||||
#define CONF_MAX_CONNECTIONS 7
|
#define CONF_MAX_CONN "max_connections"
|
||||||
#define CONF_MAX_PLAYLIST_LENGTH 8
|
#define CONF_MAX_PLAYLIST_LENGTH "max_playlist_length"
|
||||||
#define CONF_BUFFER_BEFORE_PLAY 9
|
#define CONF_BUFFER_BEFORE_PLAY "buffer_before_play"
|
||||||
#define CONF_MAX_COMMAND_LIST_SIZE 10
|
#define CONF_MAX_COMMAND_LIST_SIZE "max_command_list_size"
|
||||||
#define CONF_MAX_OUTPUT_BUFFER_SIZE 11
|
#define CONF_MAX_OUTPUT_BUFFER_SIZE "max_output_buffer_size"
|
||||||
#define CONF_AO_DRIVER 12
|
#define CONF_AUDIO_OUTPUT "audio_output"
|
||||||
#define CONF_AO_DRIVER_OPTIONS 13
|
#define CONF_SAVE_ABSOLUTE_PATHS "save_absolute_paths_in_playlists"
|
||||||
#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS 14
|
#define CONF_BIND_TO_ADDRESS "bind_to_address"
|
||||||
#define CONF_BIND_TO_ADDRESS 15
|
#define CONF_MIXER_TYPE "mixer_type"
|
||||||
#define CONF_MIXER_TYPE 16
|
#define CONF_STATE_FILE "state_file"
|
||||||
#define CONF_STATE_FILE 17
|
#define CONF_USER "user"
|
||||||
#define CONF_USER 18
|
#define CONF_DB_FILE "db_file"
|
||||||
#define CONF_DB_FILE 19
|
#define CONF_LOG_LEVEL "log_level"
|
||||||
#define CONF_LOG_LEVEL 20
|
#define CONF_MIXER_CONTROL "mixer_control"
|
||||||
#define CONF_MIXER_CONTROL 21
|
#define CONF_AUDIO_WRITE_SIZE "audio_write_size"
|
||||||
#define CONF_AUDIO_WRITE_SIZE 22
|
#define CONF_FS_CHARSET "filesystem_charset"
|
||||||
#define CONF_FS_CHARSET 23
|
#define CONF_PASSWORD "password"
|
||||||
#define CONF_PASSWORD 24
|
#define CONF_DEFAULT_PERMS "default_permissions"
|
||||||
#define CONF_DEFAULT_PERMISSIONS 25
|
#define CONF_AUDIO_BUFFER_SIZE "audio_buffer_size"
|
||||||
#define CONF_BUFFER_SIZE 26
|
#define CONF_REPLAYGAIN "replaygain"
|
||||||
#define CONF_REPLAYGAIN 27
|
#define CONF_AUDIO_OUTPUT_FORMAT "audio_output_format"
|
||||||
#define CONF_AUDIO_OUTPUT_FORMAT 28
|
#define CONF_HTTP_PROXY_HOST "http_proxy_host"
|
||||||
#define CONF_HTTP_PROXY_HOST 29
|
#define CONF_HTTP_PROXY_PORT "http_proxy_port"
|
||||||
#define CONF_HTTP_PROXY_PORT 30
|
#define CONF_HTTP_PROXY_USER "http_proxy_user"
|
||||||
#define CONF_HTTP_PROXY_USER 31
|
#define CONF_HTTP_PROXY_PASSWORD "http_proxy_password"
|
||||||
#define CONF_HTTP_PROXY_PASSWORD 32
|
#define CONF_REPLAYGAIN_PREAMP "replaygain_preamp"
|
||||||
#define CONF_REPLAYGAIN_PREAMP 33
|
#define CONF_ID3V1_ENCODING "id3v1_encoding"
|
||||||
#define CONF_SHOUT_HOST 34
|
|
||||||
#define CONF_SHOUT_PORT 35
|
|
||||||
#define CONF_SHOUT_PASSWD 36
|
|
||||||
#define CONF_SHOUT_MOUNT 37
|
|
||||||
#define CONF_SHOUT_NAME 38
|
|
||||||
#define CONF_SHOUT_USER 39
|
|
||||||
#define CONF_SHOUT_QUALITY 40
|
|
||||||
#define CONF_ID3V1_ENCODING 41
|
|
||||||
#define CONF_SHOUT_FORMAT 42
|
|
||||||
|
|
||||||
#define CONF_CAT_CHAR "\n"
|
typedef struct _BlockParam {
|
||||||
|
char * name;
|
||||||
|
char * value;
|
||||||
|
int line;
|
||||||
|
} BlockParam;
|
||||||
|
|
||||||
/* do not free the return value, it is a static variable */
|
typedef struct _ConfigParam {
|
||||||
char ** readConf(char * file);
|
char * value;
|
||||||
|
unsigned int line;
|
||||||
char ** getConf();
|
BlockParam * blockParams;
|
||||||
|
int numberOfBlockParams;
|
||||||
|
} ConfigParam;
|
||||||
|
|
||||||
void initConf();
|
void initConf();
|
||||||
|
|
||||||
void writeConf(char * file);
|
void readConf(char * file);
|
||||||
|
|
||||||
|
/* don't free the returned value
|
||||||
|
set _last_ to NULL to get first entry */
|
||||||
|
ConfigParam * getNextConfigParam(char * name, ConfigParam * last);
|
||||||
|
|
||||||
|
#define getConfigParam(name) getNextConfigParam(name, NULL)
|
||||||
|
|
||||||
|
char * getConfigParamValue(char * name);
|
||||||
|
|
||||||
|
char * forceAndGetConfigParamValue(char * name);
|
||||||
|
|
||||||
|
void registerConfigParam(char * name, int repeats, int block);
|
||||||
|
|
||||||
|
BlockParam * getBlockParam(ConfigParam * param, char * name);
|
||||||
|
|
||||||
|
char * parseConfigFilePath(char * name, int force);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1053,7 +1053,8 @@ int readDirectoryDB() {
|
|||||||
fsCharset = &(buffer[strlen(
|
fsCharset = &(buffer[strlen(
|
||||||
DIRECTORY_FS_CHARSET)]);
|
DIRECTORY_FS_CHARSET)]);
|
||||||
if((tempCharset =
|
if((tempCharset =
|
||||||
getConf()[CONF_FS_CHARSET]) &&
|
getConfigParamValue(
|
||||||
|
CONF_FS_CHARSET)) &&
|
||||||
strcmp(fsCharset,tempCharset))
|
strcmp(fsCharset,tempCharset))
|
||||||
{
|
{
|
||||||
WARNING("Using \"%s\" for the "
|
WARNING("Using \"%s\" for the "
|
||||||
|
@ -47,6 +47,11 @@
|
|||||||
|
|
||||||
#define HTTP_REDIRECT_MAX 10
|
#define HTTP_REDIRECT_MAX 10
|
||||||
|
|
||||||
|
static char * proxyHost = NULL;
|
||||||
|
static int proxyPort = 0;
|
||||||
|
static char * proxyUser = NULL;
|
||||||
|
static char * proxyPassword = NULL;
|
||||||
|
|
||||||
typedef struct _InputStreemHTTPData {
|
typedef struct _InputStreemHTTPData {
|
||||||
char * host;
|
char * host;
|
||||||
char * path;
|
char * path;
|
||||||
@ -59,57 +64,73 @@ typedef struct _InputStreemHTTPData {
|
|||||||
int icyMetaint;
|
int icyMetaint;
|
||||||
int prebuffer;
|
int prebuffer;
|
||||||
int icyOffset;
|
int icyOffset;
|
||||||
char * proxyHost;
|
|
||||||
int proxyPort;
|
|
||||||
char * proxyAuth;
|
char * proxyAuth;
|
||||||
char * httpAuth;
|
char * httpAuth;
|
||||||
} InputStreamHTTPData;
|
} InputStreamHTTPData;
|
||||||
|
|
||||||
void inputStream_initHttp() {
|
void inputStream_initHttp() {
|
||||||
if(getConf()[CONF_HTTP_PROXY_HOST]) {
|
ConfigParam * param = getConfigParam(CONF_HTTP_PROXY_HOST);
|
||||||
char * portStr = getConf()[CONF_HTTP_PROXY_PORT];
|
|
||||||
int port = 0;
|
|
||||||
char * test;
|
char * test;
|
||||||
|
|
||||||
if(!portStr) {
|
if(param) {
|
||||||
ERROR("http_proxy_host specified but not the http_"
|
proxyHost = param->value;
|
||||||
"proxy_port\n");
|
|
||||||
|
param = getConfigParam(CONF_HTTP_PROXY_PORT);
|
||||||
|
|
||||||
|
if(!param) {
|
||||||
|
ERROR("%s specified but not %s", CONF_HTTP_PROXY_HOST,
|
||||||
|
CONF_HTTP_PROXY_PORT);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
port = strtol(portStr, &test, 10);
|
proxyPort = strtol(param->value, &test, 10);
|
||||||
if(port <= 0 || *test != '\0') {
|
if(proxyPort <= 0 || *test != '\0') {
|
||||||
ERROR("http_proxy_port \"%s\" is not a positive integer"
|
ERROR("%s \"%s\" is not a positive integer, line %i\n"
|
||||||
"\n", portStr);
|
CONF_HTTP_PROXY_PORT, param->value,
|
||||||
|
param->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConf()[CONF_HTTP_PROXY_USER] &&
|
param = getConfigParam(CONF_HTTP_PROXY_USER);
|
||||||
!getConf()[CONF_HTTP_PROXY_PASSWORD])
|
|
||||||
{
|
if(param) {
|
||||||
ERROR("http_proxy_user specified, but not http_proxy_"
|
proxyUser = param->value;
|
||||||
"password\n");
|
|
||||||
|
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
|
||||||
|
|
||||||
|
if(!param) {
|
||||||
|
ERROR("%s specifid but not %s\n",
|
||||||
|
CONF_HTTP_PROXY_USER,
|
||||||
|
CONF_HTTP_PROXY_PASSWORD);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConf()[CONF_HTTP_PROXY_PASSWORD] &&
|
proxyPassword = param->value;
|
||||||
!getConf()[CONF_HTTP_PROXY_USER])
|
}
|
||||||
{
|
|
||||||
ERROR("http proxy password specified, but not http "
|
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
|
||||||
"proxy user\n");
|
|
||||||
|
if(param) {
|
||||||
|
ERROR("%s specifid but not %s\n",
|
||||||
|
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(getConf()[CONF_HTTP_PROXY_PORT]) {
|
else if((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
|
||||||
ERROR("http_proxy_port specified but not http_proxy_host\n");
|
ERROR("%s specified but not %s, line %i\n",
|
||||||
|
CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST,
|
||||||
|
param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
else if(getConf()[CONF_HTTP_PROXY_USER]) {
|
else if((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
|
||||||
ERROR("http_proxy_user specified but not http_proxy_host\n");
|
ERROR("%s specified but not %s, line %i\n",
|
||||||
|
CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST,
|
||||||
|
param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
else if(getConf()[CONF_HTTP_PROXY_PASSWORD]) {
|
else if((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
|
||||||
ERROR("http_proxy_password specified but not http_proxy_host"
|
ERROR("%s specified but not %s, line %i\n",
|
||||||
"\n");
|
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
|
||||||
|
param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,19 +209,10 @@ static char * authString(char * header, char * user, char * password) {
|
|||||||
static InputStreamHTTPData * newInputStreamHTTPData() {
|
static InputStreamHTTPData * newInputStreamHTTPData() {
|
||||||
InputStreamHTTPData * ret = malloc(sizeof(InputStreamHTTPData));
|
InputStreamHTTPData * ret = malloc(sizeof(InputStreamHTTPData));
|
||||||
|
|
||||||
if(getConf()[CONF_HTTP_PROXY_HOST]) {
|
if(proxyHost) {
|
||||||
ret->proxyHost = getConf()[CONF_HTTP_PROXY_HOST];
|
ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword);
|
||||||
DEBUG(__FILE__ ": Proxy host %s\n", ret->proxyHost);
|
|
||||||
ret->proxyPort = atoi(getConf()[CONF_HTTP_PROXY_PORT]);
|
|
||||||
DEBUG(__FILE__ ": Proxy port %i\n", ret->proxyPort);
|
|
||||||
ret->proxyAuth = proxyAuthString(
|
|
||||||
getConf()[CONF_HTTP_PROXY_USER],
|
|
||||||
getConf()[CONF_HTTP_PROXY_PASSWORD]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret->proxyHost = NULL;
|
|
||||||
ret->proxyAuth = NULL;
|
|
||||||
}
|
}
|
||||||
|
else ret->proxyAuth = NULL;
|
||||||
|
|
||||||
ret->httpAuth = NULL;
|
ret->httpAuth = NULL;
|
||||||
ret->host = NULL;
|
ret->host = NULL;
|
||||||
@ -299,7 +311,7 @@ static int parseUrl(InputStreamHTTPData * data, char * url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* fetch the path */
|
/* fetch the path */
|
||||||
if(data->proxyHost) data->path = strdup(url);
|
if(proxyHost) data->path = strdup(url);
|
||||||
else data->path = strdup(slash ? slash : "/");
|
else data->path = strdup(slash ? slash : "/");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -319,9 +331,9 @@ static int initHTTPConnection(InputStream * inStream) {
|
|||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->proxyHost) {
|
if(proxyHost) {
|
||||||
connHost = data->proxyHost;
|
connHost = proxyHost;
|
||||||
connPort = data->proxyPort;
|
connPort = proxyPort;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
connHost = data->host;
|
connHost = data->host;
|
||||||
|
@ -48,11 +48,17 @@
|
|||||||
#define INTERFACE_LIST_OK_MODE_BEGIN "command_list_ok_begin"
|
#define INTERFACE_LIST_OK_MODE_BEGIN "command_list_ok_begin"
|
||||||
#define INTERFACE_LIST_MODE_END "command_list_end"
|
#define INTERFACE_LIST_MODE_END "command_list_end"
|
||||||
#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096
|
#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096
|
||||||
|
#define INTERFACE_TIMEOUT_DEFAULT 60
|
||||||
|
#define INTERFACE_MAX_CONNECTIONS_DEFAULT 10
|
||||||
|
#define INTERFACE_MAX_COMMAND_LIST_DEFAULT (2048*1024)
|
||||||
|
#define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (2048*1024)
|
||||||
|
|
||||||
int interface_max_connections = 0;
|
static int interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT;
|
||||||
int interface_timeout;
|
static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT;
|
||||||
unsigned long long interface_max_command_list_size;
|
static size_t interface_max_command_list_size =
|
||||||
unsigned long long interface_max_output_buffer_size;
|
INTERFACE_MAX_COMMAND_LIST_DEFAULT;
|
||||||
|
static size_t interface_max_output_buffer_size =
|
||||||
|
INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT;
|
||||||
|
|
||||||
typedef struct _Interface {
|
typedef struct _Interface {
|
||||||
char buffer[INTERFACE_MAX_BUFFER_LENGTH+2];
|
char buffer[INTERFACE_MAX_BUFFER_LENGTH+2];
|
||||||
@ -420,33 +426,58 @@ int doIOForInterfaces() {
|
|||||||
void initInterfaces() {
|
void initInterfaces() {
|
||||||
int i;
|
int i;
|
||||||
char * test;
|
char * test;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
interface_timeout = strtol((getConf())[CONF_CONNECTION_TIMEOUT],&test,10);
|
param = getConfigParam(CONF_CONN_TIMEOUT);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
interface_timeout = strtol(param->value,&test,10);
|
||||||
if(*test!='\0' || interface_timeout<=0) {
|
if(*test!='\0' || interface_timeout<=0) {
|
||||||
ERROR("connection timeout \"%s\" is not a positive integer\n",(getConf())[CONF_CONNECTION_TIMEOUT]);
|
ERROR("connection timeout \"%s\" is not a positive "
|
||||||
|
"integer, line %i\n", CONF_CONN_TIMEOUT,
|
||||||
|
param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface_max_connections = strtol((getConf())[CONF_MAX_CONNECTIONS],&test,10);
|
param = getConfigParam(CONF_MAX_CONN);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
interface_max_connections = strtol(param->value, &test, 10);
|
||||||
if(*test!='\0' || interface_max_connections<=0) {
|
if(*test!='\0' || interface_max_connections<=0) {
|
||||||
ERROR("max connections \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_CONNECTIONS]);
|
ERROR("max connections \"%s\" is not a positive integer"
|
||||||
|
", line %i\n", param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface_max_command_list_size = strtoll((getConf())[CONF_MAX_COMMAND_LIST_SIZE],&test,10);
|
param = getConfigParam(CONF_MAX_COMMAND_LIST_SIZE);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
interface_max_command_list_size = strtoll(param->value,
|
||||||
|
&test, 10);
|
||||||
if(*test!='\0' || interface_max_command_list_size<=0) {
|
if(*test!='\0' || interface_max_command_list_size<=0) {
|
||||||
ERROR("max command list size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_COMMAND_LIST_SIZE]);
|
ERROR("max command list size \"%s\" is not a positive "
|
||||||
|
"integer, line %i\n", param->value,
|
||||||
|
param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface_max_output_buffer_size = strtoll((getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE],&test,10);
|
|
||||||
if(*test!='\0' || interface_max_output_buffer_size<=0) {
|
|
||||||
ERROR("max output buffer size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface_max_command_list_size*=1024;
|
interface_max_command_list_size*=1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
param = getConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
interface_max_output_buffer_size = strtoll(param->value, &test,
|
||||||
|
10);
|
||||||
|
if(*test!='\0' || interface_max_output_buffer_size<=0) {
|
||||||
|
ERROR("max output buffer size \"%s\" is not a positive "
|
||||||
|
"integer, line %i\n", param->value,
|
||||||
|
param->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
interface_max_output_buffer_size*=1024;
|
interface_max_output_buffer_size*=1024;
|
||||||
|
}
|
||||||
|
|
||||||
interfaces = malloc(sizeof(Interface)*interface_max_connections);
|
interfaces = malloc(sizeof(Interface)*interface_max_connections);
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ int findInList(List * list,char * key,void ** data) {
|
|||||||
tmpNode = list->nodesArray[cur];
|
tmpNode = list->nodesArray[cur];
|
||||||
cmp = strcmp(tmpNode->key,key);
|
cmp = strcmp(tmpNode->key,key);
|
||||||
if(cmp==0) {
|
if(cmp==0) {
|
||||||
(*data) = tmpNode->data;
|
if(data) *data = tmpNode->data;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if(cmp>0) high = cur;
|
else if(cmp>0) high = cur;
|
||||||
|
@ -88,6 +88,7 @@ void deleteNodeFromList(List * list,ListNode * node);
|
|||||||
* _key_ -> which node is being searched for
|
* _key_ -> which node is being searched for
|
||||||
* _data_ -> a pointer to where data will be placed,
|
* _data_ -> a pointer to where data will be placed,
|
||||||
* _data_ memory should not by allocated or freed
|
* _data_ memory should not by allocated or freed
|
||||||
|
* _data_ can be NULL
|
||||||
* returns 1 if successful, 0 otherwise
|
* returns 1 if successful, 0 otherwise
|
||||||
*/
|
*/
|
||||||
int findInList(List * list, char * key, void ** data);
|
int findInList(List * list, char * key, void ** data);
|
||||||
|
20
src/listen.c
20
src/listen.c
@ -44,6 +44,7 @@
|
|||||||
int listenSocket;
|
int listenSocket;
|
||||||
|
|
||||||
int establish(unsigned short port) {
|
int establish(unsigned short port) {
|
||||||
|
ConfigParam * param;
|
||||||
int allowReuse = ALLOW_REUSE;
|
int allowReuse = ALLOW_REUSE;
|
||||||
int sock;
|
int sock;
|
||||||
struct sockaddr * addrp;
|
struct sockaddr * addrp;
|
||||||
@ -61,7 +62,9 @@ int establish(unsigned short port) {
|
|||||||
sin.sin_port = htons(port);
|
sin.sin_port = htons(port);
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
|
|
||||||
if(strcmp((getConf())[CONF_BIND_TO_ADDRESS],"any")==0) {
|
param = getConfigParam(CONF_BIND_TO_ADDRESS);
|
||||||
|
|
||||||
|
if(!param || 0==strcmp(param->value, "any")==0) {
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if(ipv6Supported()) {
|
if(ipv6Supported()) {
|
||||||
sin6.sin6_addr = in6addr_any;
|
sin6.sin6_addr = in6addr_any;
|
||||||
@ -78,9 +81,9 @@ int establish(unsigned short port) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct hostent * he;
|
struct hostent * he;
|
||||||
if(!(he = gethostbyname((getConf())[CONF_BIND_TO_ADDRESS]))) {
|
if(!(he = gethostbyname(param->value))) {
|
||||||
ERROR("can't lookup host \"%s\"\n",
|
ERROR("can't lookup host \"%s\" at line %i\n",
|
||||||
(getConf())[CONF_BIND_TO_ADDRESS]);
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
switch(he->h_addrtype) {
|
switch(he->h_addrtype) {
|
||||||
@ -88,8 +91,8 @@ int establish(unsigned short port) {
|
|||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if(!ipv6Supported()) {
|
if(!ipv6Supported()) {
|
||||||
ERROR("no IPv6 support, but a IPv6 address "
|
ERROR("no IPv6 support, but a IPv6 address "
|
||||||
"found for \"%s\"\n",
|
"found for \"%s\" at line %i\n",
|
||||||
(getConf())[CONF_BIND_TO_ADDRESS]);
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
bcopy((char *)he->h_addr,(char *)
|
bcopy((char *)he->h_addr,(char *)
|
||||||
@ -105,8 +108,9 @@ int establish(unsigned short port) {
|
|||||||
addrlen = sizeof(struct sockaddr_in);
|
addrlen = sizeof(struct sockaddr_in);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR("address type for \"%s\" is not IPv4 or IPv6\n",
|
ERROR("address type for \"%s\" is not IPv4 or IPv6 "
|
||||||
(getConf())[CONF_BIND_TO_ADDRESS]);
|
"at line %i\n",
|
||||||
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/log.c
16
src/log.c
@ -32,16 +32,24 @@ short warningFlushed = 0;
|
|||||||
static char * warningBuffer = NULL;
|
static char * warningBuffer = NULL;
|
||||||
|
|
||||||
void initLog() {
|
void initLog() {
|
||||||
if(strcmp(getConf()[CONF_LOG_LEVEL],"default")==0) {
|
ConfigParam * param = getConfigParam(CONF_LOG_LEVEL);
|
||||||
|
|
||||||
|
if(!param) return;
|
||||||
|
|
||||||
|
if(0 == strcmp(param->value, "default")) {
|
||||||
if(logLevel<LOG_LEVEL_LOW) logLevel = LOG_LEVEL_LOW;
|
if(logLevel<LOG_LEVEL_LOW) logLevel = LOG_LEVEL_LOW;
|
||||||
}
|
}
|
||||||
else if(strcmp(getConf()[CONF_LOG_LEVEL],"secure")==0) {
|
else if(0 == strcmp(param->value, "secure")) {
|
||||||
if(logLevel<LOG_LEVEL_SECURE) logLevel = LOG_LEVEL_SECURE;
|
if(logLevel<LOG_LEVEL_SECURE) logLevel = LOG_LEVEL_SECURE;
|
||||||
}
|
}
|
||||||
else if(strcmp(getConf()[CONF_LOG_LEVEL],"verbose")==0) {
|
else if(0 == strcmp(param->value, "verbose")) {
|
||||||
if(logLevel<LOG_LEVEL_DEBUG) logLevel = LOG_LEVEL_DEBUG;
|
if(logLevel<LOG_LEVEL_DEBUG) logLevel = LOG_LEVEL_DEBUG;
|
||||||
}
|
}
|
||||||
else ERROR("unknown log level \"%s\"\n",getConf()[CONF_LOG_LEVEL]);
|
else {
|
||||||
|
ERROR("unknown log level \"%s\" at line %i\n",
|
||||||
|
param->value, param->line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BUFFER_LENGTH 4096
|
#define BUFFER_LENGTH 4096
|
||||||
|
35
src/main.c
35
src/main.c
@ -165,9 +165,12 @@ void parseOptions(int argc, char ** argv, Options * options) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(argcLeft<=2) {
|
else if(argcLeft<=2) {
|
||||||
char ** conf = NULL;
|
int conf = 0;
|
||||||
if(argcLeft==2) conf = readConf(argv[argc-1]);
|
if(argcLeft==2) {
|
||||||
if(argcLeft==1) {
|
readConf(argv[argc-1]);
|
||||||
|
conf = 1;
|
||||||
|
}
|
||||||
|
else if(argcLeft==1) {
|
||||||
FILE * fp;
|
FILE * fp;
|
||||||
char * homedir = getenv("HOME");
|
char * homedir = getenv("HOME");
|
||||||
char userfile[MAXPATHLEN+1] = "";
|
char userfile[MAXPATHLEN+1] = "";
|
||||||
@ -179,23 +182,27 @@ void parseOptions(int argc, char ** argv, Options * options) {
|
|||||||
}
|
}
|
||||||
if(strlen(userfile) && (fp=fopen(userfile,"r"))) {
|
if(strlen(userfile) && (fp=fopen(userfile,"r"))) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
conf = readConf(userfile);
|
readConf(userfile);
|
||||||
|
conf = 1;
|
||||||
}
|
}
|
||||||
else if((fp=fopen(SYSTEM_CONFIG_FILE_LOCATION,"r"))) {
|
else if((fp=fopen(SYSTEM_CONFIG_FILE_LOCATION,"r"))) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
conf = readConf(SYSTEM_CONFIG_FILE_LOCATION);
|
readConf(SYSTEM_CONFIG_FILE_LOCATION);
|
||||||
|
conf = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf) {
|
if(conf) {
|
||||||
options->portStr = conf[CONF_PORT];
|
options->portStr = forceAndGetConfigParamValue(
|
||||||
options->musicDirArg = conf[CONF_MUSIC_DIRECTORY];
|
CONF_PORT);
|
||||||
options->playlistDirArg = conf[CONF_PLAYLIST_DIRECTORY];
|
options->musicDirArg =
|
||||||
options->logFile = conf[CONF_LOG_FILE];
|
parseConfigFilePath(CONF_MUSIC_DIR, 1);
|
||||||
options->errorFile = conf[CONF_ERROR_FILE];
|
options->playlistDirArg =
|
||||||
options->usr = conf[CONF_USER];
|
parseConfigFilePath(CONF_PLAYLIST_DIR, 1);
|
||||||
if(conf[CONF_DB_FILE]) {
|
options->logFile = parseConfigFilePath(CONF_LOG_FILE,1);
|
||||||
options->dbFile = conf[CONF_DB_FILE];
|
options->errorFile =
|
||||||
}
|
parseConfigFilePath(CONF_ERROR_FILE, 1);
|
||||||
|
options->usr = parseConfigFilePath(CONF_USER, 0);
|
||||||
|
options->dbFile = parseConfigFilePath(CONF_DB_FILE, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ void initPaths(char * playlistDirArg, char * musicDirArg) {
|
|||||||
char * charset = NULL;
|
char * charset = NULL;
|
||||||
char * originalLocale;
|
char * originalLocale;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
playlistDir = prependCwdToPathDup(playlistDirArg);
|
playlistDir = prependCwdToPathDup(playlistDirArg);
|
||||||
if((stat(playlistDir,&st))<0) {
|
if((stat(playlistDir,&st))<0) {
|
||||||
@ -135,8 +136,10 @@ void initPaths(char * playlistDirArg, char * musicDirArg) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConf()[CONF_FS_CHARSET]) {
|
param = getConfigParam(CONF_FS_CHARSET);
|
||||||
charset = strdup(getConf()[CONF_FS_CHARSET]);
|
|
||||||
|
if(param) {
|
||||||
|
charset = strdup(param->value);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_LOCALE
|
#ifdef HAVE_LOCALE
|
||||||
#ifdef HAVE_LANGINFO_CODESET
|
#ifdef HAVE_LANGINFO_CODESET
|
||||||
@ -296,5 +299,3 @@ char * prependCwdToPathDup(char * path) {
|
|||||||
|
|
||||||
return realloc(ret,len+1);
|
return realloc(ret,len+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
|
|
||||||
|
@ -69,56 +69,53 @@ unsigned int parsePermissions(char * string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initPermissions() {
|
void initPermissions() {
|
||||||
char * passwordSets;
|
|
||||||
char * nextSet;
|
|
||||||
char * temp;
|
char * temp;
|
||||||
char * cp1;
|
|
||||||
char * cp2;
|
char * cp2;
|
||||||
char * password;
|
char * password;
|
||||||
unsigned int * permission;
|
unsigned int * permission;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
permission_passwords = makeList(free);
|
permission_passwords = makeList(free);
|
||||||
|
|
||||||
permission_default = PERMISSION_READ | PERMISSION_ADD |
|
permission_default = PERMISSION_READ | PERMISSION_ADD |
|
||||||
PERMISSION_CONTROL | PERMISSION_ADMIN;
|
PERMISSION_CONTROL | PERMISSION_ADMIN;
|
||||||
|
|
||||||
if(getConf()[CONF_DEFAULT_PERMISSIONS]) {
|
param = getNextConfigParam(CONF_PASSWORD, NULL);
|
||||||
permission_default = parsePermissions(
|
|
||||||
getConf()[CONF_DEFAULT_PERMISSIONS]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!getConf()[CONF_PASSWORD]) return;
|
if(param) {
|
||||||
|
permission_default = 0;
|
||||||
|
|
||||||
if(!getConf()[CONF_DEFAULT_PERMISSIONS]) permission_default = 0;
|
do {
|
||||||
|
if(!strstr(param->value, PERMISSION_PASSWORD_CHAR)) {
|
||||||
passwordSets = strdup(getConf()[CONF_PASSWORD]);
|
ERROR("\"%s\" not found in password string "
|
||||||
|
"\"%s\", line %i\n",
|
||||||
nextSet = strtok_r(passwordSets,CONF_CAT_CHAR,&cp1);
|
|
||||||
while(nextSet && strlen(nextSet)) {
|
|
||||||
if(!strstr(nextSet,PERMISSION_PASSWORD_CHAR)) {
|
|
||||||
ERROR("\"%s\" not found in password string \"%s\"\n",
|
|
||||||
PERMISSION_PASSWORD_CHAR,
|
PERMISSION_PASSWORD_CHAR,
|
||||||
nextSet);
|
param->value,
|
||||||
|
param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(temp = strtok_r(nextSet,PERMISSION_PASSWORD_CHAR,&cp2))) {
|
if(!(temp = strtok_r(param->value,
|
||||||
|
PERMISSION_PASSWORD_CHAR,&cp2))) {
|
||||||
ERROR("something weird just happend in permission.c\n");
|
ERROR("something weird just happend in permission.c\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
password = temp;
|
password = temp;
|
||||||
|
|
||||||
permission = malloc(sizeof(unsigned int));
|
permission = malloc(sizeof(unsigned int));
|
||||||
*permission = parsePermissions(strtok_r(NULL,"",&cp2));
|
*permission = parsePermissions(strtok_r(NULL,"",&cp2));
|
||||||
|
|
||||||
insertInList(permission_passwords,password,permission);
|
insertInList(permission_passwords,password,permission);
|
||||||
|
} while((param = getNextConfigParam(CONF_PASSWORD, param)));
|
||||||
nextSet = strtok_r(NULL,CONF_CAT_CHAR,&cp1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sortList(permission_passwords);
|
param = getConfigParam(CONF_DEFAULT_PERMS);
|
||||||
|
|
||||||
free(passwordSets);
|
if(param) permission_default = parsePermissions(param->value);
|
||||||
|
|
||||||
|
sortList(permission_passwords);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getPermissionFromPassword(char * password, unsigned int * permission) {
|
int getPermissionFromPassword(char * password, unsigned int * permission) {
|
||||||
|
@ -30,23 +30,32 @@
|
|||||||
int buffered_before_play;
|
int buffered_before_play;
|
||||||
int buffered_chunks;
|
int buffered_chunks;
|
||||||
|
|
||||||
|
#define DEFAULT_BUFFER_SIZE 2048
|
||||||
|
#define DEFAULT_BUFFER_BEFORE_PLAY 25
|
||||||
|
|
||||||
PlayerData * playerData_pd;
|
PlayerData * playerData_pd;
|
||||||
|
|
||||||
void initPlayerData() {
|
void initPlayerData() {
|
||||||
float perc;
|
float perc = DEFAULT_BUFFER_BEFORE_PLAY;
|
||||||
char * test;
|
char * test;
|
||||||
int shmid;
|
int shmid;
|
||||||
int crossfade = 0;
|
int crossfade = 0;
|
||||||
size_t bufferSize;
|
size_t bufferSize = DEFAULT_BUFFER_SIZE;
|
||||||
size_t allocationSize;
|
size_t allocationSize;
|
||||||
OutputBuffer * buffer;
|
OutputBuffer * buffer;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
bufferSize = strtol(getConf()[CONF_BUFFER_SIZE],&test,10);
|
param = getConfigParam(CONF_AUDIO_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
bufferSize = strtol(param->value, &test, 10);
|
||||||
if(*test!='\0' || bufferSize<=0) {
|
if(*test!='\0' || bufferSize<=0) {
|
||||||
ERROR("buffer size \"%s\" is not a positive integer\n",
|
ERROR("buffer size \"%s\" is not a positive integer, "
|
||||||
getConf()[CONF_BUFFER_SIZE]);
|
"line %i\n", param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bufferSize*=1024;
|
bufferSize*=1024;
|
||||||
|
|
||||||
buffered_chunks = bufferSize/CHUNK_SIZE;
|
buffered_chunks = bufferSize/CHUNK_SIZE;
|
||||||
@ -56,13 +65,18 @@ void initPlayerData() {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
perc = strtod((getConf())[CONF_BUFFER_BEFORE_PLAY],&test);
|
param = getConfigParam(CONF_BUFFER_BEFORE_PLAY);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
perc = strtod(param->value, &test);
|
||||||
if(*test!='%' || perc<0 || perc>100) {
|
if(*test!='%' || perc<0 || perc>100) {
|
||||||
ERROR("buffered before play \"%s\" is not a positive "
|
ERROR("buffered before play \"%s\" is not a positive "
|
||||||
"percentage and less than 100 percent\n",
|
"percentage and less than 100 percent, line %i"
|
||||||
(getConf())[CONF_BUFFER_BEFORE_PLAY]);
|
"\n", param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buffered_before_play = (perc/100)*buffered_chunks;
|
buffered_before_play = (perc/100)*buffered_chunks;
|
||||||
if(buffered_before_play>buffered_chunks) {
|
if(buffered_before_play>buffered_chunks) {
|
||||||
buffered_before_play = buffered_chunks;
|
buffered_before_play = buffered_chunks;
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
|
|
||||||
#define PLAYLIST_HASH_MULT 4
|
#define PLAYLIST_HASH_MULT 4
|
||||||
|
|
||||||
|
#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16)
|
||||||
|
#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0
|
||||||
|
|
||||||
typedef struct _Playlist {
|
typedef struct _Playlist {
|
||||||
Song ** songs;
|
Song ** songs;
|
||||||
/* holds version a song was modified on */
|
/* holds version a song was modified on */
|
||||||
@ -77,13 +80,13 @@ typedef struct _Playlist {
|
|||||||
|
|
||||||
static Playlist playlist;
|
static Playlist playlist;
|
||||||
static int playlist_state = PLAYLIST_STATE_STOP;
|
static int playlist_state = PLAYLIST_STATE_STOP;
|
||||||
static int playlist_max_length;
|
static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH;
|
||||||
static int playlist_stopOnError;
|
static int playlist_stopOnError;
|
||||||
static int playlist_errorCount = 0;
|
static int playlist_errorCount = 0;
|
||||||
static int playlist_queueError;
|
static int playlist_queueError;
|
||||||
static int playlist_noGoToNext = 0;
|
static int playlist_noGoToNext = 0;
|
||||||
|
|
||||||
static int playlist_saveAbsolutePaths;
|
static int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
|
||||||
|
|
||||||
static char * playlist_stateFile = NULL;
|
static char * playlist_stateFile = NULL;
|
||||||
|
|
||||||
@ -128,6 +131,7 @@ static void incrPlaylistCurrent() {
|
|||||||
void initPlaylist() {
|
void initPlaylist() {
|
||||||
char * test;
|
char * test;
|
||||||
int i;
|
int i;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
playlist.length = 0;
|
playlist.length = 0;
|
||||||
playlist.repeat = 0;
|
playlist.repeat = 0;
|
||||||
@ -136,27 +140,33 @@ void initPlaylist() {
|
|||||||
playlist.queued = -1;
|
playlist.queued = -1;
|
||||||
playlist.current = -1;
|
playlist.current = -1;
|
||||||
|
|
||||||
playlist_max_length = strtol((getConf())[CONF_MAX_PLAYLIST_LENGTH],&test,10);
|
param = getConfigParam(CONF_MAX_PLAYLIST_LENGTH);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
playlist_max_length = strtol(param->value, &test, 10);
|
||||||
if(*test!='\0') {
|
if(*test!='\0') {
|
||||||
ERROR("max playlist length \"%s\" is not an integer\n",
|
ERROR("max playlist length \"%s\" is not an integer, "
|
||||||
(getConf())[CONF_MAX_PLAYLIST_LENGTH]);
|
"line %i\n", param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(strcmp("yes",(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS])
|
param = getConfigParam(CONF_SAVE_ABSOLUTE_PATHS);
|
||||||
==0) {
|
|
||||||
|
if(param) {
|
||||||
|
if(0 == strcmp("yes", param->value) ) {
|
||||||
playlist_saveAbsolutePaths = 1;
|
playlist_saveAbsolutePaths = 1;
|
||||||
}
|
}
|
||||||
else if(strcmp("no",(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS])
|
else if(0 == strcmp("no", param->value) ) {
|
||||||
==0) {
|
|
||||||
playlist_saveAbsolutePaths = 0;
|
playlist_saveAbsolutePaths = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ERROR("save_absolute_paths_in_playlist \"%s\" is not yes or "
|
ERROR("%s \"%s\" is not yes or no, line %i"
|
||||||
"no\n",
|
CONF_SAVE_ABSOLUTE_PATHS,
|
||||||
(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS]);
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
playlist.songs = malloc(sizeof(Song *)*playlist_max_length);
|
playlist.songs = malloc(sizeof(Song *)*playlist_max_length);
|
||||||
playlist.songMod = malloc(sizeof(mpd_uint32)*playlist_max_length);
|
playlist.songMod = malloc(sizeof(mpd_uint32)*playlist_max_length);
|
||||||
@ -169,9 +179,7 @@ void initPlaylist() {
|
|||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
if(getConf()[CONF_STATE_FILE]) {
|
playlist_stateFile = getConfigParamValue(CONF_STATE_FILE);
|
||||||
playlist_stateFile = getConf()[CONF_STATE_FILE];
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0; i<playlist_max_length*PLAYLIST_HASH_MULT; i++) {
|
for(i=0; i<playlist_max_length*PLAYLIST_HASH_MULT; i++) {
|
||||||
playlist.idToPosition[i] = -1;
|
playlist.idToPosition[i] = -1;
|
||||||
|
@ -32,34 +32,38 @@ static int replayGainState = REPLAYGAIN_OFF;
|
|||||||
static float replayGainPreamp = 1.0;
|
static float replayGainPreamp = 1.0;
|
||||||
|
|
||||||
void initReplayGainState() {
|
void initReplayGainState() {
|
||||||
if(!getConf()[CONF_REPLAYGAIN]) return;
|
ConfigParam * param = getConfigParam(CONF_REPLAYGAIN);
|
||||||
|
|
||||||
if(strcmp(getConf()[CONF_REPLAYGAIN],"track")==0) {
|
if(!param) return;
|
||||||
|
|
||||||
|
if(strcmp(param->value, "track") == 0) {
|
||||||
replayGainState = REPLAYGAIN_TRACK;
|
replayGainState = REPLAYGAIN_TRACK;
|
||||||
}
|
}
|
||||||
else if(strcmp(getConf()[CONF_REPLAYGAIN],"album")==0) {
|
else if(strcmp(param->value, "album") == 0) {
|
||||||
replayGainState = REPLAYGAIN_ALBUM;
|
replayGainState = REPLAYGAIN_ALBUM;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ERROR("replaygain value \"%s\" is invalid\n",
|
ERROR("replaygain value \"%s\" at line %i is invalid\n",
|
||||||
getConf()[CONF_REPLAYGAIN]);
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConf()[CONF_REPLAYGAIN_PREAMP]) {
|
param = getConfigParam(CONF_REPLAYGAIN_PREAMP);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
char * test;
|
char * test;
|
||||||
float f = strtod(getConf()[CONF_REPLAYGAIN_PREAMP], &test);
|
float f = strtod(param->value, &test);
|
||||||
|
|
||||||
if(*test != '\0') {
|
if(*test != '\0') {
|
||||||
ERROR("Replaygain preamp \"%s\" is not a number\n",
|
ERROR("Replaygain preamp \"%s\" is not a number at "
|
||||||
getConf()[CONF_REPLAYGAIN_PREAMP]);
|
"line %i\n", param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(f < -15 || f > 15) {
|
if(f < -15 || f > 15) {
|
||||||
ERROR("Replaygain preamp \"%s\" is not between -15 and"
|
ERROR("Replaygain preamp \"%s\" is not between -15 and"
|
||||||
"15\n",
|
"15 at line %i\n",
|
||||||
getConf()[CONF_REPLAYGAIN_PREAMP]);
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/tag.c
12
src/tag.c
@ -93,18 +93,6 @@ char * getID3Info(struct id3_tag * tag, char * id) {
|
|||||||
utf8 = id3_ucs4_utf8duplicate(ucs4);
|
utf8 = id3_ucs4_utf8duplicate(ucs4);
|
||||||
if(!utf8) return NULL;
|
if(!utf8) return NULL;
|
||||||
|
|
||||||
if(getConf()[CONF_ID3V1_ENCODING]
|
|
||||||
&& (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1)) {
|
|
||||||
|
|
||||||
char* isostr;
|
|
||||||
setCharSetConversion("ISO-8859-1", "UTF-8");
|
|
||||||
isostr = convStrDup(utf8);
|
|
||||||
free(utf8);
|
|
||||||
setCharSetConversion("UTF-8", getConf()[CONF_ID3V1_ENCODING]);
|
|
||||||
utf8 = convStrDup(isostr);
|
|
||||||
free(isostr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return utf8;
|
return utf8;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
61
src/volume.c
61
src/volume.c
@ -45,8 +45,21 @@
|
|||||||
#define VOLUME_MIXER_ALSA_DEFAULT "default"
|
#define VOLUME_MIXER_ALSA_DEFAULT "default"
|
||||||
#define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "Master"
|
#define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "Master"
|
||||||
|
|
||||||
int volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
|
#ifndef NO_OSS_MIXER
|
||||||
char * volume_mixerDevice;
|
#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_OSS
|
||||||
|
#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_OSS_DEFAULT
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_ALSA
|
||||||
|
#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_ALSA
|
||||||
|
#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_ALSA_DEFAULT
|
||||||
|
#else
|
||||||
|
#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_SOFTWARE
|
||||||
|
#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_SOFTWARE_DEFAULT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int volume_mixerType = VOLUME_MIXER_TYPE_DEFAULT;
|
||||||
|
char * volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT;
|
||||||
|
|
||||||
int volume_softwareSet = 100;
|
int volume_softwareSet = 100;
|
||||||
|
|
||||||
@ -66,13 +79,16 @@ int volume_alsaSet = -1;
|
|||||||
#ifndef NO_OSS_MIXER
|
#ifndef NO_OSS_MIXER
|
||||||
int prepOssMixer(char * device) {
|
int prepOssMixer(char * device) {
|
||||||
int devmask = 0;
|
int devmask = 0;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
if((volume_ossFd = open(device,O_RDONLY))<0) {
|
if((volume_ossFd = open(device,O_RDONLY))<0) {
|
||||||
WARNING("unable to open oss mixer \"%s\"\n",device);
|
WARNING("unable to open oss mixer \"%s\"\n",device);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getConf()[CONF_MIXER_CONTROL]) {
|
param = getConfigParam(CONF_MIXER_CONTROL);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
|
char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
|
||||||
char * dup;
|
char * dup;
|
||||||
int i,j;
|
int i,j;
|
||||||
@ -88,7 +104,7 @@ int prepOssMixer(char * device) {
|
|||||||
/* eliminate spaces at the end */
|
/* eliminate spaces at the end */
|
||||||
j = strlen(dup)-1;
|
j = strlen(dup)-1;
|
||||||
while(j>=0 && dup[j]==' ') dup[j--] = '\0';
|
while(j>=0 && dup[j]==' ') dup[j--] = '\0';
|
||||||
if(strcasecmp(dup,getConf()[CONF_MIXER_CONTROL])==0) {
|
if(strcasecmp(dup, param->value)==0) {
|
||||||
free(dup);
|
free(dup);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -96,14 +112,14 @@ int prepOssMixer(char * device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(i>=SOUND_MIXER_NRDEVICES) {
|
if(i>=SOUND_MIXER_NRDEVICES) {
|
||||||
WARNING("mixer control \"%s\" not found\n",
|
WARNING("mixer control \"%s\" not found at line %i\n",
|
||||||
getConf()[CONF_MIXER_CONTROL]);
|
param->value, param->line);
|
||||||
close(volume_ossFd);
|
close(volume_ossFd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if(!( ( 1 << i ) & devmask )) {
|
else if(!( ( 1 << i ) & devmask )) {
|
||||||
WARNING("mixer control \"%s\" not usable\n",
|
WARNING("mixer control \"%s\" not usable at line %i\n",
|
||||||
getConf()[CONF_MIXER_CONTROL]);
|
param->value, param->line);
|
||||||
close(volume_ossFd);
|
close(volume_ossFd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -173,6 +189,7 @@ int prepAlsaMixer(char * card) {
|
|||||||
int err;
|
int err;
|
||||||
snd_mixer_elem_t * elem;
|
snd_mixer_elem_t * elem;
|
||||||
char * controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT;
|
char * controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT;
|
||||||
|
ConfigParam * param;
|
||||||
|
|
||||||
if((err = snd_mixer_open(&volume_alsaMixerHandle,0))<0) {
|
if((err = snd_mixer_open(&volume_alsaMixerHandle,0))<0) {
|
||||||
WARNING("problems opening alsa mixer: %s\n",snd_strerror(err));
|
WARNING("problems opening alsa mixer: %s\n",snd_strerror(err));
|
||||||
@ -201,8 +218,11 @@ int prepAlsaMixer(char * card) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
elem = snd_mixer_first_elem(volume_alsaMixerHandle);
|
elem = snd_mixer_first_elem(volume_alsaMixerHandle);
|
||||||
if(getConf()[CONF_MIXER_CONTROL]) {
|
|
||||||
controlName = getConf()[CONF_MIXER_CONTROL];
|
param = getConfigParam(CONF_MIXER_CONTROL);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
controlName = param->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(elem) {
|
while(elem) {
|
||||||
@ -340,29 +360,37 @@ void finishVolume() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initVolume() {
|
void initVolume() {
|
||||||
|
ConfigParam * param = getConfigParam(CONF_MIXER_TYPE);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
if(0);
|
if(0);
|
||||||
#ifdef HAVE_ALSA
|
#ifdef HAVE_ALSA
|
||||||
else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_ALSA)==0) {
|
else if(strcmp(param->value, VOLUME_MIXER_ALSA)==0) {
|
||||||
volume_mixerType = VOLUME_MIXER_TYPE_ALSA;
|
volume_mixerType = VOLUME_MIXER_TYPE_ALSA;
|
||||||
volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT;
|
volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef NO_OSS_MIXER
|
#ifndef NO_OSS_MIXER
|
||||||
else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_OSS)==0) {
|
else if(strcmp(param->value, VOLUME_MIXER_OSS)==0) {
|
||||||
volume_mixerType = VOLUME_MIXER_TYPE_OSS;
|
volume_mixerType = VOLUME_MIXER_TYPE_OSS;
|
||||||
volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT;
|
volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_SOFTWARE)==0) {
|
else if(strcmp(param->value ,VOLUME_MIXER_SOFTWARE)==0) {
|
||||||
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
|
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
|
||||||
volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT;
|
volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ERROR("unknown mixer type: %s\n",(getConf())[CONF_MIXER_TYPE]);
|
ERROR("unknown mixer type %s at line %i\n",
|
||||||
|
param->value, param->line);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if(strlen((getConf())[CONF_MIXER_DEVICE])) {
|
}
|
||||||
volume_mixerDevice = (getConf())[CONF_MIXER_DEVICE];
|
|
||||||
|
param = getConfigParam(CONF_MIXER_DEVICE);
|
||||||
|
|
||||||
|
if(param) {
|
||||||
|
volume_mixerDevice = param->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,4 +459,3 @@ int changeVolumeLevel(FILE * fp, int change, int rel) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
|
|
||||||
|
Loading…
Reference in New Issue
Block a user