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; | 		myAudioDevicesEnabled[i] = 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) { | 	param = getNextConfigParam(CONF_AUDIO_OUTPUT, param); | ||||||
|  |  | ||||||
|  | 	do { | ||||||
| 		if(audioOutputArraySize == AUDIO_MAX_DEVICES) { | 		if(audioOutputArraySize == AUDIO_MAX_DEVICES) { | ||||||
| 			ERROR("only up to 255 audio output devices are " | 			ERROR("only up to 255 audio output devices are " | ||||||
| 					"supported"); | 					"supported"); | ||||||
| @@ -93,12 +95,12 @@ void initAudioDriver() { | |||||||
| 	 | 	 | ||||||
| 		audioOutputArray[i] = newAudioOutput(param); | 		audioOutputArray[i] = newAudioOutput(param); | ||||||
|  |  | ||||||
| 		if(!audioOutputArray[i]) { | 		if(!audioOutputArray[i] && param) { | ||||||
| 			ERROR("problems configuring output device defined at " | 			ERROR("problems configuring output device defined at " | ||||||
| 					"line %i\n", param->line); | 					"line %i\n", param->line); | ||||||
| 			exit(EXIT_FAILURE); | 			exit(EXIT_FAILURE); | ||||||
| 		} | 		} | ||||||
| 	} | 	} while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))); | ||||||
| } | } | ||||||
|  |  | ||||||
| void getOutputAudioFormat(AudioFormat * inAudioFormat,  | void getOutputAudioFormat(AudioFormat * inAudioFormat,  | ||||||
|   | |||||||
| @@ -48,55 +48,87 @@ AudioOutput * newAudioOutput(ConfigParam * param) { | |||||||
| 	char * name = NULL; | 	char * name = NULL; | ||||||
| 	char * format = NULL; | 	char * format = NULL; | ||||||
| 	char * type = NULL; | 	char * type = NULL; | ||||||
| 	BlockParam * bp; | 	BlockParam * bp = NULL; | ||||||
|  | 	AudioOutputPlugin * plugin = NULL; | ||||||
|  |  | ||||||
| 	getBlockParam(AUDIO_OUTPUT_NAME, name, 1); | 	if(param) { | ||||||
| 	getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); | 		getBlockParam(AUDIO_OUTPUT_NAME, name, 1); | ||||||
|  | 		getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); | ||||||
|  |  | ||||||
| 	if(findInList(audioOutputPluginList, type, &data)) { | 		if(!findInList(audioOutputPluginList, type, &data)) { | ||||||
| 		AudioOutputPlugin * plugin = (AudioOutputPlugin *) data; | 			ERROR("couldn't find audio output plugin for type " | ||||||
| 		ret = malloc(sizeof(AudioOutput)); | 					"\"%s\" at line %i\n", type,  | ||||||
| 		ret->name = strdup(name); | 					param->line); | ||||||
| 		ret->type = strdup(type); | 			exit(EXIT_FAILURE); | ||||||
| 		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; | 		plugin = (AudioOutputPlugin *) data; | ||||||
| 		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); |  | ||||||
| 	 | 	 | ||||||
| 		if(format) { | 		if(format) { | ||||||
| 			ret->convertAudioFormat = 1; | 			ret->convertAudioFormat = 1; | ||||||
|  |  | ||||||
| 			if(0 != parseAudioConfig(&ret->reqAudioFormat, format)) | 			if(0 != parseAudioConfig(&ret->reqAudioFormat, format)) | ||||||
| 			{ | 			{ | ||||||
| 		        	ERROR("error parsing format at line %i\n",  | 	        		ERROR("error parsing format at line %i\n",  | ||||||
| 						bp->line); | 						bp->line); | ||||||
| 		        	exit(EXIT_FAILURE); | 	        		exit(EXIT_FAILURE); | ||||||
| 		        } | 	        	} | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if(plugin->initDriverFunc(ret, param) != 0) { |  | ||||||
| 			free(ret); |  | ||||||
| 			ret = NULL; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else { | 	else { | ||||||
| 		ERROR("couldn't find audio output plugin for type \"%s\" at " | 		ListNode * node = audioOutputPluginList->firstNode; | ||||||
| 				"line %i\n", type, param->line); |  | ||||||
| 		exit(EXIT_FAILURE); | 		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; | 	return ret; | ||||||
|   | |||||||
| @@ -28,6 +28,8 @@ | |||||||
|  |  | ||||||
| typedef struct _AudioOutput AudioOutput; | typedef struct _AudioOutput AudioOutput; | ||||||
|  |  | ||||||
|  | typedef int (* AudioOutputTestDefaultDeviceFunc) (); | ||||||
|  |  | ||||||
| typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput,  | typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput,  | ||||||
| 		ConfigParam * param); | 		ConfigParam * param); | ||||||
|  |  | ||||||
| @@ -71,6 +73,7 @@ struct _AudioOutput { | |||||||
| typedef struct _AudioOutputPlugin { | typedef struct _AudioOutputPlugin { | ||||||
| 	char * name; | 	char * name; | ||||||
|  |  | ||||||
|  | 	AudioOutputTestDefaultDeviceFunc testDefaultDeviceFunc; | ||||||
|         AudioOutputInitDriverFunc initDriverFunc; |         AudioOutputInitDriverFunc initDriverFunc; | ||||||
|         AudioOutputFinishDriverFunc finishDriverFunc; |         AudioOutputFinishDriverFunc finishDriverFunc; | ||||||
|         AudioOutputOpenDeviceFunc openDeviceFunc; |         AudioOutputOpenDeviceFunc openDeviceFunc; | ||||||
|   | |||||||
| @@ -69,7 +69,10 @@ static void freeAlsaData(AlsaData * ad) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | 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(); | 	AlsaData * ad = newAlsaData(); | ||||||
| 	 | 	 | ||||||
| 	audioOutput->data = ad; | 	audioOutput->data = ad; | ||||||
| @@ -85,6 +88,23 @@ static void alsa_finishDriver(AudioOutput * audioOutput) { | |||||||
| 	freeAlsaData(ad); | 	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)  | static int alsa_openDevice(AudioOutput * audioOutput)  | ||||||
| { | { | ||||||
| 	AlsaData * ad = audioOutput->data; | 	AlsaData * ad = audioOutput->data; | ||||||
| @@ -313,6 +333,7 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk, | |||||||
| AudioOutputPlugin alsaPlugin = | AudioOutputPlugin alsaPlugin = | ||||||
| { | { | ||||||
| 	"alsa", | 	"alsa", | ||||||
|  | 	alsa_testDefault, | ||||||
| 	alsa_initDriver, | 	alsa_initDriver, | ||||||
| 	alsa_finishDriver, | 	alsa_finishDriver, | ||||||
| 	alsa_openDevice, | 	alsa_openDevice, | ||||||
| @@ -332,6 +353,7 @@ AudioOutputPlugin alsaPlugin = | |||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL /* sendMetadataFunc */ | 	NULL /* sendMetadataFunc */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -237,6 +237,7 @@ static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk, | |||||||
| AudioOutputPlugin aoPlugin =  | AudioOutputPlugin aoPlugin =  | ||||||
| { | { | ||||||
| 	"ao", | 	"ao", | ||||||
|  | 	NULL, | ||||||
| 	audioOutputAo_initDriver, | 	audioOutputAo_initDriver, | ||||||
| 	audioOutputAo_finishDriver, | 	audioOutputAo_finishDriver, | ||||||
| 	audioOutputAo_openDevice, | 	audioOutputAo_openDevice, | ||||||
| @@ -259,6 +260,7 @@ AudioOutputPlugin aoPlugin = | |||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -291,10 +291,38 @@ static int oss_statDevice(char * device, int * stErrno) { | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | static int oss_testDefault() { | ||||||
| 	BlockParam * bp = getBlockParam(param, "device"); | 	int fd; | ||||||
| 	OssData * od = newOssData(); |  | ||||||
|  |  | ||||||
|  | 	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; | 	audioOutput->data = od; | ||||||
|  |  | ||||||
| 	if(!bp) { | 	if(!bp) { | ||||||
| @@ -307,8 +335,14 @@ static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { | |||||||
| 		if(ret[0] == 0) od->device = strdup("/dev/sound/dsp"); | 		if(ret[0] == 0) od->device = strdup("/dev/sound/dsp"); | ||||||
| 		else if(ret[1] == 0) od->device = strdup("/dev/dsp"); | 		else if(ret[1] == 0) od->device = strdup("/dev/dsp"); | ||||||
| 		else { | 		else { | ||||||
| 			ERROR("Error trying to open default OSS device " | 			if(param) { | ||||||
| 				"specified at line %i\n", param->line); | 				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) { | 			if(ret[0] == ret[1] == OSS_STAT_DOESN_T_EXIST) { | ||||||
| 				ERROR("Neither /dev/dsp nor /dev/sound/dsp " | 				ERROR("Neither /dev/dsp nor /dev/sound/dsp " | ||||||
| @@ -501,6 +535,7 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, | |||||||
| AudioOutputPlugin ossPlugin = | AudioOutputPlugin ossPlugin = | ||||||
| { | { | ||||||
| 	"oss", | 	"oss", | ||||||
|  | 	oss_testDefault, | ||||||
| 	oss_initDriver, | 	oss_initDriver, | ||||||
| 	oss_finishDriver, | 	oss_finishDriver, | ||||||
| 	oss_openDevice, | 	oss_openDevice, | ||||||
| @@ -521,6 +556,7 @@ AudioOutputPlugin ossPlugin = | |||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL /* sendMetadataFunc */ | 	NULL /* sendMetadataFunc */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -597,6 +597,7 @@ static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag) { | |||||||
| AudioOutputPlugin shoutPlugin =  | AudioOutputPlugin shoutPlugin =  | ||||||
| { | { | ||||||
| 	"shout", | 	"shout", | ||||||
|  | 	NULL, | ||||||
| 	myShout_initDriver, | 	myShout_initDriver, | ||||||
| 	myShout_finishDriver, | 	myShout_finishDriver, | ||||||
| 	myShout_openDevice, | 	myShout_openDevice, | ||||||
| @@ -617,6 +618,7 @@ AudioOutputPlugin shoutPlugin = | |||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
| 	NULL, | 	NULL, | ||||||
|  | 	NULL, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,9 +68,12 @@ void bufferWarning(char * format, ... ) { | |||||||
|  |  | ||||||
| 	va_end(arglist); | 	va_end(arglist); | ||||||
| } | } | ||||||
|  |  | ||||||
| void flushWarningLog() { | void flushWarningLog() { | ||||||
| 	char * s; | 	char * s; | ||||||
|  |  | ||||||
|  | 	DEBUG("flushing warning messages\n"); | ||||||
|  |  | ||||||
| 	if(warningBuffer == NULL) return; | 	if(warningBuffer == NULL) return; | ||||||
|  |  | ||||||
| 	s = strtok(warningBuffer, "\n"); | 	s = strtok(warningBuffer, "\n"); | ||||||
|   | |||||||
| @@ -357,8 +357,8 @@ void setupLogOutput(Options * options, FILE * out, FILE * err) { | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 myfprintfStdLogMode(out, err); |                 myfprintfStdLogMode(out, err); | ||||||
|                 flushWarningLog(); |  | ||||||
|         } |         } | ||||||
|  |         flushWarningLog(); | ||||||
|  |  | ||||||
|         /* lets redirect stdin to dev null as a work around for libao bug */ |         /* lets redirect stdin to dev null as a work around for libao bug */ | ||||||
|         { |         { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Warren Dukes
					Warren Dukes