esound r523 - trunk



Author: jmouette
Date: Tue Nov 18 20:30:54 2008
New Revision: 523
URL: http://svn.gnome.org/viewvc/esound?rev=523&view=rev

Log:
        * audio.c: (esd_audio_write), (esd_audio_flush),
        (esound_getblksize):
        * audio_oss.c: (esd_audio_open):
        * esd-server.h:
        * esd.c: (main):
        * esd.h:
        * proto.c: (esd_proto_get_latency):
        Rewrite generic esd_audio_write to attempt to use select if the
        driver seems to support it, and to write in a blocksize that
        can be changed by audio open functions.


Modified:
   trunk/ChangeLog
   trunk/audio.c
   trunk/audio_oss.c
   trunk/esd-server.h
   trunk/esd.c
   trunk/esd.h
   trunk/proto.c

Modified: trunk/audio.c
==============================================================================
--- trunk/audio.c	(original)
+++ trunk/audio.c	Tue Nov 18 20:30:54 2008
@@ -7,6 +7,8 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <math.h>
+#include <errno.h>
+#include <sys/select.h>
 
 /*******************************************************************/
 /* globals */
@@ -16,6 +18,8 @@
 
 /* the audio device, /dev/dsp, file descriptor */
 static int esd_audio_fd = -1;
+static int select_works = 0;
+static int esd_write_size = ESD_BUF_SIZE;
 
 /*******************************************************************/
 /* returns audio_fd for use by main prog - platform dependent */
@@ -84,7 +88,44 @@
 /* dump a buffer to the sound device */
 int esd_audio_write( void *buffer, int buf_size )
 {
-    return write( esd_audio_fd, buffer, buf_size );
+    ssize_t nwrite=0, pos=0;
+    int write_size = esd_write_size;
+
+    while (buf_size-pos > 0) {
+	if (buf_size-pos < write_size)
+	    write_size = buf_size-pos;
+
+	if (select_works) {
+	    fd_set set;
+	    struct timeval tv;
+	    int ret;
+
+	    tv.tv_sec = 0;
+	    tv.tv_usec = 10000;
+	    FD_ZERO(&set);
+	    FD_SET(esd_audio_fd, &set);
+	    if ((ret = select(esd_audio_fd+1, NULL, &set, NULL, &tv)) == 0) {
+		continue;
+	    } else if (ret < 0) {
+		return pos > 0 ? pos : -1;
+	    }
+	}
+
+	if ((nwrite = write( esd_audio_fd, buffer+pos, write_size )) <= 0 ) {
+	    if ( nwrite == -1 ) {
+		if ( errno == EAGAIN || errno == EINTR ) {
+		    if (!select_works)
+			usleep(1000);
+		    continue;
+		} else {
+		    perror("esound: esd_audio_write: write");
+		    return pos > 0 ? pos : -1;
+		}
+	    }
+	}
+	pos += nwrite;
+    }
+    return pos;
 }
 #endif
 
@@ -102,7 +143,14 @@
 /* flush the audio buffer */
 void esd_audio_flush()
 {
-    fsync( esd_audio_fd );
     return;
 }
 #endif
+
+/*
+ * For the daemon's use only -- what size to make the buffer
+ */
+int esound_getblksize(void)
+{
+    return esd_write_size;
+}

Modified: trunk/audio_oss.c
==============================================================================
--- trunk/audio_oss.c	(original)
+++ trunk/audio_oss.c	Tue Nov 18 20:30:54 2008
@@ -23,6 +23,7 @@
     return "/dev/dsp, /dev/dsp2, etc.";
 }
 
+#define NFRAGS 32
 
 #define ARCH_esd_audio_open
 int esd_audio_open()
@@ -31,6 +32,22 @@
 
     int afd = -1, value = 0, test = 0;
     int mode = O_WRONLY;
+    int rate;
+    int fragsize;
+    int frag;
+    struct timeval tv;
+    fd_set set;
+
+    rate = esd_audio_rate *
+        ( ( ( esd_audio_format & ESD_MASK_CHAN) == ESD_STEREO ) ? 2 : 1 ) *
+        ( ( ( esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 ) ? 2 : 1 );
+
+    for ( fragsize = 0; 1L << fragsize < rate / 25; fragsize++ )
+	;
+
+    fragsize--;
+
+    frag = (NFRAGS << 16) | fragsize;
 
     /* if recording, set for full duplex mode */
     if ( (esd_audio_format & ESD_MASK_FUNC) == ESD_RECORD )
@@ -51,6 +68,10 @@
     mode &= ~O_NONBLOCK;
     fcntl(afd, F_SETFL, mode);
 
+#if defined(SNDCTL_DSP_SETFRAGMENT)
+    ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &frag);
+#endif
+
     /* TODO: check that this is allowable */
     /* set for full duplex operation, if recording */
 #if defined(SNDCTL_DSP_SETDUPLEX)
@@ -59,26 +80,6 @@
     }
 #endif
 
