if no audioOutput specified, we no attempt to detect if there exists a usable oss or alsa device
git-svn-id: https://svn.musicpd.org/mpd/trunk@3057 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
		| @@ -79,7 +79,9 @@ void initAudioDriver() { | ||||
| 		myAudioDevicesEnabled[i] = 1; | ||||
| 	} | ||||
|  | ||||
| 	while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) { | ||||
| 	param = getNextConfigParam(CONF_AUDIO_OUTPUT, param); | ||||
|  | ||||
| 	do { | ||||
| 		if(audioOutputArraySize == AUDIO_MAX_DEVICES) { | ||||
| 			ERROR("only up to 255 audio output devices are " | ||||
| 					"supported"); | ||||
| @@ -93,12 +95,12 @@ void initAudioDriver() { | ||||
| 	 | ||||
| 		audioOutputArray[i] = newAudioOutput(param); | ||||
|  | ||||
| 		if(!audioOutputArray[i]) { | ||||
| 		if(!audioOutputArray[i] && param) { | ||||
| 			ERROR("problems configuring output device defined at " | ||||
| 					"line %i\n", param->line); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	} | ||||
| 	} while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))); | ||||
| } | ||||
|  | ||||
| void getOutputAudioFormat(AudioFormat * inAudioFormat,  | ||||
|   | ||||
| @@ -48,55 +48,87 @@ AudioOutput * newAudioOutput(ConfigParam * param) { | ||||
| 	char * name = NULL; | ||||
| 	char * format = NULL; | ||||
| 	char * type = NULL; | ||||
| 	BlockParam * bp; | ||||
| 	BlockParam * bp = NULL; | ||||
| 	AudioOutputPlugin * plugin = NULL; | ||||
|  | ||||
| 	getBlockParam(AUDIO_OUTPUT_NAME, name, 1); | ||||
| 	getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); | ||||
| 	if(param) { | ||||
| 		getBlockParam(AUDIO_OUTPUT_NAME, name, 1); | ||||
| 		getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); | ||||
|  | ||||
| 	if(findInList(audioOutputPluginList, type, &data)) { | ||||
| 		AudioOutputPlugin * plugin = (AudioOutputPlugin *) data; | ||||
| 		ret = malloc(sizeof(AudioOutput)); | ||||
| 		ret->name = strdup(name); | ||||
| 		ret->type = strdup(type); | ||||
| 		ret->finishDriverFunc = plugin->finishDriverFunc; | ||||
| 		ret->openDeviceFunc = plugin->openDeviceFunc; | ||||
| 		ret->playFunc = plugin->playFunc; | ||||
| 		ret->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc; | ||||
| 		ret->closeDeviceFunc = plugin->closeDeviceFunc; | ||||
| 		ret->sendMetdataFunc = plugin->sendMetdataFunc; | ||||
| 		ret->open = 0; | ||||
| 		if(!findInList(audioOutputPluginList, type, &data)) { | ||||
| 			ERROR("couldn't find audio output plugin for type " | ||||
| 					"\"%s\" at line %i\n", type,  | ||||
| 					param->line); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
|  | ||||
| 		ret->convertAudioFormat = 0; | ||||
| 		ret->sameInAndOutFormats = 0; | ||||
| 		ret->convBuffer = NULL; | ||||
| 		ret->convBufferLen = 0; | ||||
|  | ||||
| 		memset(&ret->inAudioFormat, 0, sizeof(AudioFormat)); | ||||
| 		memset(&ret->outAudioFormat, 0, sizeof(AudioFormat)); | ||||
| 		memset(&ret->reqAudioFormat, 0, sizeof(AudioFormat)); | ||||
|  | ||||
| 		getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0); | ||||
| 		plugin = (AudioOutputPlugin *) data; | ||||
| 	 | ||||
| 		if(format) { | ||||
| 			ret->convertAudioFormat = 1; | ||||
|  | ||||
| 			if(0 != parseAudioConfig(&ret->reqAudioFormat, format)) | ||||
| 			{ | ||||
| 		        	ERROR("error parsing format at line %i\n",  | ||||
| 	        		ERROR("error parsing format at line %i\n",  | ||||
| 						bp->line); | ||||
| 		        	exit(EXIT_FAILURE); | ||||
| 		        } | ||||
| 		} | ||||
|  | ||||
| 		if(plugin->initDriverFunc(ret, param) != 0) { | ||||
| 			free(ret); | ||||
| 			ret = NULL; | ||||
| 	        		exit(EXIT_FAILURE); | ||||
| 	        	} | ||||
| 		} | ||||
| 	} | ||||
| 	else { | ||||
| 		ERROR("couldn't find audio output plugin for type \"%s\" at " | ||||
| 				"line %i\n", type, param->line); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 		ListNode * node = audioOutputPluginList->firstNode; | ||||
|  | ||||
| 		WARNING("No \"%s\" defined in config file\n",  | ||||
| 				CONF_AUDIO_OUTPUT); | ||||
| 		WARNING("Attempt to detect audio output device\n"); | ||||
|  | ||||
| 		while(node) { | ||||
| 			plugin = (AudioOutputPlugin *) node->data; | ||||
| 			if(plugin->testDefaultDeviceFunc) { | ||||
| 				WARNING("Attempting to detect a %s audio " | ||||
| 						"device\n", plugin->name); | ||||
| 				if(plugin->testDefaultDeviceFunc() == 0) { | ||||
| 					WARNING("Successfully detected a %s " | ||||
| 							"audio device\n", | ||||
| 							plugin->name); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			node = node->nextNode; | ||||
| 		} | ||||
|  | ||||
| 		if(!node) { | ||||
| 			WARNING("Unable to detect an audio device\n"); | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		name = "default detected output"; | ||||
| 		type = plugin->name; | ||||
| 	} | ||||
|  | ||||
| 	ret = malloc(sizeof(AudioOutput)); | ||||
| 	ret->name = strdup(name); | ||||
| 	ret->type = strdup(type); | ||||
| 	ret->finishDriverFunc = plugin->finishDriverFunc; | ||||
| 	ret->openDeviceFunc = plugin->openDeviceFunc; | ||||
| 	ret->playFunc = plugin->playFunc; | ||||
| 	ret->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc; | ||||
| 	ret->closeDeviceFunc = plugin->closeDeviceFunc; | ||||
| 	ret->sendMetdataFunc = plugin->sendMetdataFunc; | ||||
| 	ret->open = 0; | ||||
|  | ||||
| 	ret->convertAudioFormat = 0; | ||||
| 	ret->sameInAndOutFormats = 0; | ||||
| 	ret->convBuffer = NULL; | ||||
| 	ret->convBufferLen = 0; | ||||
|  | ||||
| 	memset(&ret->inAudioFormat, 0, sizeof(AudioFormat)); | ||||
| 	memset(&ret->outAudioFormat, 0, sizeof(AudioFormat)); | ||||
| 	memset(&ret->reqAudioFormat, 0, sizeof(AudioFormat)); | ||||
|  | ||||
| 	if(plugin->initDriverFunc(ret, param) != 0) { | ||||
| 		free(ret); | ||||
| 		ret = NULL; | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
|   | ||||
| @@ -28,6 +28,8 @@ | ||||
|  | ||||
| typedef struct _AudioOutput AudioOutput; | ||||
|  | ||||
| typedef int (* AudioOutputTestDefaultDeviceFunc) (); | ||||
|  | ||||
| typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput,  | ||||
| 		ConfigParam * param); | ||||
|  | ||||
| @@ -71,6 +73,7 @@ struct _AudioOutput { | ||||
| typedef struct _AudioOutputPlugin { | ||||
| 	char * name; | ||||
|  | ||||
| 	AudioOutputTestDefaultDeviceFunc testDefaultDeviceFunc; | ||||
|         AudioOutputInitDriverFunc initDriverFunc; | ||||
|         AudioOutputFinishDriverFunc finishDriverFunc; | ||||
|         AudioOutputOpenDeviceFunc openDeviceFunc; | ||||
|   | ||||
| @@ -69,7 +69,10 @@ static void freeAlsaData(AlsaData * ad) { | ||||
| } | ||||
|  | ||||
| static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | ||||
| 	BlockParam * bp = getBlockParam(param, "device"); | ||||
| 	BlockParam * bp = NULL; | ||||
|  | ||||
| 	if(param) bp = getBlockParam(param, "device"); | ||||
|  | ||||
| 	AlsaData * ad = newAlsaData(); | ||||
| 	 | ||||
| 	audioOutput->data = ad; | ||||
| @@ -85,6 +88,23 @@ static void alsa_finishDriver(AudioOutput * audioOutput) { | ||||
| 	freeAlsaData(ad); | ||||
| } | ||||
|  | ||||
| static int alsa_testDefault() | ||||
| { | ||||
| 	snd_pcm_t * handle; | ||||
|  | ||||
| 	int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,  | ||||
| 					           SND_PCM_NONBLOCK); | ||||
| 	 | ||||
| 	if(ret) { | ||||
| 		WARNING("Error opening default alsa device: %s\n", | ||||
| 				snd_strerror(-ret)); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	else snd_pcm_close(handle); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int alsa_openDevice(AudioOutput * audioOutput)  | ||||
| { | ||||
| 	AlsaData * ad = audioOutput->data; | ||||
| @@ -313,6 +333,7 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk, | ||||
| AudioOutputPlugin alsaPlugin = | ||||
| { | ||||
| 	"alsa", | ||||
| 	alsa_testDefault, | ||||
| 	alsa_initDriver, | ||||
| 	alsa_finishDriver, | ||||
| 	alsa_openDevice, | ||||
| @@ -332,6 +353,7 @@ AudioOutputPlugin alsaPlugin = | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL /* sendMetadataFunc */ | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -237,6 +237,7 @@ static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk, | ||||
| AudioOutputPlugin aoPlugin =  | ||||
| { | ||||
| 	"ao", | ||||
| 	NULL, | ||||
| 	audioOutputAo_initDriver, | ||||
| 	audioOutputAo_finishDriver, | ||||
| 	audioOutputAo_openDevice, | ||||
| @@ -259,6 +260,7 @@ AudioOutputPlugin aoPlugin = | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -291,10 +291,38 @@ static int oss_statDevice(char * device, int * stErrno) { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | ||||
| 	BlockParam * bp = getBlockParam(param, "device"); | ||||
| 	OssData * od = newOssData(); | ||||
| static int oss_testDefault() { | ||||
| 	int fd; | ||||
|  | ||||
| 	fd = open("/dev/sound/dsp", O_WRONLY); | ||||
|  | ||||
| 	if(fd) { | ||||
| 		close(fd); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	WARNING("Error opening OSS device \"/dev/sound/dsp\": %s\n", | ||||
| 			strerror(errno)); | ||||
|  | ||||
| 	fd = open("/dev/dsp", O_WRONLY); | ||||
|  | ||||
| 	if(fd) { | ||||
| 		close(fd); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	WARNING("Error opening OSS device \"/dev/dsp\": %s\n", | ||||
| 			strerror(errno)); | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | ||||
| 	BlockParam * bp = NULL; | ||||
|  | ||||
| 	if(param) bp = getBlockParam(param, "device"); | ||||
|  | ||||
| 	OssData * od = newOssData(); | ||||
| 	audioOutput->data = od; | ||||
|  | ||||
| 	if(!bp) { | ||||
| @@ -307,8 +335,14 @@ static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | ||||
| 		if(ret[0] == 0) od->device = strdup("/dev/sound/dsp"); | ||||
| 		else if(ret[1] == 0) od->device = strdup("/dev/dsp"); | ||||
| 		else { | ||||
| 			ERROR("Error trying to open default OSS device " | ||||
| 				"specified at line %i\n", param->line); | ||||
| 			if(param) { | ||||
| 				ERROR("Error trying to open default OSS device " | ||||
| 					"specified at line %i\n", param->line); | ||||
| 			} | ||||
| 			else { | ||||
| 				ERROR("Error trying to open default OSS " | ||||
| 						"device\n"); | ||||
| 			} | ||||
|  | ||||
| 			if(ret[0] == ret[1] == OSS_STAT_DOESN_T_EXIST) { | ||||
| 				ERROR("Neither /dev/dsp nor /dev/sound/dsp " | ||||
| @@ -501,6 +535,7 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, | ||||
| AudioOutputPlugin ossPlugin = | ||||
| { | ||||
| 	"oss", | ||||
| 	oss_testDefault, | ||||
| 	oss_initDriver, | ||||
| 	oss_finishDriver, | ||||
| 	oss_openDevice, | ||||
| @@ -521,6 +556,7 @@ AudioOutputPlugin ossPlugin = | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL /* sendMetadataFunc */ | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -597,6 +597,7 @@ static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag) { | ||||
| AudioOutputPlugin shoutPlugin =  | ||||
| { | ||||
| 	"shout", | ||||
| 	NULL, | ||||
| 	myShout_initDriver, | ||||
| 	myShout_finishDriver, | ||||
| 	myShout_openDevice, | ||||
| @@ -617,6 +618,7 @@ AudioOutputPlugin shoutPlugin = | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -68,9 +68,12 @@ void bufferWarning(char * format, ... ) { | ||||
|  | ||||
| 	va_end(arglist); | ||||
| } | ||||
|  | ||||
| void flushWarningLog() { | ||||
| 	char * s; | ||||
|  | ||||
| 	DEBUG("flushing warning messages\n"); | ||||
|  | ||||
| 	if(warningBuffer == NULL) return; | ||||
|  | ||||
| 	s = strtok(warningBuffer, "\n"); | ||||
|   | ||||
| @@ -357,8 +357,8 @@ void setupLogOutput(Options * options, FILE * out, FILE * err) { | ||||
|                 } | ||||
|  | ||||
|                 myfprintfStdLogMode(out, err); | ||||
|                 flushWarningLog(); | ||||
|         } | ||||
|         flushWarningLog(); | ||||
|  | ||||
|         /* lets redirect stdin to dev null as a work around for libao bug */ | ||||
|         { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Warren Dukes
					Warren Dukes