[Alsaplayer-devel]ac3play patch

Yuqing Deng deng@tinker.chem.brown.edu
Thu, 7 Jun 2001 18:22:46 -0700 (EDT)


Hi,
  I made ac3play work with alsa 0.9.
  The patch is included.  Run automake and autoconf before configure.
  
  Yuqing
  
diff -Ncr ac3play-0.3.0/Makefile.am /home/deng/ac3play-0.3.0/Makefile.am
*** ac3play-0.3.0/Makefile.am	Mon Jun  5 14:49:13 2000
--- /home/deng/ac3play-0.3.0/Makefile.am	Wed Jan 24 20:44:36 2001
***************
*** 4,8 ****
  
  CFLAGS = @CFLAGS@ -I$(top_srcdir)/libac3
  bin_PROGRAMS = ac3play
! ac3play_SOURCES = ac3play.c ac3_pack.c ac3_pack.h
  ac3play_LDADD =  $(top_builddir)/libac3/libac3.a
--- 4,8 ----
  
  CFLAGS = @CFLAGS@ -I$(top_srcdir)/libac3
  bin_PROGRAMS = ac3play
! ac3play_SOURCES = ac3play.c ac3burst.c ac3burst.h
  ac3play_LDADD =  $(top_builddir)/libac3/libac3.a