-    /* set the sound driver fragment size and number */
-#if !defined(__powerpc__) /* does not exist on powerpc */
-    /* fragment = max_buffers << 16 + log2(buffer_size), (256 16) */
-    value = test = ( 0x0100 << 16 ) + 0x0008;
-    if (ioctl(afd, SNDCTL_DSP_SETFRAGMENT, &test) == -1)
-    {   /* Fatal error */
-        perror( "SNDCTL_DSP_SETFRAGMENT" );
-        close( afd );
-        esd_audio_fd = -1;
-        return( -1 );
-    }
-    if ( 0 /* value != test */ ) /* TODO: determine the real test */
-    {   /* The device doesn't support the requested audio format. */
-        fprintf( stderr, "unsupported fragment size: %d\n", value );
-        close( afd );
-        esd_audio_fd = -1;
-        return( -1 );
-    }
-#endif /* #if !defined(__powerpc__) */
-
     /* set the sound driver audio format for playback */
     
     value = test = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 )
@@ -131,8 +132,31 @@
         return( -1 );
     }
 
+    if ( ioctl(afd, SNDCTL_DSP_GETBLKSIZE, &test) == -1)
+    { /* Fatal error */
+        perror("SNDCTL_DSP_GETBLKSIZE");
+        close( afd );
+        esd_audio_fd = -1;
+        return( -1 );
+    }
+    esd_write_size = test > ESD_MAX_WRITE_SIZE ? ESD_MAX_WRITE_SIZE : test;
+
     /* value = test = buf_size; */
     esd_audio_fd = afd;
+    /*
+     * From XMMS:
+     * Stupid hack to find out if the driver supports select; some
+     * drivers won't work properly without a select and some won't
+     * work with a select :/
+     */
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10;
+    FD_ZERO(&set);
+    FD_SET(afd, &set);
+    test = select(afd + 1, NULL, &set, NULL, &tv);
+    if (test > 0)
+	    select_works = 1;
     return afd;
 }
 

Modified: trunk/esd-server.h
==============================================================================
--- trunk/esd-server.h	(original)
+++ trunk/esd-server.h	Tue Nov 18 20:30:54 2008
@@ -209,6 +209,9 @@
 int esd_set_socket_buffers( int sock, int src_format, 
 			    int src_rate, int base_rate );
 
+/* audio.c */
+int esound_getblksize(void);
+
 /*******************************************************************/
 /* evil evil macros */
 

Modified: trunk/esd.c
==============================================================================
--- trunk/esd.c	(original)
+++ trunk/esd.c	Tue Nov 18 20:30:54 2008
@@ -640,7 +640,7 @@
     /* begin test scaffolding parameters */
     /* int format = AFMT_U8; AFMT_S16_LE; */
     /* int stereo = 0; */     /* 0=mono, 1=stereo */
-    int default_rate = ESD_DEFAULT_RATE, default_buf_size = ESD_BUF_SIZE;
+    int default_rate = ESD_DEFAULT_RATE;
     int i, j, freq=440;
     int magl, magr;
 
@@ -848,11 +848,6 @@
     exit( 1 );	
   }
 
-#define ESD_AUDIO_STUFF \
-    esd_sample_size = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 ) \
-	? sizeof(signed short) : sizeof(unsigned char); \
-    esd_buf_size_samples = default_buf_size / 2; \
-    esd_buf_size_octets = esd_buf_size_samples * esd_sample_size;
 
     /* start the initializatin process */
 /*    printf( "ESound daemon initializing...\n" );*/
@@ -860,7 +855,6 @@
     /* set the data size parameters */
     esd_audio_format = default_format;
     esd_audio_rate = default_rate;
-    ESD_AUDIO_STUFF;
 
   /* open and initialize the audio device, /dev/dsp */
   itmp = esd_audio_open();
@@ -885,7 +879,6 @@
     /* cant do defaults ... try 44.1 kkz 8bit stereo */
     esd_audio_format = ESD_BITS8 | ESD_STEREO;
     esd_audio_rate = 44100;
