[xiph-commits] r16817 - in trunk/ao: include/ao src src/plugins/alsa09

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Tue Jan 26 01:38:18 PST 2010


Author: xiphmont
Date: 2010-01-26 01:38:18 -0800 (Tue, 26 Jan 2010)
New Revision: 16817

Modified:
   trunk/ao/include/ao/ao.h
   trunk/ao/src/audio_out.c
   trunk/ao/src/plugins/alsa09/ao_alsa09.c
Log:
Add soem smarts to the ALSA default device autoselection, as the device 
named 'default' is a plug that will happily accept any number of 
channels, but only plays L/R.



Modified: trunk/ao/include/ao/ao.h
===================================================================
--- trunk/ao/include/ao/ao.h	2010-01-26 07:33:24 UTC (rev 16816)
+++ trunk/ao/include/ao/ao.h	2010-01-26 09:38:18 UTC (rev 16817)
@@ -100,7 +100,7 @@
 void ao_shutdown(void);
 
 /* device setup/playback/teardown */
-int ao_append_option(ao_option **options, const char *key, 
+int ao_append_option(ao_option **options, const char *key,
 		     const char *value);
 void ao_free_options(ao_option *options);
 ao_device* ao_open_live(int driver_id, ao_sample_format *format,

Modified: trunk/ao/src/audio_out.c
===================================================================
--- trunk/ao/src/audio_out.c	2010-01-26 07:33:24 UTC (rev 16816)
+++ trunk/ao/src/audio_out.c	2010-01-26 09:38:18 UTC (rev 16817)
@@ -580,9 +580,10 @@
 	}
 }
 
-/* the channel locations we know right now. code below assumes U is in slot 0, M in slot 1 */
+/* the channel locations we know right now. code below assumes U is in slot 0, X in 1, M in 2 */
 static char *mnemonics[]={
-  "U","M","L","C","R","CL","CR","SL","SR","BL","BC","BR","LFE",
+  "U","X","M",
+  "L","C","R","CL","CR","SL","SR","BL","BC","BR","LFE",
   "A1","A2","A3","A4","A5","A6","A7","A8","A9",NULL
 };
 
@@ -608,7 +609,8 @@
       while(t>p && isspace(*(t-1)))t--;
 
       while(mnemonics[m]){
-        if(t-p && !strncmp(mnemonics[m],p,t-p)){
+        if(t-p && !strncmp(mnemonics[m],p,t-p) &&
+           strlen(mnemonics[m])==t-p){
           if(count)strcat(ret,",");
           strcat(ret,mnemonics[m]);
           break;
@@ -647,7 +649,8 @@
     while(*h && *h!=',')h++;
 
     while(mnemonics[m]){
-      if(!strncmp(mnemonics[needle],p,h-p))break;
+      if(!strncmp(mnemonics[needle],p,h-p) &&
+         strlen(mnemonics[needle])==h-p)break;
       m++;
     }
     if(mnemonics[m])
@@ -786,8 +789,8 @@
                 /* find match in input if any */
                 device->permute_channels[count] = _find_channel(m,sformat.matrix);
                 if(device->permute_channels[count] == -1 && sformat.channels == 1){
-                  device->permute_channels[count] = _find_channel(1,sformat.matrix);
-                  mm=0;
+                  device->permute_channels[count] = _find_channel(2,sformat.matrix);
+                  mm=2;
                 }
               }else
                 device->permute_channels[count] = -1;
@@ -799,8 +802,8 @@
                           count,mnemonics[m],device->permute_channels[count],
                           mnemonics[mm]);
                 }else{
-                  fprintf(stderr,"Output %d (%s)\t <- none\n",
-                          count,mnemonics[m]);
+                  fprintf(stderr,"Output %d (%s)\t <- %s\n",
+                          count,mnemonics[m],(m==1?"unavailable":"none"));
                 }
               }
               count++;

Modified: trunk/ao/src/plugins/alsa09/ao_alsa09.c
===================================================================
--- trunk/ao/src/plugins/alsa09/ao_alsa09.c	2010-01-26 07:33:24 UTC (rev 16816)
+++ trunk/ao/src/plugins/alsa09/ao_alsa09.c	2010-01-26 09:38:18 UTC (rev 16817)
@@ -107,10 +107,9 @@
 	int err;
 
 	/* Use nonblock flag when testing to avoid getting stuck if the device
-	   is in use. */
+	   is in use. Try several devices, as 'default' usually means 'stereo only'. */
 	err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,
 			   SND_PCM_NONBLOCK);