diff -Ncr ac3play-0.3.0/ac3_pack.c /home/deng/ac3play-0.3.0/ac3_pack.c
*** ac3play-0.3.0/ac3_pack.c	Tue Jun  6 03:59:22 2000
--- /home/deng/ac3play-0.3.0/ac3_pack.c	Wed Dec 31 19:00:00 1969
***************
*** 1,309 ****
- /* 
-  *  ac3_pack.c
-  *
-  *	Copyright (C) 2000 by Yuqing Deng
-  *  
-  *  Based on Andy Lo A Foe's orginal ac3play 0.2.0
-  *
-  *  ac3_pack.c is free software; you can redistribute it and/or modify
-  *  it under the terms of the GNU General Public License as published by
-  *  the Free Software Foundation; either version 2, or (at your option)
-  *  any later version.
-  *   
-  *  play_ac3 is distributed in the hope that it will be useful,
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  *  GNU General Public License for more details.
-  *   
-  *  You should have received a copy of the GNU General Public License
-  *  along with GNU Make; see the file COPYING.  If not, write to
-  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
-  *
-  *
-  *  Tue Jun  6 09:56:34 CEST 2000, andy
-  *  -----------------------------------
-  *  Updated ALSA API calls
-  *
-  *
-  */
- 
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/asoundlib.h>
- #include "ac3.h"
- #include "ac3_internal.h"
- #include "parse.h"
- 
- #define BLOCK_SIZE 6144
- static char buf[BLOCK_SIZE];
- static uint_32 sbuffer_size = 0;
- 
- static syncinfo_t syncinfo;
- static char *sbuffer = &buf[10];
- 
- static int pcm_mode = SND_PCM_MODE_FRAGMENT;
- static FILE *bla2;
- static snd_pcm_t *handle;
- static snd_pcm_stream_status_t status;
- static	snd_pcm_stream_setup_t setup;
- static stream = SND_PCM_STREAM_PLAYBACK;
- 
- uint_32
- buffer_syncframe(syncinfo_t *syncinfo, uint_8 **start, uint_8 *end)
- {
-         uint_8 *cur = *start;
-         uint_16 syncword = syncinfo->syncword;
-         uint_32 ret = 0;
-  
-         //
-         // Find an ac3 sync frame.
-         //
-         while(syncword != 0x0b77)
-         {
-                 if(cur >= end)
-                         goto done;
-                 syncword = (syncword << 8) + *cur++;
-         }
-  
-         //need the next 3 bytes to decide how big the frame is
-         while(sbuffer_size < 3)
-         {
-                 if(cur >= end)
-                         goto done;
-  
-                 sbuffer[sbuffer_size++] = *cur++;
-         }
-                                                                                     
-         parse_syncinfo(syncinfo,sbuffer);
-         //stats_print_syncinfo(syncinfo);
-  
-         while(sbuffer_size < syncinfo->frame_size * 2 - 2)
-         {
-                 if(cur >= end)
-                         goto done;
-  
-                 sbuffer[sbuffer_size++] = *cur++;
-         }
-  
-         // Check the crc over the entire frame
-         crc_init();
-         crc_process_frame(sbuffer,syncinfo->frame_size * 2 - 2);
-  
-         if(!crc_validate())
-         {
-                 //error_flag = 1;
-                 fprintf(stderr,"** CRC failed - skipping frame **\n");
-                 goto done;
-         }                                                                           
-         //
-         //if we got to this point, we found a valid ac3 frame to decode
-         //
-  
-         //bitstream_init(buffer);
-         //get rid of the syncinfo struct as we already parsed it
-         //bitstream_get(24);
-  
-         //reset the syncword for next time
-         syncword = 0xffff;
-         sbuffer_size = 0;
-         ret = 1;
-  
- done:
-         syncinfo->syncword = syncword;
-         *start = cur;
-         return ret;
- }                                                                                  
- 
- void
- output_spdif_pack(uint_8 *data_start, uint_8 *data_end)
- {
- 	unsigned short *sbuf = (unsigned short *)buf;
- 	int err = 0;
- 
- 	while(buffer_syncframe(&syncinfo, &data_start, data_end))
- 	{
- 		sbuf[0] = 0xf872;  //spdif syncword
- 		sbuf[1] = 0x4e1f;  // .............
- 		sbuf[2] = 0x0001;  // AC3 data
- 		sbuf[3] = syncinfo.frame_size * 16;
-  		sbuf[4] = 0x0b77;  // AC3 syncwork
- 
- 		// extract_ac3 seems to write swabbed data
- 		swab(&buf[10], &buf[10], syncinfo.frame_size * 2 - 2);
- #ifdef DEBUG
- 		if (bla2) 
- 			fwrite(buf, BLOCK_SIZE, 1, bla2);
- #endif
- 
- 		// Write out the frame to S/PDIF
- #ifdef DEBUG
- 		do {
- 			if ((err=snd_pcm_stream_status(handle, &status)) < 0) {
- 				fprintf(stderr, "cannot get stream status: %s\n", snd_strerror(err));
- 			}
- 			
- 			switch (status.status) {
- 			case SND_PCM_STATUS_NOTREADY:
- 			  fprintf(stderr, "status: NOTREADY\n");
- 			  break;
- 			case SND_PCM_STATUS_READY:
- 			  fprintf(stderr, "status: READY\n");
- 			  break;
- 			case SND_PCM_STATUS_PREPARED:
- 			  fprintf(stderr, "status: PREPARED\n");
- 			  break;
- 			case SND_PCM_STATUS_RUNNING:
- 			  fprintf(stderr, "status: RUNNING\n");
- 			  break;
- 			case SND_PCM_STATUS_XRUN:
- 			  fprintf(stderr, "status: XRUN\n");
- 			  break;
- 			case SND_PCM_STATUS_PAUSED:
- 			  fprintf(stderr, "status: PAUSED\n");
- 			  break;
- 			}
- 			fprintf(stderr, "bytes available: %d\n",
- 				 status.avail);
- 		} while (status.bytes_free < BLOCK_SIZE);
- #endif
- 
- 		snd_pcm_write(handle, buf, BLOCK_SIZE);
- 		memset(&status, 0, sizeof(status));
- 		snd_pcm_stream_status(handle, &status);
- 		if (status.xruns) {
- 			fprintf(stderr, "underrun, resetting stream\n");
- 			snd_pcm_stream_flush(handle, stream);
- 			snd_pcm_stream_prepare(handle, stream);
- 			snd_pcm_write(handle, buf, BLOCK_SIZE);
- 			snd_pcm_stream_status(handle, &status);
- 			if (status.xruns) {
- 				fprintf(stderr, "still underrun, give up\n");
- 				return;
- 			}
- 		}
- 	}
- }
- 
- uint_32
- spdif_init(int acard, int adevice)
- {
- 	snd_pcm_stream_info_t info;
- 	snd_pcm_digital_t	digital;
- 	snd_pcm_stream_params_t params;
- 	int err, c;
- 
- 	if ((err = snd_pcm_open(&handle, acard, adevice, SND_PCM_OPEN_PLAYBACK)) < 0)
- 	{
- 		fprintf(stderr, "open: %s\n", snd_strerror(err));
- 		return 1;
- 	}
- 	memset(&info, 0, sizeof(info));
- 	if ((err = snd_pcm_stream_info(handle, &info)) < 0) {
- 		fprintf(stderr, "info: %s\n", snd_strerror(err));
- 		snd_pcm_close(handle);
- 		return 1;
- 	}
- #ifdef DEBUG	
- 	bla2 = fopen("/tmp/ac3dump", "w");
- 
- 	printf("%s\n", info.subname);
- 	printf("stream = %d\n", info.stream);
- 	printf("formats = %d\n", info.formats);
- 	printf("flags = %d\n", info.flags);
- 	printf("samplerate = %d - %d\n", info.min_rate, info.max_rate);
- 	//	printf("mode = %d\n", info.mode);
- 	printf("fifo_size = %d\n", info.fifo_size);
- 	printf("buffer_size = %d\n", info.buffer_size);
- #endif
- 	memset(&setup, 0, sizeof(setup));
- 	memset(&params, 0, sizeof(params));
- 	params.mode = pcm_mode;
- 	params.stream = stream;
- 	params.start_mode = SND_PCM_START_FULL;
- 	params.xrun_mode = SND_PCM_XRUN_FLUSH;
- 	params.frag_size = BLOCK_SIZE;
- 	params.buffer_size = BLOCK_SIZE * 6;
- #if 1	
- 	params.digital.valid = 1;
- 	params.digital.dig.aes.status[0] = SND_PCM_AES0_NONAUDIO;
- 	params.digital.dig.aes.status[3] = SND_PCM_AES3_CON_FS_48000;
- #endif
- 	params.format.format = SND_PCM_SFMT_S16_LE;
- 	params.format.rate = 48000;
- 	params.format.interleave = 1;
- 	params.format.channels = 2;
- 	snd_pcm_stream_flush(handle, stream);
- 			
- 	if ((err = snd_pcm_stream_params(handle, &params)) < 0) {
- 		fprintf(stderr, "params: %s\n", snd_strerror(err));
- 		snd_pcm_close(handle);
- 		return 3;
- 	}	
- #if 0
- 	setup.digital.valid = 1;
- 	setup.digital.dig.aes.status[0] = SND_PCM_DIG0_NONAUDIO;
- 	setup.digital.dig.aes.status[3]	= SND_PCM_DIG3_CON_FS_48000;
- #endif
- 	setup.mode = pcm_mode;
- 	setup.stream = stream;
- 	if ((err = snd_pcm_stream_prepare(handle, stream)) < 0) {
- 		fprintf(stderr, "prepare: %s\n", snd_strerror(err));
- 		return 2;
- 	}
- 	if ((err = snd_pcm_stream_setup(handle, &setup)) < 0) {
- 		fprintf(stderr, "setup: %s\n", snd_strerror(err));
- 		snd_pcm_close(handle);
- 		return 2;
- 	}
- 
- 	memset(buf, 0, sizeof(buf));
- 
- 	// Send some trailing zeros to avoid misdetecting the 
- 	// first frame as PCM (works for DTT2500 at least)
- 	for (c=0; c < 0; c++) {
- 		if ((snd_pcm_write(handle, buf, BLOCK_SIZE)) < 0) {
- 		   fprintf(stderr, "error in initial write\n");
- 		   exit(2);
- 	        }
- 			if ((err=snd_pcm_stream_status(handle, &status)) < 0) {
- 				fprintf(stderr, "cannot get stream status: %s\n", snd_strerror(err));
- 			}
- 			//snd_pcm_stream_prepare(handle, SND_PCM_CHANNEL_PLAYBACK);
- 			
- 			switch (status.status) {
- 			case SND_PCM_STATUS_NOTREADY:
- 			  fprintf(stderr, "status: NOTREADY\n");
- 			  break;
- 			case SND_PCM_STATUS_READY:
- 			  fprintf(stderr, "status: READY\n");
- 			  break;
- 			case SND_PCM_STATUS_PREPARED:
- 			  snd_pcm_playback_go(handle);
- 			  fprintf(stderr, "status: PREPARED\n");
- 			  break;
- 			case SND_PCM_STATUS_RUNNING:
- 			  fprintf(stderr, "status: RUNNING\n");
- 			  break;
- 			case SND_PCM_STATUS_XRUN:
- 			  fprintf(stderr, "status: XRUN\n");
- 			  break;
- 			case SND_PCM_STATUS_PAUSED:
- 			  fprintf(stderr, "status: PAUSED\n");
- 			  break;
- 			}
- 			fprintf(stderr, "bytes available: %d\n",
- 				 status.bytes_avail);
- 	}
- 	return 0;
- }
- 
- void spdif_close()
- {
- 	// Cleanup
- 	snd_pcm_close(handle);
- #ifdef DEBUG
- 	if (bla2)
- 		fclose(bla2);
- #endif	
- }
--- 0 ----
diff -Ncr ac3play-0.3.0/ac3_pack.h /home/deng/ac3play-0.3.0/ac3_pack.h
*** ac3play-0.3.0/ac3_pack.h	Mon Jun  5 01:14:45 2000
--- /home/deng/ac3play-0.3.0/ac3_pack.h	Wed Dec 31 19:00:00 1969
***************
*** 1,4 ****
- uint_32 buffer_syncframe(syncinfo_t*, uint_8 **, uint_8 *);
- void output_spdif_pack(uint_8 *, uint_8 *);
- uint_32 spdif_init(int acard, int adevice);
- void spdif_close(void);
--- 0 ----
diff -Ncr ac3play-0.3.0/ac3burst.c /home/deng/ac3play-0.3.0/ac3burst.c
*** ac3play-0.3.0/ac3burst.c	Wed Dec 31 19:00:00 1969
--- /home/deng/ac3play-0.3.0/ac3burst.c	Sat Jun  2 10:13:03 2001
***************
*** 0 ****
--- 1,362 ----
+ /* 
+  *  ac3burst.c
+  *
+  *	Copyright (C) 2000 by Yuqing Deng
+  *  
+  *  Based on Andy Lo A Foe's orginal ac3play 0.2.0
+  *
+  *  ac3_pack.c is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+  *  the Free Software Foundation; either version 2, or (at your option)
+  *  any later version.
+  *   
+  *  play_ac3 is distributed in the hope that it will be useful,
+  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  *  GNU General Public License for more details.
+  *   
+  *  You should have received a copy of the GNU General Public License
+  *  along with GNU Make; see the file COPYING.  If not, write to
+  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
+  *
+  *
+  *  Tue Jun  6 09:56:34 CEST 2000, andy
+  *  -----------------------------------
+  *  Updated ALSA API calls
+  *
+  *
+  */
+ 
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+ #include <sys/asoundlib.h>
+ #include <sys/uio.h>
+ #include <errno.h>
+ #include <sys/poll.h>
+ #include "ac3.h"
+ #include "ac3_internal.h"
+ #include "crc.h"
+ #include "parse.h"
+ 
+ extern void swab (__const void *__restrict __from, void *__restrict __to,
+                   ssize_t __n);
+ 
+ #define BURST_SIZE 6144
+ static u_char buf[BURST_SIZE];
+ static uint_32 sbuffer_size = 0;
+ 
+ static syncinfo_t syncinfo;
+ static char *sbuffer = &buf[10];
+ 
+ #ifdef DEBUG
+ static FILE *bla2;
+ #endif
+ 
+ static snd_pcm_t *handle;
+ static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
+ static snd_output_t *log;
+ //static snd_pcm_uframes_t buffer_size = BURST_SIZE / 4 * 6;
+ 
+ uint_32
+ buffer_syncframe(syncinfo_t *syncinfo, uint_8 **start, uint_8 *end)
+ {
+         uint_8 *cur = *start;
+         uint_16 syncword = syncinfo->syncword;
+         uint_32 ret = 0;
+  
+         //
+         // Find an ac3 sync frame.
+         //
+ resync:
+         while(syncword != 0x0b77)
+         {
+                 if(cur >= end)
+                         goto done;
+                 syncword = (syncword << 8) + *cur++;
+         }
+  
+         //need the next 3 bytes to decide how big the frame is
+         while(sbuffer_size < 3)
+         {
+                 if(cur >= end)
+                         goto done;
+  
+                 sbuffer[sbuffer_size++] = *cur++;
+         }
+                                                                                     
+         parse_syncinfo(syncinfo,sbuffer);
+         //stats_print_syncinfo(syncinfo);
+  
+         while(sbuffer_size < syncinfo->frame_size * 2 - 2)
+         {
+                 if(cur >= end)
+                         goto done;
+  
+                 sbuffer[sbuffer_size++] = *cur++;
+         }
+  
+         // Check the crc over the entire frame
+         crc_init();
+         crc_process_frame(sbuffer,syncinfo->frame_size * 2 - 2);
+  
+         if(!crc_validate())
+         {
+                 //error_flag = 1;
+                 fprintf(stderr,"** CRC failed - skipping frame **\n");
+         	syncword = 0xffff;
+ 		sbuffer_size = 0;
+                 goto resync;
+         }                                                                           
+         //
+         //if we got to this point, we found a valid ac3 frame to decode
+         //
+  
+         //bitstream_init(buffer);
+         //get rid of the syncinfo struct as we already parsed it
+         //bitstream_get(24);
+  
+         //reset the syncword for next time
+         syncword = 0xffff;
+         sbuffer_size = 0;
+         ret = 1;
+  
+ done:
+         syncinfo->syncword = syncword;
+         *start = cur;
+         return ret;
+ }                                                                                  
+ void xrun(void)
+ {
+         snd_pcm_status_t *status;
+         int res;
+ 	 
+         snd_pcm_status_alloca(&status);
+         if ((res = snd_pcm_status(handle, status))<0) {
+            printf("status error: %s", snd_strerror(res));
+ 	   return;
+         }
+         if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
+            struct timeval now, diff, tstamp;
+            gettimeofday(&now, 0);
+            snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+            timersub(&now, &tstamp, &diff);
+            fprintf(stderr, "xrun!!! (at least %.3f ms long)\n", diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+ 										           if ((res = snd_pcm_prepare(handle))<0) {
+ 	           printf("xrun: prepare error: %s", snd_strerror(res));
+ 		   return;
+            }
+            return;         /* ok, data should be accepted again */
+         }
+ }
+ void write_burst(u_char *data, size_t count)
+ {
+    ssize_t r;
+    while(count > 0) {
+      r = snd_pcm_writei(handle, data, count);
+      if (r == -EAGAIN || (r >=0 && r < count)) {
+        snd_pcm_wait(handle, 1000);
+      } else if (r == -EPIPE) {
+        xrun();
+      }
+      if (r > 0) {
+        count -= r;
+        data += r * 4;
+      }
+   }
+ }
+ 
+ void write_pause_burst(int error)
+ {
+  	unsigned short *sbuf = (unsigned short *)&buf[0];
+ 
+ 	sbuf[0] = 0xf872;
+ 	sbuf[1] = 0x4e1f;
+ 	
+ 	if (error == 0)  
+ 		// Audio ES Channel empty, wait for DD Decoder or pause
+ 		sbuf[2] = 0x0003;
+ 	else
+ 		// user stop, skip or error
+ 		sbuf[2] = 0x0103;
+ 
+ 	sbuf[3] = 0x0020;
+ 	sbuf[4] = 0x0000;
+ 	sbuf[5] = 0x0000;
+ 	
+ 	memset(&sbuf[6], 0, BURST_SIZE - 96);
+ 
+ 	write_burst((u_char *)sbuf, BURST_SIZE / 4);
+ }
+ 
+ void
+ output_spdif_burst(uint_8 *data_start, uint_8 *data_end)
+ {
+ 	unsigned short *sbuf = (unsigned short *)buf;
+ 
+ 	while(buffer_syncframe(&syncinfo, &data_start, data_end))
+ 	{
+ 		sbuf[0] = 0xf872;  //spdif syncword
+ 		sbuf[1] = 0x4e1f;  // .............
+ 		sbuf[2] = 0x0001;  // AC3 data
+ 		sbuf[3] = syncinfo.frame_size * 16;
+  		sbuf[4] = 0x0b77;  // AC3 syncword
+ 
+ 		// extract_ac3 seems to write swabbed data
+ 		swab(&buf[10], &buf[10], syncinfo.frame_size * 2 - 2);
+ #ifdef DEBUG
+ 		if (bla2) 
+ 			fwrite(buf, BURST_SIZE, 1, bla2);
+ #endif
+ 
+ 		// Write out the frame to S/PDIF
+ 		write_burst(buf, BURST_SIZE / 4);
+ 			
+ 
+ 	}
+ }
+ 
+ uint_32
+ spdif_init(int acard, int adevice)
+ {
+ 	//char *pcm_name = "hw:0,2"; /* first card second device */
+ 	char pcm_name[255];
+ 	static snd_aes_iec958_t spdif;
+ 	snd_pcm_info_t 	*info;
+ 	snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
+ 	unsigned int channels = 2;
+ 	unsigned int rate = 48000;
+ 	int err, c;
+ 
+ 	if (err = snprintf(&pcm_name[0], 11, "hw:%1d,%1d", acard, adevice) <= 0)
+ 	{
+ 		return 1;
+ 	}
+ 
+ 	if ((err = snd_pcm_open(&handle, pcm_name, stream, 0)) < 0)
+ 	{
+ 		fprintf(stderr, "open: %s\n", snd_strerror(err));
+ 		return 1;
+ 	}
+ 
+ 	snd_pcm_info_alloca(&info);
+ 
+ 	if ((err = snd_pcm_info(handle, info)) < 0) {
+ 		fprintf(stderr, "info: %s\n", snd_strerror(err));
+ 		snd_pcm_close(handle);
+ 		return 1;
+ 	}
+         printf("device: %d, subdevice: %d\n", snd_pcm_info_get_device(info),
+                 snd_pcm_info_get_subdevice(info));                              
+ 	{
+         snd_ctl_elem_value_t *ctl;
+         snd_ctl_t *ctl_handle;
+         char ctl_name[12];
+         int ctl_card;
+ 
+ 	spdif.status[0] = IEC958_AES0_NONAUDIO |
+ 			  IEC958_AES0_CON_EMPHASIS_NONE;
+ 	spdif.status[1] = IEC958_AES1_CON_ORIGINAL |
+ 			  IEC958_AES1_CON_PCM_CODER;
+ 	spdif.status[2] = 0;
+ 	spdif.status[3] = IEC958_AES3_CON_FS_48000;
+ 
+         snd_ctl_elem_value_alloca(&ctl);
+         snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM);
+         snd_ctl_elem_value_set_device(ctl, snd_pcm_info_get_device(info));
+         snd_ctl_elem_value_set_subdevice(ctl, snd_pcm_info_get_subdevice(info));
+         snd_ctl_elem_value_set_name(ctl, SND_CTL_NAME_IEC958("", PLAYBACK,PCM_STREAM));
+         snd_ctl_elem_value_set_iec958(ctl, &spdif);
+         ctl_card = snd_pcm_info_get_card(info);
+         if (ctl_card < 0) {
+            fprintf(stderr, "Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card");
+            goto __diga_end;
+         }
+        sprintf(ctl_name, "hw:%d", ctl_card);
+        printf("hw:%d\n", ctl_card);
+        if ((err = snd_ctl_open(&ctl_handle, ctl_name, 0)) < 0) {
+           fprintf(stderr, "Unable to open the control interface '%s': %s", ctl_name, snd_strerror(err));                                                    
+           goto __diga_end;
+        }
+        if ((err = snd_ctl_elem_write(ctl_handle, ctl)) < 0) {
+           fprintf(stderr, "Unable to update the IEC958 control: %s", snd_strerror(err));
+           goto __diga_end;
+        }
+       snd_ctl_close(ctl_handle);
+       __diga_end:                                                       
+ 
+       }
+ #ifdef DEBUG	
+ 	bla2 = fopen("/tmp/ac3dump", "w");
+ #endif
+ 
+ 	{
+ 	  snd_pcm_hw_params_t *params;
+ 	  snd_pcm_sw_params_t *swparams;
+ 	  
+ 	  snd_pcm_hw_params_alloca(&params);
+ 	  snd_pcm_sw_params_alloca(&swparams);
+ 
+           err = snd_pcm_hw_params_any(handle, params);
+           if (err < 0) {
+              fprintf(stderr, "Broken configuration for this PCM: no configurations available");                                                                        
+ 	     return 2;
+ 	  }
+ 	  err = snd_pcm_hw_params_set_access(handle, params,
+ 	  				    SND_PCM_ACCESS_RW_INTERLEAVED);
+ 	  if (err < 0) {
+ 	    fprintf(stderr, "Access tyep not available");
+ 	    return 2;
+ 	  }
+ 	  err = snd_pcm_hw_params_set_format(handle, params, format);
+ 
+ 	  if (err < 0) {
+ 	    fprintf(stderr, "Sample format non available");
+ 	    return 2;
+ 	  }
+ 
+ 	  err = snd_pcm_hw_params_set_channels(handle, params, channels);
+ 
+ 	  if (err < 0) {
+ 	    fprintf(stderr, "Channels count non avaible");
+ 	    return 2;
+ 	  }
+ 
+           err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0);        assert(err >= 0);
+ 
+ 	  //err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size);
+ 
+ 	  snd_output_stdio_attach(&log, stderr, 0);
+ 
+ 	  err = snd_pcm_hw_params(handle, params);
+ 
+ 	  if (err < 0) {
+ 	    fprintf(stderr, "Cannot set buffer size\n");
+ 	    snd_pcm_hw_params_dump(params, log);
+ 	    return 2;
+ 	  }
+ 	  snd_pcm_sw_params_current(handle, swparams);
+ #ifdef DEBUG
+ 	  snd_pcm_sw_params_dump(swparams, log);
+ 	  snd_pcm_dump(handle, log);
+ #endif
+ 	}  
+ 	memset(buf, 0, sizeof(buf));
+ 
+ 	// Send some trailing zeros to avoid misdetecting the 
+ 	// first frame as PCM (works for DTT2500 at least)
+ 	for (c=0; c < 0; c++) {
+ 		write_pause_burst(0);
+ 	}
+ 	return 0;
+ }
+ 
+ void spdif_close()
+ {
+ 	// Cleanup
+ 	snd_pcm_close(handle);
+ #ifdef DEBUG
+ 	if (bla2)
+ 		fclose(bla2);
+ #endif	
+ }
diff -Ncr ac3play-0.3.0/ac3burst.h /home/deng/ac3play-0.3.0/ac3burst.h
*** ac3play-0.3.0/ac3burst.h	Wed Dec 31 19:00:00 1969
--- /home/deng/ac3play-0.3.0/ac3burst.h	Wed Jan 24 20:44:36 2001
***************
*** 0 ****
--- 1,5 ----
+ uint_32 buffer_syncframe(syncinfo_t*, uint_8 **, uint_8 *);
+ void output_spdif_burst(uint_8 *, uint_8 *);
+ void write_paust_burst(int);
+ uint_32 spdif_init(int acard, int adevice);
+ void spdif_close(void);
diff -Ncr ac3play-0.3.0/ac3play.c /home/deng/ac3play-0.3.0/ac3play.c
*** ac3play-0.3.0/ac3play.c	Mon Jun  5 01:54:36 2000
--- /home/deng/ac3play-0.3.0/ac3play.c	Wed Jan 24 20:44:36 2001
***************
*** 21,31 ****
   */
  
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <ac3.h>
  #include <ac3_internal.h>