-    ESD_AUDIO_STUFF;
     if ( esd_audio_open() < 0 ) {
       fprintf(stderr, "Audio device open for 44.1Khz, stereo, 8bit failed\n"
 
@@ -893,56 +886,48 @@
     /* cant do defaults ... try 48 kkz 16bit stereo */
     esd_audio_format = ESD_BITS16 | ESD_STEREO;
     esd_audio_rate = 48000;
-    ESD_AUDIO_STUFF;
     if ( esd_audio_open() < 0 ) {
       fprintf(stderr, "Audio device open for 48Khz, stereo,16bit failed\n"
 	      "Trying 22.05Khz, 8bit stereo.\n");
       /* cant do defaults ... try 22.05 kkz 8bit stereo */
       esd_audio_format = ESD_BITS8 | ESD_STEREO;
       esd_audio_rate = 22050;
-      ESD_AUDIO_STUFF;
       if ( esd_audio_open() < 0 ) {
 	fprintf(stderr, "Audio device open for 22.05Khz, stereo, 8bit failed\n"
 		"Trying 44.1Khz, 16bit mono.\n");
 	/* cant do defaults ... try 44.1Khz kkz 16bit mono */
 	esd_audio_format = ESD_BITS16;
 	esd_audio_rate = 44100;
-	ESD_AUDIO_STUFF;
 	if ( esd_audio_open() < 0 ) {
 	  fprintf(stderr, "Audio device open for 44.1Khz, mono, 8bit failed\n"
 		  "Trying 22.05Khz, 8bit mono.\n");
 	  /* cant do defaults ... try 22.05 kkz 8bit mono */
 	  esd_audio_format = ESD_BITS8;
 	  esd_audio_rate = 22050;
-	  ESD_AUDIO_STUFF;
 	  if ( esd_audio_open() < 0 ) {
 	    fprintf(stderr, "Audio device open for 22.05Khz, mono, 8bit failed\n"
 		    "Trying 11.025Khz, 8bit stereo.\n");
 	    /* cant to defaults ... try 11.025 kkz 8bit stereo */
 	    esd_audio_format = ESD_BITS8 | ESD_STEREO;
 	    esd_audio_rate = 11025;
-	    ESD_AUDIO_STUFF;
 	    if ( esd_audio_open() < 0 ) {
 	      fprintf(stderr, "Audio device open for 11.025Khz, stereo, 8bit failed\n"
 		      "Trying 11.025Khz, 8bit mono.\n");
 	      /* cant to defaults ... try 11.025 kkz 8bit mono */
 	      esd_audio_format = ESD_BITS8;
 	      esd_audio_rate = 11025;
-	      ESD_AUDIO_STUFF;
 	      if ( esd_audio_open() < 0 ) {
 		fprintf(stderr, "Audio device open for 11.025Khz, mono, 8bit failed\n"
 			"Trying 8.192Khz, 8bit mono.\n");
 	        /* cant to defaults ... try 8.192 kkz 8bit mono */
 		esd_audio_format = ESD_BITS8;
 		esd_audio_rate = 8192;
-		ESD_AUDIO_STUFF;
 		if ( esd_audio_open() < 0 ) {
 		  fprintf(stderr, "Audio device open for 8.192Khz, mono, 8bit failed\n"
 			  "Trying 8Khz, 8bit mono.\n");
 		  /* cant to defaults ... try 8 kkz 8bit mono */
 		  esd_audio_format = ESD_BITS8;
 		  esd_audio_rate = 8000;
-		  ESD_AUDIO_STUFF;
 		  if ( esd_audio_open() < 0 ) {
 		    fprintf(stderr, "Sound device inadequate for Esound. Fatal.\n");
 		    if (!esd_use_tcpip)
@@ -969,6 +954,11 @@
     }
    }
   }
+    esd_sample_size = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 )
+	? sizeof(signed short) : sizeof(unsigned char);
+    esd_buf_size_samples = esound_getblksize() / esd_sample_size;
+    esd_buf_size_octets = esound_getblksize();
+
 
     /* allocate and zero out buffer */
     output_buffer = (void *) malloc( esd_buf_size_octets );

Modified: trunk/esd.h
==============================================================================
--- trunk/esd.h	(original)
+++ trunk/esd.h	Tue Nov 18 20:30:54 2008
@@ -12,6 +12,8 @@
 
 /* size of the audio buffer */
 #define ESD_BUF_SIZE (4 * 1024)
+/* maximum size we can write().  Otherwise we might overflow */
+#define ESD_MAX_WRITE_SIZE (21 * 4096)
 
 /* length of the authorization key, octets */
 #define ESD_KEY_LEN (16)

Modified: trunk/proto.c
==============================================================================
--- trunk/proto.c	(original)
+++ trunk/proto.c	Tue Nov 18 20:30:54 2008
@@ -89,22 +89,23 @@
 int esd_proto_get_latency( esd_client_t *client )
 {
     int lag, amount, actual;
+    int buf_size = esound_getblksize();
 
     ESDBG_TRACE( printf( "(%02d) proto: get latency\n", client->fd ); );
   
     if (esd_audio_format & ESD_STEREO)
       {
 	if (esd_audio_format & ESD_BITS16)
-	  amount = (44100 * (ESD_BUF_SIZE + 64)) / esd_audio_rate;
+	  amount = (44100 * (buf_size + 64)) / esd_audio_rate;
 	else
-	  amount = (44100 * (ESD_BUF_SIZE + 128)) / esd_audio_rate;
+	  amount = (44100 * (buf_size + 128)) / esd_audio_rate;
       }
     else
       {
 	if (esd_audio_format & ESD_BITS16)
-	  amount = (2 * 44100 * (ESD_BUF_SIZE + 128)) / esd_audio_rate;
+	  amount = (2 * 44100 * (buf_size + 128)) / esd_audio_rate;
 	else
-	  amount = (2 * 44100 * (ESD_BUF_SIZE + 256)) / esd_audio_rate;
+	  amount = (2 * 44100 * (buf_size + 256)) / esd_audio_rate;
       }
     lag = maybe_swap_32( client->swap_byte_order, amount );
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]