12
12
********************************************************************
14
last mod: $Id: buffer.c,v 1.13 2001/12/20 00:24:53 volsung Exp $
14
last mod: $Id: buffer.c,v 1.22 2003/09/01 20:15:19 volsung Exp $
16
16
********************************************************************/
28
28
#include "compat.h"
29
29
#include "buffer.h"
31
33
#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
32
34
#define MIN3(x,y,z) MIN(x,MIN(y,z))
33
35
#define MIN4(w,x,y,z) MIN( MIN(w,x), MIN(y,z) )
35
/* Special debugging code. THIS IS NOT PORTABLE! */
36
37
#ifdef DEBUG_BUFFER
38
#define DEBUG(x, y...) { fprintf (debugfile, "%d: " x "\n", getpid(), ## y); }
39
#define DEBUG(x) { fprintf (debugfile, "%d: " x "\n", getpid()); }
40
#define DEBUG1(x, y) { fprintf (debugfile, "%d: " x "\n", getpid(), y); }
41
#define DEBUG2(x, y, z) { fprintf (debugfile, "%d: " x "\n", getpid(), y, z); }
40
#define DEBUG(x, y...)
45
#define DEBUG2(x, y, z)
43
48
/* Macros that support debugging of threading structures */
45
#define LOCK_MUTEX(mutex) { DEBUG("Locking mutex %s.", #mutex); pthread_mutex_lock (&(mutex)); }
46
#define UNLOCK_MUTEX(mutex) { DEBUG("Unlocking mutex %s", #mutex); pthread_mutex_unlock(&(mutex)); }
47
#define COND_WAIT(cond, mutex) { DEBUG("Unlocking %s and waiting on %s", #mutex, #cond); pthread_cond_wait(&(cond), &(mutex)); }
48
#define COND_SIGNAL(cond) { DEBUG("Signalling %s", #cond); pthread_cond_signal(&(cond)); }
50
#define LOCK_MUTEX(mutex) { DEBUG1("Locking mutex %s.", #mutex); pthread_mutex_lock (&(mutex)); }
51
#define UNLOCK_MUTEX(mutex) { DEBUG1("Unlocking mutex %s", #mutex); pthread_mutex_unlock(&(mutex)); }
52
#define COND_WAIT(cond, mutex) { DEBUG2("Unlocking %s and waiting on %s", #mutex, #cond); pthread_cond_wait(&(cond), &(mutex)); }
53
#define COND_SIGNAL(cond) { DEBUG1("Signalling %s", #cond); pthread_cond_signal(&(cond)); }
55
extern signal_request_t sig_request; /* Need access to global cancel flag */
51
58
/* -------------------- Private Functions ------------------ */
85
93
buf_t *buf = (buf_t *)arg;
87
95
DEBUG("Enter buffer_thread_cleanup");
89
/* Cleanup thread data structures */
90
pthread_mutex_unlock(&buf->mutex);
91
pthread_mutex_destroy(&buf->mutex);
92
pthread_cond_destroy(&buf->playback_cond);
93
pthread_cond_destroy(&buf->write_cond);
202
204
/* This test is safe since curfill will never decrease and eos will
203
205
never be unset. */
204
while ( !(buf->eos && buf->curfill == 0) ) {
206
while ( !(buf->eos && buf->curfill == 0)) {
208
if (buf->cancel_flag || sig_request.cancel)
206
211
DEBUG("Check for something to play");
207
212
/* Block until we can play something */
213
218
DEBUG("Waiting for more data to play.");
214
219
COND_WAIT(buf->playback_cond, buf->mutex);
217
222
DEBUG("Ready to play");
219
224
UNLOCK_MUTEX(buf->mutex);
221
pthread_testcancel();
226
if (buf->cancel_flag || sig_request.cancel)
223
229
/* Don't need to lock buffer while running actions since position
224
230
won't change. We clear out any actions before we compute the
231
237
/* Need to be locked while we check things. */
232
238
write_amount = compute_dequeue_size(buf, buf->audio_chunk_size);
234
pthread_testcancel();
236
240
UNLOCK_MUTEX(buf->mutex);
238
242
/* No need to lock mutex here because the other thread will
239
243
NEVER reduce the number of bytes stored in the buffer */
240
DEBUG("Sending %d bytes to the audio device", write_amount);
241
buf->write_func(buf->buffer + buf->start, write_amount,
244
DEBUG1("Sending %d bytes to the audio device", write_amount);
245
write_amount = buf->write_func(buf->buffer + buf->start, write_amount,
242
246
/* Only set EOS if this is the last chunk */
243
247
write_amount == buf->curfill ? buf->eos : 0,
248
252
buf->curfill -= write_amount;
249
253
buf->position += write_amount;
250
254
buf->start = (buf->start + write_amount) % buf->size;
251
DEBUG("Updated buffer fill, curfill = %ld", buf->curfill);
255
DEBUG1("Updated buffer fill, curfill = %ld", buf->curfill);
253
257
/* If we've essentially emptied the buffer and prebuffering is enabled,
254
258
we need to do another prebuffering session */
275
279
long buf_write_pos; /* offset of first available write location */
276
280
size_t write_size;
278
DEBUG("Enter submit_data_chunk, size %d", size);
282
DEBUG1("Enter submit_data_chunk, size %d", size);
280
284
pthread_cleanup_push(buffer_mutex_unlock, buf);
282
286
/* Put the data into the buffer as space is made available */
287
while (size > 0 && !buf->abort_write) {
285
289
/* Section 1: Write a chunk of data */
286
290
DEBUG("Obtaining lock on buffer");
300
304
data += write_size;
301
305
size -= write_size;
302
306
buf->position_end += write_size;
303
DEBUG("writing chunk into buffer, curfill = %ld", buf->curfill);
307
DEBUG1("writing chunk into buffer, curfill = %ld", buf->curfill);
371
375
/* Initialize the buffer structure. */
372
DEBUG("buffer_create, size = %ld", size);
376
DEBUG1("buffer_create, size = %ld", size);
374
378
memset (buf, 0, sizeof(*buf));
430
434
void buffer_destroy (buf_t *buf)
432
436
DEBUG("buffer_destroy");
438
/* Cleanup pthread variables */
439
pthread_mutex_destroy(&buf->mutex);
440
COND_SIGNAL(buf->write_cond);
441
pthread_cond_destroy(&buf->write_cond);
442
COND_SIGNAL(buf->playback_cond);
443
pthread_cond_destroy(&buf->playback_cond);
481
493
DEBUG("Attempting to kill playback thread.");
484
pthread_cancel (buf->thread);
495
/* Flag the cancellation */
496
buf->cancel_flag = 1;
486
/* Signal all the playback condition to wake stuff up */
498
/* Signal the playback condition to wake stuff up */
487
499
COND_SIGNAL(buf->playback_cond);
489
501
pthread_join(buf->thread, NULL);
517
529
/* Put the data into the buffer as space is made available */
518
530
while (nbytes > 0) {
532
if (buf->abort_write)
520
535
DEBUG("Obtaining lock on buffer");
521
536
/* Block until we can read something */
522
537
if (buf->curfill == 0 && buf->eos)
523
538
break; /* No more data to read */
525
if (buf->curfill == 0 && (buf->prebuffering && !buf->eos)) {
540
if (buf->curfill == 0 || (buf->prebuffering && !buf->eos)) {
526
541
DEBUG("Waiting for more data to copy.");
527
542
COND_WAIT(buf->playback_cond, buf->mutex);
546
561
/* No need to lock mutex here because the other thread will
547
562
NEVER reduce the number of bytes stored in the buffer */
548
DEBUG("Copying %d bytes from the buffer", write_amount);
563
DEBUG1("Copying %d bytes from the buffer", write_amount);
549
564
memcpy(data, buf->buffer + buf->start, write_amount);
550
565
LOCK_MUTEX(buf->mutex);
553
568
data += write_amount;
554
569
nbytes -= write_amount;
555
570
buf->start = (buf->start + write_amount) % buf->size;
556
DEBUG("Updated buffer fill, curfill = %ld", buf->curfill);
571
DEBUG1("Updated buffer fill, curfill = %ld", buf->curfill);
558
573
/* Signal a waiting decoder thread that they can put more
559
574
audio into the buffer */
590
605
void buffer_abort_write (buf_t *buf)
592
DEBUG("buffer_mark_eos");
607
DEBUG("buffer_abort_write");
594
609
pthread_cleanup_push(buffer_mutex_unlock, buf);
596
611
LOCK_MUTEX(buf->mutex);
597
612
buf->abort_write = 1;
598
613
COND_SIGNAL(buf->write_cond);
614
COND_SIGNAL(buf->playback_cond);
599
615
UNLOCK_MUTEX(buf->mutex);
601
617
pthread_cleanup_pop(0);
729
745
if (buf->curfill > 0) {
730
DEBUG("Buffer curfill = %ld, going back to sleep.", buf->curfill);
746
DEBUG1("Buffer curfill = %ld, going back to sleep.", buf->curfill);
731
747
COND_WAIT(buf->write_cond, buf->mutex);