mpg123-1.31.0
This commit is contained in:
@@ -68,6 +68,9 @@ static void catch_interrupt (void)
|
||||
intflag = TRUE;
|
||||
}
|
||||
|
||||
static int xfer_write_string(out123_handle *ao, int who, const char *buf);
|
||||
static int xfer_read_string(out123_handle *ao, int who, char **buf);
|
||||
static int read_buf(int fd, void *addr, size_t size, byte *prebuf, int *preoff, int presize);
|
||||
static int read_record(out123_handle *ao
|
||||
, int who, void **buf, byte *prebuf, int *preoff, int presize, size_t *recsize);
|
||||
static int buffer_loop(out123_handle *ao);
|
||||
@@ -198,6 +201,47 @@ static int buffer_cmd_finish(out123_handle *ao)
|
||||
}
|
||||
}
|
||||
|
||||
/* Serialization of tunable parameters to communicate them between
|
||||
main process and buffer. Make sure these two stay in sync ... */
|
||||
|
||||
static int write_parameters(out123_handle *ao, int who)
|
||||
{
|
||||
int fd = ao->buffermem->fd[who];
|
||||
if(
|
||||
GOOD_WRITEVAL(fd, ao->flags)
|
||||
&& GOOD_WRITEVAL(fd, ao->preload)
|
||||
&& GOOD_WRITEVAL(fd, ao->gain)
|
||||
&& GOOD_WRITEVAL(fd, ao->device_buffer)
|
||||
&& GOOD_WRITEVAL(fd, ao->verbose)
|
||||
&& !xfer_write_string(ao, who, ao->name)
|
||||
&& !xfer_write_string(ao, who, ao->bindir)
|
||||
)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int read_parameters(out123_handle *ao
|
||||
, int who, byte *prebuf, int *preoff, int presize)
|
||||
{
|
||||
int fd = ao->buffermem->fd[who];
|
||||
#define GOOD_READVAL_BUF(fd, val) \
|
||||
!read_buf(fd, &val, sizeof(val), prebuf, preoff, presize)
|
||||
if(
|
||||
GOOD_READVAL_BUF(fd, ao->flags)
|
||||
&& GOOD_READVAL_BUF(fd, ao->preload)
|
||||
&& GOOD_READVAL_BUF(fd, ao->gain)
|
||||
&& GOOD_READVAL_BUF(fd, ao->device_buffer)
|
||||
&& GOOD_READVAL_BUF(fd, ao->verbose)
|
||||
&& !read_record(ao, who, (void**)&ao->name, prebuf, preoff, presize, NULL)
|
||||
&& !read_record(ao, who, (void**)&ao->bindir, prebuf, preoff, presize, NULL)
|
||||
)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
#undef GOOD_READVAL_BUF
|
||||
}
|
||||
|
||||
int buffer_sync_param(out123_handle *ao)
|
||||
{
|
||||
int writerfd = ao->buffermem->fd[XF_WRITER];
|
||||
@@ -524,7 +568,7 @@ int xfer_write_string(out123_handle *ao, int who, const char *buf)
|
||||
}
|
||||
|
||||
|
||||
int xfer_read_string(out123_handle *ao, int who, char **buf)
|
||||
static int xfer_read_string(out123_handle *ao, int who, char **buf)
|
||||
{
|
||||
/* ao->errcode set in read_record() */
|
||||
return read_record(ao, who, (void**)buf, NULL, NULL, 0, NULL)
|
||||
@@ -536,7 +580,7 @@ int xfer_read_string(out123_handle *ao, int who, char **buf)
|
||||
This assumes responsible use and avoids needless checking of input.
|
||||
And, yes, it modifies the preoff argument!
|
||||
Returns 0 on success, modifies prebuffer fill. */
|
||||
int read_buf(int fd, void *addr, size_t size, byte *prebuf, int *preoff, int presize)
|
||||
static int read_buf(int fd, void *addr, size_t size, byte *prebuf, int *preoff, int presize)
|
||||
{
|
||||
size_t need = size;
|
||||
|
||||
|
||||
@@ -54,13 +54,4 @@ size_t buffer_write(out123_handle *ao, void *buffer, size_t bytes);
|
||||
/* Thin wrapper over xfermem giving the current buffer fill. */
|
||||
size_t buffer_fill(out123_handle *ao);
|
||||
|
||||
/* Special handler to safely read values from command channel with
|
||||
an additional buffer handed in. Exported for read_parameters(). */
|
||||
int read_buf(int fd, void *addr, size_t size
|
||||
, byte *prebuf, int *preoff, int presize);
|
||||
|
||||
/* Read/write strings from/to command channel. 0 on success. */
|
||||
int xfer_write_string(out123_handle *ao, int who, const char *buf);
|
||||
int xfer_read_string(out123_handle *ao, int who, char* *buf);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -361,49 +361,6 @@ out123_param_from(out123_handle *ao, out123_handle* from_ao)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NOXFERMEM
|
||||
/* Serialization of tunable parameters to communicate them between
|
||||
main process and buffer. Make sure these two stay in sync ... */
|
||||
|
||||
int write_parameters(out123_handle *ao, int who)
|
||||
{
|
||||
int fd = ao->buffermem->fd[who];
|
||||
if(
|
||||
GOOD_WRITEVAL(fd, ao->flags)
|
||||
&& GOOD_WRITEVAL(fd, ao->preload)
|
||||
&& GOOD_WRITEVAL(fd, ao->gain)
|
||||
&& GOOD_WRITEVAL(fd, ao->device_buffer)
|
||||
&& GOOD_WRITEVAL(fd, ao->verbose)
|
||||
&& !xfer_write_string(ao, who, ao->name)
|
||||
&& !xfer_write_string(ao, who, ao->bindir)
|
||||
)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read_parameters(out123_handle *ao
|
||||
, int who, byte *prebuf, int *preoff, int presize)
|
||||
{
|
||||
int fd = ao->buffermem->fd[who];
|
||||
#define GOOD_READVAL_BUF(fd, val) \
|
||||
!read_buf(fd, &val, sizeof(val), prebuf, preoff, presize)
|
||||
if(
|
||||
GOOD_READVAL_BUF(fd, ao->flags)
|
||||
&& GOOD_READVAL_BUF(fd, ao->preload)
|
||||
&& GOOD_READVAL_BUF(fd, ao->gain)
|
||||
&& GOOD_READVAL_BUF(fd, ao->device_buffer)
|
||||
&& GOOD_READVAL_BUF(fd, ao->verbose)
|
||||
&& !xfer_read_string(ao, who, &ao->name)
|
||||
&& !xfer_read_string(ao, who, &ao->bindir)
|
||||
)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
#undef GOOD_READVAL_BUF
|
||||
}
|
||||
#endif
|
||||
|
||||
int attribute_align_arg
|
||||
out123_open(out123_handle *ao, const char* driver, const char* device)
|
||||
{
|
||||
@@ -730,8 +687,14 @@ out123_play(out123_handle *ao, void *bytes, size_t count)
|
||||
sum += written;
|
||||
count -= written;
|
||||
}
|
||||
if(written < block && errno != EINTR)
|
||||
{
|
||||
if(written < block && errno != EINTR
|
||||
&& errno != EAGAIN
|
||||
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
|
||||
// Not all platforms define it (or only in more modern POSIX modes).
|
||||
// Standard says it is supposed to be a macro, so simple check here.
|
||||
&& errno != EWOULDBLOCK
|
||||
#endif
|
||||
){
|
||||
ao->errcode = OUT123_DEV_PLAY;
|
||||
if(!AOQUIET)
|
||||
merror( "Error in writing audio, wrote only %d of %d (%s?)!"
|
||||
|
||||
@@ -18,9 +18,16 @@
|
||||
NOTE: This particular num/size combination performs best under heavy
|
||||
loads for my system, however this may not be true for any hardware/OS out there.
|
||||
Generally, BUFFER_SIZE < 8k || NUM_BUFFERS > 16 || NUM_BUFFERS < 4 are not recommended.
|
||||
|
||||
Introducing user-settable device buffer. We fix 8 buffers, scale the individual
|
||||
buffer size, rounded/truncated a bit to not be too odd. The old default of 64K
|
||||
buffers leads to 2.97 s with CD-DA. Quite excessive. We will probably reduce this
|
||||
soon.
|
||||
*/
|
||||
#define BUFFER_SIZE 0x10000
|
||||
#define NUM_BUFFERS 8 /* total 512k roughly 2.5 sec of CD quality sound */
|
||||
#define DEFAULT_DEVICE_BUFFER 0.25
|
||||
// Buffers are multiples of this.
|
||||
#define BUFFER_GRANULARITY 256
|
||||
#define NUM_BUFFERS 8
|
||||
|
||||
static void wait_for_buffer(WAVEHDR* hdr, HANDLE hEvent);
|
||||
static void drain_win32(out123_handle *ao);
|
||||
@@ -29,6 +36,7 @@ static void drain_win32(out123_handle *ao);
|
||||
struct queue_state
|
||||
{
|
||||
WAVEHDR buffer_headers[NUM_BUFFERS];
|
||||
size_t bufsize;
|
||||
/* The next buffer to be filled and put in playback */
|
||||
int next_buffer;
|
||||
/* Buffer playback completion event */
|
||||
@@ -100,11 +108,18 @@ static int open_win32(out123_handle *ao)
|
||||
ereturn(-1, "Unable to open wave output device.");
|
||||
}
|
||||
|
||||
state->bufsize = (size_t)( (double)
|
||||
(ao->device_buffer > 0. ? ao->device_buffer : DEFAULT_DEVICE_BUFFER)
|
||||
* out_fmt.nAvgBytesPerSec / NUM_BUFFERS / BUFFER_GRANULARITY);
|
||||
if(state->bufsize < 1)
|
||||
state->bufsize = 1;
|
||||
state->bufsize *= BUFFER_GRANULARITY;
|
||||
|
||||
/* Reset event from the "device open" message */
|
||||
ResetEvent(state->play_done_event);
|
||||
/* Allocate playback buffers */
|
||||
for(i = 0; i < NUM_BUFFERS; i++)
|
||||
if(!(state->buffer_headers[i].lpData = (LPSTR)malloc(BUFFER_SIZE)))
|
||||
if(!(state->buffer_headers[i].lpData = (LPSTR)malloc(state->bufsize)))
|
||||
{
|
||||
ereturn(-1, "Out of memory for playback buffers.");
|
||||
}
|
||||
@@ -112,7 +127,7 @@ static int open_win32(out123_handle *ao)
|
||||
{
|
||||
/* Tell waveOutPrepareHeader the maximum value of dwBufferLength
|
||||
we will ever send */
|
||||
state->buffer_headers[i].dwBufferLength = BUFFER_SIZE;
|
||||
state->buffer_headers[i].dwBufferLength = state->bufsize;
|
||||
state->buffer_headers[i].dwFlags = 0;
|
||||
res = waveOutPrepareHeader(state->waveout, &state->buffer_headers[i], sizeof(WAVEHDR));
|
||||
if(res != MMSYSERR_NOERROR) ereturn(-1, "Can't write to audio output device (prepare).");
|
||||
@@ -231,13 +246,13 @@ static int write_win32(out123_handle *ao, unsigned char *buf, int len)
|
||||
wait_for_buffer(hdr, state->play_done_event);
|
||||
|
||||
/* Now see how much we want to stuff in and then stuff it in. */
|
||||
bufill = BUFFER_SIZE - hdr->dwBufferLength;
|
||||
bufill = state->bufsize - hdr->dwBufferLength;
|
||||
if(len < bufill) bufill = len;
|
||||
|
||||
rest_len = len - bufill;
|
||||
memcpy(hdr->lpData + hdr->dwBufferLength, buf, bufill);
|
||||
hdr->dwBufferLength += bufill;
|
||||
if(hdr->dwBufferLength == BUFFER_SIZE)
|
||||
if(hdr->dwBufferLength == state->bufsize)
|
||||
{ /* Send the buffer out when it's full. */
|
||||
hdr->dwFlags |= WHDR_PREPARED;
|
||||
|
||||
|
||||
@@ -117,9 +117,5 @@ struct audio_format_name {
|
||||
char *sname;
|
||||
};
|
||||
|
||||
int write_parameters(out123_handle *ao, int fd);
|
||||
int read_parameters(out123_handle *ao
|
||||
, int fd, byte *prebuf, int *preoff, int presize);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user