-
 	if (err != 0)
 		return 0; /* Cannot use this plugin with default parameters */
 	else {
@@ -132,21 +131,16 @@
 {
 	ao_alsa_internal *internal;
 
-	internal = (ao_alsa_internal *) malloc(sizeof(ao_alsa_internal));
+	internal = (ao_alsa_internal *) calloc(1,sizeof(ao_alsa_internal));
 
-	if (internal == NULL)	
+	if (internal == NULL)
 		return 0;
-	
+
 	internal->buffer_time = AO_ALSA_BUFFER_TIME;
 	internal->period_time = AO_ALSA_PERIOD_TIME;
 	internal->writei = AO_ALSA_WRITEI;
 	internal->access_mask = AO_ALSA_ACCESS_MASK;
 
-	if (!(internal->dev = strdup("default"))) {
-		free (internal);
-		return 0;
-	}
-	
 	device->internal = internal;
 
 	return 1;
@@ -364,8 +358,42 @@
 
 	/* Open the ALSA device */
 	internal->cmd = "snd_pcm_open";
-	err = snd_pcm_open(&(internal->pcm_handle), internal->dev,
-			   SND_PCM_STREAM_PLAYBACK, 0);
+        if(!internal->dev){
+          char *tmp=NULL;
+          /* we don't try just 'default' as it's a plug device that
+             will accept any number of channels but usually plays back
+             everything as stereo. */
+          switch(format->channels){
+          default:
+          case 8:
+          case 7:
+            err = snd_pcm_open(&(internal->pcm_handle), tmp="surround71",
+                               SND_PCM_STREAM_PLAYBACK, 0);
+            if(err==0)break;
+            /* fall through */
+          case 6:
+          case 5:
+          case 4:
+          case 3:
+            err = snd_pcm_open(&(internal->pcm_handle), tmp="surround51",
+                               SND_PCM_STREAM_PLAYBACK, 0);
+            if(err==0)break;
+            err = snd_pcm_open(&(internal->pcm_handle), tmp="surround40",
+                               SND_PCM_STREAM_PLAYBACK, 0);
+            if(err==0)break;
+            /* fall through */
+          case 2:
+          case 1:
+            err = snd_pcm_open(&(internal->pcm_handle), tmp="default",
+                               SND_PCM_STREAM_PLAYBACK, 0);
+            if(err==0)break;
+            err = snd_pcm_open(&(internal->pcm_handle), tmp="hw:0",
+                               SND_PCM_STREAM_PLAYBACK, 0);
+          }
+          if(err==0)internal->dev=strdup(tmp);
+        }else
+          err = snd_pcm_open(&(internal->pcm_handle), internal->dev,
+                             SND_PCM_STREAM_PLAYBACK, 0);
 	if (err < 0) {
 		internal->pcm_handle = NULL;
 		goto error;
@@ -385,9 +413,22 @@
 	if (format->bits > 8)
 		device->driver_byte_format = device->client_byte_format;
 
-        if(!device->output_matrix)
-          device->output_matrix=strdup("L,R,BL,BR,C,LFE,SL,SR");
+        if(device->verbose>0)
+          fprintf(stderr,"Using alsa device '%s'\n", internal->dev);
 
+        if(!device->output_matrix){
+          if(!strncasecmp(internal->dev,"plug:",5))
+            if(format->channels>2 && device->verbose>=0)
+              fprintf(stderr,"\nWARNING: No way to determine hardware channel mapping of\n"
+                      "ALSA 'plug:' devices.\n");
+          if(!strcasecmp(internal->dev,"default")){
+            if(format->channels>2 && device->verbose>=0)
+              fprintf(stderr,"\nWARNING: ALSA 'default' device plays only L,R channels.\n");
+            device->output_matrix=strdup("L,R,X,X,X,X,X,X,X,X,X");
+          }else
+            device->output_matrix=strdup("L,R,BL,BR,C,LFE,SL,SR");
+        }
+
 	return 1;
 
 error:



More information about the commits mailing list