diff mbox

Aplay Fails When Reading From stdin

Message ID s5h4ljmbnnj.wl-tiwai@suse.de (mailing list archive)
State New, archived
Headers show

Commit Message

Takashi Iwai May 5, 2018, 6:51 a.m. UTC
On Fri, 04 May 2018 21:57:35 +0200,
Jay Foster wrote:
> 
> 
> 
> On 5/4/2018 12:47 PM, Takashi Iwai wrote:
> > On Fri, 04 May 2018 19:51:05 +0200,
> > Jay Foster wrote:
> >> I recently updated may alsa from 1.1.4.1 to 1.1.6.  I now noticed that
> >> aplay does not work properly (the same as 1.1.4.1) when reading the
> >> sound file data from stdin.  This might have something to do with the
> >> recent change with reading the sound file header.
> >>
> >> With the previous version of aplay, aplay would report:
> >>
> >> Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono
> >>
> >> With 1.1.6, aplay reports:
> >>
> >> Playing raw data 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
> >>
> >> This results in static/noise output.  If I explicitly add the '-f
> >> S16_LE -r 22050' options to aplay, then it does play correctly.
> >>
> >> Is this a known bug and is there a fix?
> > It works fine on my system.
> >
> > % aplay test.wav
> > Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
> >
> > % aplay < ~/test/test.wav
> > Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
> >
> > % aplay --version
> > aplay: version 1.1.6 by Jaroslav Kysela <perex@perex.cz>
> >
> >
> > Takashi
> >
> >
> Well, it does not work for me:
> 
> cat bird-calls.wav | /usr/bin/aplay -Dplughw:0 --
> Playing raw data 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
> ^CAborted by signal Interrupt...
> aplay: pcm_write:2051: write error: Interrupted system call
> 
> aplay -Dplughw:0 bird-calls.wav
> Playing WAVE 'bird-calls.wav' : Signed 16 bit Little Endian, Rate
> 44100 Hz, Stereo
> 
> Looks like aplay may now have problems reading from stdin if stdin is
> a pipe.

OK, now I see it.  It's in the safety check of file stat.
The fix patch is below.


thanks,

Takashi

---

Comments