! #include "ac3_pack.h"
  
  #define AC3_BLOCK_SIZE 2048
  static char inbuf[AC3_BLOCK_SIZE];
--- 21,34 ----
   */
  
  #include <stdio.h>
+ #include <fcntl.h>
  #include <string.h>
+ #include <errno.h>
+ #include <unistd.h>
  #include <stdlib.h>
  #include <ac3.h>
  #include <ac3_internal.h>
! #include "ac3burst.h"
  
  #define AC3_BLOCK_SIZE 2048
  static char inbuf[AC3_BLOCK_SIZE];
***************
*** 33,39 ****
  
  int main(int argc, char *argv[])
  {
!          FILE *bla;
  	int val,need_swab = 1;
  	int old_rate = -1;
  	int arg_file = 1; // Default location of filename
--- 36,42 ----
  
  int main(int argc, char *argv[])
  {
!         FILE* bla;
  	int val,need_swab = 1;
  	int old_rate = -1;
  	int arg_file = 1; // Default location of filename
***************
*** 67,86 ****
  			bla = stdin;
  	} else		
  		bla = fopen(argv[arg_file], "r");
! 	if (!bla) {
  			fprintf(stderr, "Invalid file\n");
  			return 1;
  	}		
  	
! 	if (spdif_init(acard, adevice) != 0)
  	  fprintf(stderr, "error openning digital output\n");
  
  
  	// Read the whole file
  	while((bytes_read = fread(inbuf, 1, AC3_BLOCK_SIZE, bla)) == AC3_BLOCK_SIZE)
  	{
! 	        output_spdif_pack(inbuf, inbuf + AC3_BLOCK_SIZE);
! 		
  	}
  
  	// cleanup
--- 70,90 ----
  			bla = stdin;
  	} else		
  		bla = fopen(argv[arg_file], "r");
! 	if (bla < 0) {
  			fprintf(stderr, "Invalid file\n");
  			return 1;
  	}		
  	
! 	if (spdif_init(acard, adevice) != 0) {
  	  fprintf(stderr, "error openning digital output\n");
+ 	  return 1;
+ 	}
  
  
  	// Read the whole file
  	while((bytes_read = fread(inbuf, 1, AC3_BLOCK_SIZE, bla)) == AC3_BLOCK_SIZE)
  	{
! 	       	output_spdif_burst(inbuf, inbuf + AC3_BLOCK_SIZE);
  	}
  
  	// cleanup