--- bplay-0.991.orig/bplay.c
+++ bplay-0.991/bplay.c
@@ -5,13 +5,16 @@
**
**
*/
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <limits.h>
+#include <stdint.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
@@ -24,6 +27,30 @@
#include <sys/soundcard.h>
+/* Needed for BYTE_ORDER and BIG/LITTLE_ENDIAN macros. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+# include <endian.h>
+# undef _BSD_SOURCE
+#else
+# include <endian.h>
+#endif
+
+#include <sys/types.h>
+#include <byteswap.h>
+
+/* Adapted from the byteorder macros in the Linux kernel. */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#else
+#define cpu_to_le32(x) bswap_32((x))
+#define cpu_to_le16(x) bswap_16((x))
+#endif
+
+#define le32_to_cpu(x) cpu_to_le32((x))
+#define le16_to_cpu(x) cpu_to_le16((x))
+
#include "fmtheaders.h"
/* Types and constants */
@@ -39,6 +66,7 @@
pid_t pid;
int recorder = 0;
int debug = 0;
+int verbose = 1;
/* Prototypes */
@@ -52,10 +80,14 @@
void ErrDie(char *err);
void Die(char *err);
-void getbcount(int speed, int bits, int stereo, int *bcount,
+void cleanup(int val, void *arg);
+
+void getbcount(int speed, int bits, int stereo, long long int *bcount,
int timelim, int samplim, int timejmp, int sampjmp, int *bjump);
-void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo);
-void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, int stereo);
+void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo,
+ int jump, int secs);
+void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits,
+ int stereo, int jump, int secs);
void playvoc(int thefd, char hd_buf[20]);
/* extern globals */
@@ -67,9 +99,9 @@
extern void init_sound(int recorder);
extern void snd_parm(int speed, int bits, int stereo);
extern void init_shm(void);
-extern void shmrec(int outfd, int bcount, int terminate);
-extern void diskread(int outfd, int bcount, char hd_buf[20], int terminate,
- int speed, int bits, int stereo);
+extern void shmrec(int outfd, long long int bcount, int terminate);
+extern void diskread(int outfd, long long int bcount, char hd_buf[20], int terminate,
+ int speed, int bits, int stereo, int jump);
extern volatile void audiowrite(void);
extern void initsems(int disks, int snds);
extern void cleanupsems(void);
@@ -77,14 +109,14 @@
int main(int argc, char *argv[])
{
-
+
int thefd; /* The file descriptor */
int speed, bits, stereo; /* Audio parameters */
int timelim; /* Recording time in secs */
int samplim; /* Recording time in samples */
int timejmp; /* Skip time in secs */
int sampjmp; /* Skip time in samples */
- int bcount; /* Number of bytes to record */
+ long long int bcount; /* Number of bytes to record */
int bjump; /* Number of bytes to skip */
int themask; /* Permission mask for file */
sndf_t filetype; /* The file type */
@@ -110,7 +142,7 @@
filetype = F_UNKNOWN;
mods = 0;
/* Parse the options */
- while ((optc = getopt(argc, argv, "Ss:b:t:T:j:J:rvwd:B:D:")) != -1)
+ while ((optc = getopt(argc, argv, "Ss:b:t:T:j:J:rvwd:B:D:q")) != -1)
{
switch(optc)
{
@@ -142,6 +174,9 @@
case 'J':
sampjmp = atoi(optarg);
break;
+ case 'q':
+ verbose = 0;
+ break;
case 'r':
filetype = F_RAW;
break;
@@ -172,7 +207,7 @@
"%s: setpriority: %s: continuing anyway\n",
progname, strerror(errno));
}
-
+
#endif
/* Drop out of suid mode before we open any files */
if(setreuid(geteuid(), getuid()) == -1)
@@ -199,12 +234,12 @@
/* Ok, get the mask for the opening the file */
themask = umask(0);
umask(themask);
- if ((thefd = open(argv[optind], O_CREAT | O_TRUNC | O_WRONLY,
+ if ((thefd = open(argv[optind], O_CREAT | O_TRUNC | O_WRONLY | O_LARGEFILE,
(~themask) & 0666)) == -1)
ErrDie(argv[optind]);
}
else
- if ((thefd = open(argv[optind], O_RDONLY)) == -1)
+ if ((thefd = open(argv[optind], O_RDONLY | O_LARGEFILE)) == -1)
ErrDie(argv[optind]);
}
@@ -223,20 +258,21 @@
#endif
/* Set up the shared buffers and semaphore blocks */
+ on_exit(cleanup, 0);
init_shm(); /* MUST be called after init_sound() */
/* Call the appropriate routine */
if (recorder)
{
if ((timelim == 0) && (samplim == 0)) {
- bcount = INT_MAX;
+ bcount = INT64_MAX - 1;
} else {
getbcount(speed, bits, stereo, &bcount, timelim,
samplim, timejmp, sampjmp,
&bjump);
}
if (debug)
- fprintf(stderr, "bcount: %d\n", bcount);
+ fprintf(stderr, "bcount: %lld\n", bcount);
if (filetype == F_UNKNOWN)
filetype = F_RAW; /* Change to change default */
@@ -244,9 +280,11 @@
{
case F_WAV:
/* Spit out header here... */
- fprintf(stderr, "Writing MS WAV sound file");
+ if (verbose)
+ fprintf(stdout, "Writing MS WAV sound file");
{
wavhead header;
+ unsigned long long int tmp;
char *riff = "RIFF";
char *wave = "WAVE";
@@ -254,34 +292,45 @@
char *data = "data";
memcpy(&(header.main_chunk), riff, 4);
- header.length = sizeof(wavhead) - 8 + bcount;
+ if ( (tmp = sizeof(wavhead) - 8 + bcount) >> 32 ) {
+ header.length = 0xFFFFFFFF; // do not overload the header
+ fprintf(stderr, " (WARNING: Resulting file size is larger than 4GiB, violating the WAVE format specification!)");
+ }
+ else
+ header.length = cpu_to_le32(tmp);
+
memcpy(&(header.chunk_type), wave, 4);
memcpy(&(header.sub_chunk), fmt, 4);
- header.sc_len = 16;
- header.format = 1;
- header.modus = stereo + 1;
- header.sample_fq = speed;
- header.byte_p_sec = ((bits > 8)? 2:1)*(stereo+1)*speed;
- header.byte_p_spl = ((bits > 8)? 2:1)*(stereo+1);
- header.bit_p_spl = bits;
+ header.sc_len = cpu_to_le32(16);
+ header.format = cpu_to_le16(1);
+ header.modus = cpu_to_le16(stereo + 1);
+ header.sample_fq = cpu_to_le32(speed);
+ header.byte_p_sec = cpu_to_le32(((bits > 8)?
+ 2:1)*(stereo+1)*speed);
+ header.byte_p_spl = cpu_to_le16(((bits > 8)?
+ 2:1)*(stereo+1));
+ header.bit_p_spl = cpu_to_le16(bits);
memcpy(&(header.data_chunk), data, 4);
- header.data_length = bcount;
+ header.data_length = ( bcount >> 32 ) ? 0xFFFFFFFF : cpu_to_le32(bcount) ; //FIXME see above, make sure that it works cleanly
write(thefd, &header, sizeof(header));
}
case F_RAW:
if (filetype == F_RAW)
- fprintf(stderr, "Writing raw sound file");
- fprintf(stderr, ", %dHz, %dbit, %s\n", speed, bits, (stereo)? "stereo":"");
+ if (verbose) {
+ fprintf(stdout, "Writing raw sound file");
+ fprintf(stdout, ", %dHz, %dbit, %s\n", speed, bits, (stereo)? "stereo":"");
+ }
snd_parm(speed, bits, stereo);
initsems(0, 1);
shmrec(thefd, bcount, 1);
break;
case F_VOC:
/* Spit out header here... */
- fprintf(stderr, "Writing CL VOC sound file");
- fprintf(stderr, ", %dHz, %dbit, %s\n", speed, bits, (stereo)? "stereo":"");
+ if (verbose) {
+ fprintf(stdout, "Writing CL VOC sound file");
+ fprintf(stdout, ", %dHz, %dbit, %s\n", speed, bits, (stereo)? "stereo":"");}
{
vochead header;
blockTC ablk;
@@ -291,23 +340,29 @@
for (i=0;i<20;i++)
header.Magic[i] = VOC_MAGIC[i];
- header.BlockOffset = 0x1a;
- header.Version = 0x0114;
- header.IDCode = 0x111F;
+ header.BlockOffset = cpu_to_le16(0x1a);
+ header.Version = cpu_to_le16(0x0114);
+ header.IDCode = cpu_to_le16(0x111F);
write(thefd, &header, sizeof(vochead));
snd_parm(speed, bits, stereo);
initsems(0, 1);
- i = (bcount >= 0xFFFFF2)? 0xFFFFF2 + 12 : bcount;
+ i = bcount;
+ if (bcount >= 0xFFFFF2)
+ {
+ i = 0xFFFFF2 + 12;
+ fprintf(stderr, "Warning: length is out of allowed range, consider using another sound format!\n");
+ }
+
ablk.BlockID = 9;
ablk.BlockLen[0] = (i + 12) & 0xFF;
ablk.BlockLen[1] = ((i + 12) >> 8) & 0xFF;
ablk.BlockLen[2] = ((i + 12) >> 16) & 0xFF;
- bblk.SamplesPerSec = speed;
+ bblk.SamplesPerSec = cpu_to_le32(speed);
bblk.BitsPerSample = bits;
bblk.Channels = stereo + 1;
- bblk.Format = (bits == 8)? 0 : 4;
+ bblk.Format = cpu_to_le16((bits == 8)? 0 : 4);
write(thefd, &ablk, sizeof(ablk));
write(thefd, &bblk, sizeof(bblk));
shmrec(thefd, i, 1);
@@ -338,9 +393,18 @@
if(strstr(hd_buf, VOC_MAGIC) != NULL)
playvoc(thefd, hd_buf);
else if(strstr(hd_buf, "RIFF") != NULL)
- playwav(thefd, hd_buf, mods, speed, bits, stereo);
+ {
+ if (sampjmp)
+ playwav(thefd, hd_buf, mods, speed, bits, stereo, sampjmp, 0);
+ else
+ playwav(thefd, hd_buf, mods, speed, bits, stereo, timejmp, 1);
+ }
else /* Assume raw data */
- playraw(thefd, hd_buf, speed, bits, stereo);
+ if (sampjmp)
+ playraw(thefd, hd_buf, speed, bits, stereo, sampjmp, 0);
+ else
+ playraw(thefd, hd_buf, speed, bits, stereo, timejmp, 1);
+
wait(NULL);
cleanupsems();
@@ -352,7 +416,7 @@
void Usage(void)
{
fprintf(stderr,
- "Usage: %s [-d device] [-B buffersize] [-S] [-s Hz] [-b 8|16] [-t secs] [-D level] [-r|-v|-w] [filename]\n",
+ "Usage: %s [-d device] [-B buffersize] [-S] [-s Hz] [-b 8|16] [-t secs] [-q] [-D level] [-r|-v|-w] [filename]\n",
progname);
exit(1);
}
@@ -370,12 +434,17 @@
exit(-1);
}
-void getbcount(int speed, int bits, int stereo, int *bcount,
+void cleanup(int val, void *arg)
+{
+ cleanupsems();
+}
+
+void getbcount(int speed, int bits, int stereo, long long int *bcount,
int timelim, int samplim, int timejmp, int sampjmp, int *bjump)
{
if(timelim)
{
- *bcount = speed*timelim*(bits/8);
+ *bcount = (long long) speed * (long long) timelim * (bits/8);
if (stereo) *bcount <<= 1;
}
if(samplim)
@@ -395,14 +464,20 @@
}
}
-void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo)
+void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo, int jump, int secs)
{
- fprintf(stderr, "Playing raw data : %d bit, Speed %d %s ...\n",
- bits, speed, (stereo)? "Stereo" : "Mono");
- diskread(thefd, 0, hd_buf, 1, speed, bits, stereo);
+ if (verbose) {
+ fprintf(stdout, "Playing raw data : %d bit, Speed %d %s ...\n",
+ bits, speed, (stereo)? "Stereo" : "Mono");
+ }
+
+ if (secs == 0)
+ jump = jump / speed;
+
+ diskread(thefd, 0, hd_buf, 1, speed, bits, stereo, jump);
}
-void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, int stereo)
+void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, int stereo, int jump, int secs)
{
wavhead wavhd;
int count;
@@ -410,24 +485,20 @@
memcpy((void*)&wavhd, (void*)hd_buf, 20);
count = read(thefd, ((char*)&wavhd)+20, sizeof(wavhd) - 20);
-#if __BYTE_ORDER == __BIG_ENDIAN
-#include<byteswap.h>
- /* let's do a bit of reordering */
- wavhd.length = bswap_32 (wavhd.length);
- wavhd.sc_len = bswap_32 (wavhd.sc_len);
- wavhd.format = bswap_16 (wavhd.format);
- wavhd.modus = bswap_16 (wavhd.modus);
-
- wavhd.sample_fq = bswap_32 (wavhd.sample_fq);
- wavhd.byte_p_sec = bswap_32 (wavhd.byte_p_sec);
-
- wavhd.byte_p_spl = bswap_16 (wavhd.byte_p_spl);
- wavhd.bit_p_spl = bswap_16 (wavhd.bit_p_spl);
-
- wavhd.data_chunk = bswap_32 (wavhd.data_chunk);
- wavhd.data_length = bswap_32 (wavhd.data_length);
-#endif
-
+wavhd.length = le32_to_cpu (wavhd.length);
+wavhd.sc_len = le32_to_cpu (wavhd.sc_len);
+wavhd.format = le16_to_cpu (wavhd.format);
+wavhd.modus = le16_to_cpu (wavhd.modus);
+
+wavhd.sample_fq = le32_to_cpu (wavhd.sample_fq);
+wavhd.byte_p_sec = le32_to_cpu (wavhd.byte_p_sec);
+
+wavhd.byte_p_spl = le16_to_cpu (wavhd.byte_p_spl);
+wavhd.bit_p_spl = le16_to_cpu (wavhd.bit_p_spl);
+
+wavhd.data_chunk = le32_to_cpu (wavhd.data_chunk);
+wavhd.data_length = le32_to_cpu (wavhd.data_length);
+
if(wavhd.format != 1) Die("input is not a PCM WAV file");
if (! (mods&MSPEED))
speed = wavhd.sample_fq;
@@ -435,9 +506,15 @@
bits = wavhd.bit_p_spl;
if (! (mods&MSTEREO))
stereo = wavhd.modus - 1;
- fprintf(stderr, "Playing WAVE : %d bit, Speed %d %s ...\n",
+ if (verbose) {
+ fprintf(stdout, "Playing WAVE : %d bit, Speed %d %s ...\n",
bits, speed, (stereo)? "Stereo" : "Mono");
- diskread(thefd, 0, NULL, 1, speed, bits, stereo);
+ }
+
+ if (secs == 0)
+ jump = jump / speed;
+
+ diskread(thefd, 0, NULL, 1, speed, bits, stereo, jump);
}
void playvoc(int thefd, char hd_buf[20])
@@ -445,17 +522,24 @@
int count;
int speed=0, bits=0, stereo=0;
int inloop=0, loop_times;
- long bytecount, loop_pos=0;
+ long long bytecount, loop_pos=0;
vochead vochd;
blockTC ccblock;
int lastblocktype = -1;
int quit = 0;
- fprintf(stderr, "Playing Creative Labs Voice file ...\n");
+ if (verbose) fprintf(stdout, "Playing Creative Labs Voice file ...\n");
memcpy((void*)&vochd, (void*)hd_buf, 20);
count = read(thefd, ((char*)&vochd)+20, sizeof(vochd) - 20);
- fprintf(stderr, "Format version %d.%d\n", vochd.Version>>8,
+
+ vochd.BlockOffset = le16_to_cpu(vochd.BlockOffset);
+ vochd.Version = le16_to_cpu(vochd.Version);
+ vochd.IDCode = le16_to_cpu(vochd.IDCode);
+
+ if (verbose) {
+ fprintf(stdout, "Format version %d.%d\n", vochd.Version>>8,
vochd.Version&0xFF);
+ }
if (vochd.IDCode != (~vochd.Version+0x1234))
fprintf(stderr, "Odd - version mismatch - %d != %d\n",
vochd.IDCode, ~vochd.Version+0x1234);
@@ -463,7 +547,7 @@
{
int off = vochd.BlockOffset - sizeof(vochd);
char *junk;
- junk = (char*) malloc(off);
+ junk = (char*) malloc(off);
read(thefd, junk, off);
}
while(!quit)
@@ -473,7 +557,7 @@
if (debug)
fprintf(stderr, "Terminating\n");
- diskread(thefd, -1, NULL, 1, speed, bits, stereo);
+ diskread(thefd, -1, NULL, 1, speed, bits, stereo, 0);
quit = 1;
continue;
}
@@ -494,7 +578,7 @@
stereo = 0;
}
bytecount = DATALEN(ccblock) -2;
- diskread(thefd, bytecount, NULL, 0, speed, bits, stereo);
+ diskread(thefd, bytecount, NULL, 0, speed, bits, stereo, 0);
lastblocktype = 1;
}
break;
@@ -502,6 +586,9 @@
{
blockT8 tblock;
read(thefd, (char*)&tblock, sizeof(tblock));
+
+ tblock.TimeConstant = le16_to_cpu(tblock.TimeConstant);
+
if(tblock.PackMethod != 0) Die("Non PCM VOC block");
speed = 256000000/(65536 - tblock.TimeConstant);
bits = 8;
@@ -514,13 +601,17 @@
{
blockT9 tblock;
read(thefd, (char*)&tblock, sizeof(tblock));
+
+ tblock.SamplesPerSec = le32_to_cpu(tblock.SamplesPerSec);
+ tblock.Format = le16_to_cpu(tblock.Format);
+
if(tblock.Format != 0 && tblock.Format != 4)
Die("Non PCM VOC block");
speed = tblock.SamplesPerSec;
bits = tblock.BitsPerSample;
stereo = tblock.Channels - 1;
bytecount = DATALEN(ccblock) - 12;
- diskread(thefd, bytecount, NULL, 0, speed, bits, stereo);
+ diskread(thefd, bytecount, NULL, 0, speed, bits, stereo, 0);
lastblocktype = 9;
}
break;
@@ -528,7 +619,7 @@
if (debug)
fprintf(stderr, "Terminating\n");
- diskread(thefd, -1, NULL, 1, speed, bits, stereo);
+ diskread(thefd, -1, NULL, 1, speed, bits, stereo, 0);
quit = 1;
break;
case 6:
@@ -568,11 +659,11 @@
{
int rd = 0, trgt = BUFSIZ;
char junkbuf[BUFSIZ];
-
+
fprintf(stderr, "Ignored\n");
bytecount = DATALEN(ccblock);
while(rd < bytecount)
- {
+ {//FIXME rd, trgt, not sure what this has to do with bytecount
if (rd + trgt > bytecount)
trgt = bytecount - rd;
count = read(thefd, junkbuf, trgt);