Jay Foster May 7, 2018, 3:37 p.m. UTC | #1
On 5/4/2018 11:51 PM, Takashi Iwai wrote:
> On Fri, 04 May 2018 21:57:35 +0200,
> Jay Foster wrote:
>>
>>
>> On 5/4/2018 12:47 PM, Takashi Iwai wrote:
>>> On Fri, 04 May 2018 19:51:05 +0200,
>>> Jay Foster wrote:
>>>> I recently updated may alsa from 1.1.4.1 to 1.1.6.  I now noticed that
>>>> aplay does not work properly (the same as 1.1.4.1) when reading the
>>>> sound file data from stdin.  This might have something to do with the
>>>> recent change with reading the sound file header.
>>>>
>>>> With the previous version of aplay, aplay would report:
>>>>
>>>> Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono
>>>>
>>>> With 1.1.6, aplay reports:
>>>>
>>>> Playing raw data 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
>>>>
>>>> This results in static/noise output.  If I explicitly add the '-f
>>>> S16_LE -r 22050' options to aplay, then it does play correctly.
>>>>
>>>> Is this a known bug and is there a fix?
>>> It works fine on my system.
>>>
>>> % aplay test.wav
>>> Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
>>>
>>> % aplay < ~/test/test.wav
>>> Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
>>>
>>> % aplay --version
>>> aplay: version 1.1.6 by Jaroslav Kysela <perex@perex.cz>
>>>
>>>
>>> Takashi
>>>
>>>
>> Well, it does not work for me:
>>
>> cat bird-calls.wav | /usr/bin/aplay -Dplughw:0 --
>> Playing raw data 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
>> ^CAborted by signal Interrupt...
>> aplay: pcm_write:2051: write error: Interrupted system call
>>
>> aplay -Dplughw:0 bird-calls.wav
>> Playing WAVE 'bird-calls.wav' : Signed 16 bit Little Endian, Rate
>> 44100 Hz, Stereo
>>
>> Looks like aplay may now have problems reading from stdin if stdin is
>> a pipe.
> OK, now I see it.  It's in the safety check of file stat.
> The fix patch is below.
>
>
> thanks,
>
> Takashi
>
> ---
> diff --git a/aplay/aplay.c b/aplay/aplay.c
> index bbd7fffa04fc..2a851a73ba6e 100644
> --- a/aplay/aplay.c
> +++ b/aplay/aplay.c
> @@ -2808,7 +2808,7 @@ static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *n
>   	snd_pcm_nonblock(handle, nonblock);
>   }
>   
> -static int read_header(int *loaded, int header_size)
> +static int read_header(int *loaded, int header_size, int is_stdin)
>   {
>   	int ret;
>   	struct stat buf;
> @@ -2821,7 +2821,7 @@ static int read_header(int *loaded, int header_size)
>   
>   	/* don't be adventurous, get out if file size is smaller than
>   	 * requested header size */
> -	if (buf.st_size < header_size)
> +	if (!is_stdin && buf.st_size < header_size)
>   		return -1;
>   
>   	if (*loaded < header_size) {
> @@ -2836,9 +2836,9 @@ static int read_header(int *loaded, int header_size)
>   	return 0;
>   }
>   
> -static int playback_au(char *name, int *loaded)
> +static int playback_au(char *name, int *loaded, int is_stdin)
>   {
> -	if (read_header(loaded, sizeof(AuHeader)) < 0)
> +	if (read_header(loaded, sizeof(AuHeader), is_stdin) < 0)
>   		return -1;
>   
>   	if (test_au(fd, audiobuf) < 0)
> @@ -2851,11 +2851,11 @@ static int playback_au(char *name, int *loaded)
>   	return 0;
>   }
>   
> -static int playback_voc(char *name, int *loaded)
> +static int playback_voc(char *name, int *loaded, int is_stdin)
>   {
>   	int ofs;
>   
> -	if (read_header(loaded, sizeof(VocHeader)) < 0)
> +	if (read_header(loaded, sizeof(VocHeader), is_stdin) < 0)
>   		return -1;
>   
>   	if ((ofs = test_vocfile(audiobuf)) < 0)
> @@ -2867,11 +2867,11 @@ static int playback_voc(char *name, int *loaded)
>   	return 0;
>   }
>   
> -static int playback_wave(char *name, int *loaded)
> +static int playback_wave(char *name, int *loaded, int is_stdin)
>   {
>   	ssize_t dtawave;
>   
> -	if (read_header(loaded, sizeof(WaveHeader)) < 0)
> +	if (read_header(loaded, sizeof(WaveHeader), is_stdin) < 0)
>   		return -1;
>   
>   	if ((dtawave = test_wavefile(fd, audiobuf, *loaded)) < 0)
> @@ -2883,7 +2883,7 @@ static int playback_wave(char *name, int *loaded)
>   	return 0;
>   }
>   
> -static int playback_raw(char *name, int *loaded)
> +static int playback_raw(char *name, int *loaded, int is_stdin)
>   {
>   	init_raw_data();
>   	pbrec_count = calc_count();
> @@ -2899,13 +2899,16 @@ static int playback_raw(char *name, int *loaded)
>   static void playback(char *name)
>   {
>   	int loaded = 0;
> +	int is_stdin;
>   
>   	pbrec_count = LLONG_MAX;
>   	fdcount = 0;
>   	if (!name || !strcmp(name, "-")) {
> +		is_stdin = 1;
>   		fd = fileno(stdin);
>   		name = "stdin";
>   	} else {
> +		is_stdin = 0;
>   		init_stdin();
>   		if ((fd = open(name, O_RDONLY, 0)) == -1) {
>   			perror(name);
> @@ -2915,23 +2918,23 @@ static void playback(char *name)
>   
>   	switch(file_type) {
>   	case FORMAT_AU:
> -		playback_au(name, &loaded);
> +		playback_au(name, &loaded, is_stdin);
>   		break;
>   	case FORMAT_VOC:
> -		playback_voc(name, &loaded);
> +		playback_voc(name, &loaded, is_stdin);
>   		break;
>   	case FORMAT_WAVE:
> -		playback_wave(name, &loaded);
> +		playback_wave(name, &loaded, is_stdin);
>   		break;
>   	case FORMAT_RAW:
> -		playback_raw(name, &loaded);
> +		playback_raw(name, &loaded, is_stdin);
>   		break;
>   	default:
>   		/* parse the file header */
> -		if (playback_au(name, &loaded) < 0 &&
> -		    playback_voc(name, &loaded) < 0 &&
> -		    playback_wave(name, &loaded) < 0)
> -			playback_raw(name, &loaded); /* should be raw data */
> +		if (playback_au(name, &loaded, is_stdin) < 0 &&
> +		    playback_voc(name, &loaded, is_stdin) < 0 &&
> +		    playback_wave(name, &loaded, is_stdin) < 0)
> +			playback_raw(name, &loaded, is_stdin); /* should be raw data */
>   		break;
>           }
>   
>
>
Thanks.  That works.
Jay
diff mbox

Patch

diff --git a/aplay/aplay.c b/aplay/aplay.c
index bbd7fffa04fc..2a851a73ba6e 100644
--- a/aplay/aplay.c
+++ b/aplay/aplay.c
@@ -2808,7 +2808,7 @@  static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *n
 	snd_pcm_nonblock(handle, nonblock);
 }
 
-static int read_header(int *loaded, int header_size)
+static int read_header(int *loaded, int header_size, int is_stdin)
 {
 	int ret;
 	struct stat buf;
@@ -2821,7 +2821,7 @@  static int read_header(int *loaded, int header_size)
 
 	/* don't be adventurous, get out if file size is smaller than
 	 * requested header size */
-	if (buf.st_size < header_size)
+	if (!is_stdin && buf.st_size < header_size)
 		return -1;
 
 	if (*loaded < header_size) {
@@ -2836,9 +2836,9 @@  static int read_header(int *loaded, int header_size)
 	return 0;
 }
 
-static int playback_au(char *name, int *loaded)
+static int playback_au(char *name, int *loaded, int is_stdin)
 {
-	if (read_header(loaded, sizeof(AuHeader)) < 0)
+	if (read_header(loaded, sizeof(AuHeader), is_stdin) < 0)
 		return -1;
 
 	if (test_au(fd, audiobuf) < 0)
@@ -2851,11 +2851,11 @@  static int playback_au(char *name, int *loaded)
 	return 0;
 }
 
-static int playback_voc(char *name, int *loaded)
+static int playback_voc(char *name, int *loaded, int is_stdin)
 {
 	int ofs;
 
-	if (read_header(loaded, sizeof(VocHeader)) < 0)
+	if (read_header(loaded, sizeof(VocHeader), is_stdin) < 0)
 		return -1;
 
 	if ((ofs = test_vocfile(audiobuf)) < 0)
@@ -2867,11 +2867,11 @@  static int playback_voc(char *name, int *loaded)
 	return 0;
 }
 
-static int playback_wave(char *name, int *loaded)
+static int playback_wave(char *name, int *loaded, int is_stdin)
 {
 	ssize_t dtawave;
 
-	if (read_header(loaded, sizeof(WaveHeader)) < 0)
+	if (read_header(loaded, sizeof(WaveHeader), is_stdin) < 0)
 		return -1;
 
 	if ((dtawave = test_wavefile(fd, audiobuf, *loaded)) < 0)
@@ -2883,7 +2883,7 @@  static int playback_wave(char *name, int *loaded)
 	return 0;
 }
 
-static int playback_raw(char *name, int *loaded)
+static int playback_raw(char *name, int *loaded, int is_stdin)
 {
 	init_raw_data();
 	pbrec_count = calc_count();
@@ -2899,13 +2899,16 @@  static int playback_raw(char *name, int *loaded)
 static void playback(char *name)
 {
 	int loaded = 0;
+	int is_stdin;
 
 	pbrec_count = LLONG_MAX;
 	fdcount = 0;
 	if (!name || !strcmp(name, "-")) {
+		is_stdin = 1;
 		fd = fileno(stdin);
 		name = "stdin";
 	} else {
+		is_stdin = 0;
 		init_stdin();
 		if ((fd = open(name, O_RDONLY, 0)) == -1) {
 			perror(name);
@@ -2915,23 +2918,23 @@  static void playback(char *name)
 
 	switch(file_type) {
 	case FORMAT_AU:
-		playback_au(name, &loaded);
+		playback_au(name, &loaded, is_stdin);
 		break;
 	case FORMAT_VOC:
-		playback_voc(name, &loaded);
+		playback_voc(name, &loaded, is_stdin);
 		break;
 	case FORMAT_WAVE:
-		playback_wave(name, &loaded);
+		playback_wave(name, &loaded, is_stdin);
 		break;
 	case FORMAT_RAW:
-		playback_raw(name, &loaded);
+		playback_raw(name, &loaded, is_stdin);
 		break;
 	default:
 		/* parse the file header */
-		if (playback_au(name, &loaded) < 0 &&
-		    playback_voc(name, &loaded) < 0 &&
-		    playback_wave(name, &loaded) < 0)
-			playback_raw(name, &loaded); /* should be raw data */
+		if (playback_au(name, &loaded, is_stdin) < 0 &&
+		    playback_voc(name, &loaded, is_stdin) < 0 &&
+		    playback_wave(name, &loaded, is_stdin) < 0)
+			playback_raw(name, &loaded, is_stdin); /* should be raw data */
 		break;
         }