View | Details | Raw Unified | Return to bug 196051
Collapse All | Expand All

(-)files/patch-bug1021761 (-54 / +168 lines)
Lines 120-138 Link Here
120
   };
120
   };
121
   int i;
121
   int i;
122
 
122
 
123
diff --git media/libcubeb/src/cubeb_alsa.c media/libcubeb/src/cubeb_alsa.c
123
--- media/libcubeb/src/cubeb_alsa.c	2014-11-26 07:30:16.000000000 -0500
124
index a962553..1f780f4 100644
124
+++ media/libcubeb/src/cubeb_alsa.c	2014-12-16 22:03:04.000000000 -0500
125
--- media/libcubeb/src/cubeb_alsa.c
125
@@ -11,7 +11,10 @@
126
+++ media/libcubeb/src/cubeb_alsa.c
127
@@ -11,6 +11,7 @@
128
 #include <sys/time.h>
126
 #include <sys/time.h>
129
 #include <assert.h>
127
 #include <assert.h>
130
 #include <limits.h>
128
 #include <limits.h>
131
+#include <dlfcn.h>
129
+#include <dlfcn.h>
132
 #include <poll.h>
130
 #include <poll.h>
131
+#include <stdlib.h>
132
+#include <stdio.h>
133
 #include <unistd.h>
133
 #include <unistd.h>
134
 #include <alsa/asoundlib.h>
134
 #include <alsa/asoundlib.h>
135
@@ -24,6 +25,50 @@
135
 #include "cubeb/cubeb.h"
136
@@ -24,6 +27,51 @@
136
 
137
 
137
 #define ALSA_PA_PLUGIN "ALSA <-> PulseAudio PCM I/O Plugin"
138
 #define ALSA_PA_PLUGIN "ALSA <-> PulseAudio PCM I/O Plugin"
138
 
139
 
Lines 155-160 Link Here
155
+MAKE_TYPEDEF(snd_pcm_close);
156
+MAKE_TYPEDEF(snd_pcm_close);
156
+MAKE_TYPEDEF(snd_pcm_delay);
157
+MAKE_TYPEDEF(snd_pcm_delay);
157
+MAKE_TYPEDEF(snd_pcm_drain);
158
+MAKE_TYPEDEF(snd_pcm_drain);
159
+MAKE_TYPEDEF(snd_pcm_forward);
158
+MAKE_TYPEDEF(snd_pcm_frames_to_bytes);
160
+MAKE_TYPEDEF(snd_pcm_frames_to_bytes);
159
+MAKE_TYPEDEF(snd_pcm_get_params);
161
+MAKE_TYPEDEF(snd_pcm_get_params);
160
+/* snd_pcm_hw_params_alloca is actually a macro */
162
+/* snd_pcm_hw_params_alloca is actually a macro */
Lines 183-189 Link Here
183
 /* ALSA is not thread-safe.  snd_pcm_t instances are individually protected
185
 /* ALSA is not thread-safe.  snd_pcm_t instances are individually protected
184
    by the owning cubeb_stream's mutex.  snd_pcm_t creation and destruction
186
    by the owning cubeb_stream's mutex.  snd_pcm_t creation and destruction
185
    is not thread-safe until ALSA 1.0.24 (see alsa-lib.git commit 91c9c8f1),
187
    is not thread-safe until ALSA 1.0.24 (see alsa-lib.git commit 91c9c8f1),
186
@@ -64,6 +109,8 @@ struct cubeb {
188
@@ -64,6 +112,8 @@
187
      workaround is not required. */
189
      workaround is not required. */
188
   snd_config_t * local_config;
190
   snd_config_t * local_config;
189
   int is_pa;
191
   int is_pa;
Lines 192-221 Link Here
192
 };
194
 };
193
 
195
 
194
 enum stream_state {
196
 enum stream_state {
195
@@ -262,7 +309,7 @@ alsa_refill_stream(cubeb_stream * stm)
197
@@ -257,32 +307,35 @@
198
   long got;
199
   void * p;
200
   int draining;
201
+  unsigned pipefailures, againfailures;
196
 
202
 
203
   draining = 0;
204
 
197
   pthread_mutex_lock(&stm->mutex);
205
   pthread_mutex_lock(&stm->mutex);
198
 
206
 
199
-  r = snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents);
207
-  r = snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents);
200
+  r = WRAP(snd_pcm_poll_descriptors_revents)(stm->pcm, stm->fds, stm->nfds, &revents);
208
-  if (r < 0 || revents != POLLOUT) {
201
   if (r < 0 || revents != POLLOUT) {
209
-    /* This should be a stream error; it makes no sense for poll(2) to wake
202
     /* This should be a stream error; it makes no sense for poll(2) to wake
210
-       for this stream and then have the stream report that it's not ready.
203
        for this stream and then have the stream report that it's not ready.
211
-       Unfortunately, this does happen, so just bail out and try again. */
204
@@ -271,10 +318,10 @@ alsa_refill_stream(cubeb_stream * stm)
212
-    pthread_mutex_unlock(&stm->mutex);
205
     return RUNNING;
213
-    return RUNNING;
206
   }
214
-  }
207
 
215
-
208
-  avail = snd_pcm_avail_update(stm->pcm);
216
-  avail = snd_pcm_avail_update(stm->pcm);
209
+  avail = WRAP(snd_pcm_avail_update)(stm->pcm);
217
-  if (avail == -EPIPE) {
210
   if (avail == -EPIPE) {
211
-    snd_pcm_recover(stm->pcm, avail, 1);
218
-    snd_pcm_recover(stm->pcm, avail, 1);
212
-    avail = snd_pcm_avail_update(stm->pcm);
219
-    avail = snd_pcm_avail_update(stm->pcm);
220
-  }
221
+  for (pipefailures = 0;;) {
222
+    r = WRAP(snd_pcm_poll_descriptors_revents)(stm->pcm, stm->fds, stm->nfds, &revents);
223
+    if (r < 0 || revents != POLLOUT ||
224
+      (avail = WRAP(snd_pcm_avail_update)(stm->pcm)) == 0) {
225
+      /* This should be a stream error; it makes no sense for poll(2) to wake
226
+         for this stream and then have the stream report that it's not ready.
227
+         Unfortunately, this does happen, so just bail out and try again. */
228
+      pthread_mutex_unlock(&stm->mutex);
229
+      return RUNNING;
230
+    }
231
 
232
-  /* Failed to recover from an xrun, this stream must be broken. */
233
-  if (avail < 0) {
234
-    pthread_mutex_unlock(&stm->mutex);
235
-    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
236
-    return ERROR;
237
+    if (avail > 0)
238
+      break;
239
+    if (pipefailures++ > 11) {
240
+      fprintf(stderr, "%s: repeated failures from snd_pcm_avail_update, "
241
+              "giving up\n", __func__);
242
+      pthread_mutex_unlock(&stm->mutex);
243
+      stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
244
+      return ERROR;
245
+    }
213
+    WRAP(snd_pcm_recover)(stm->pcm, avail, 1);
246
+    WRAP(snd_pcm_recover)(stm->pcm, avail, 1);
214
+    avail = WRAP(snd_pcm_avail_update)(stm->pcm);
215
   }
247
   }
248
+  pipefailures = againfailures = 0;
216
 
249
 
217
   /* Failed to recover from an xrun, this stream must be broken. */
250
   /* This should never happen. */
218
@@ -293,8 +340,8 @@ alsa_refill_stream(cubeb_stream * stm)
251
   if ((unsigned int) avail > stm->buffer_size) {
252
@@ -293,8 +346,8 @@
219
      available to write.  If avail is still zero here, the stream must be in
253
      available to write.  If avail is still zero here, the stream must be in
220
      a funky state, so recover and try again. */
254
      a funky state, so recover and try again. */
221
   if (avail == 0) {
255
   if (avail == 0) {
Lines 226-232 Link Here
226
     if (avail <= 0) {
260
     if (avail <= 0) {
227
       pthread_mutex_unlock(&stm->mutex);
261
       pthread_mutex_unlock(&stm->mutex);
228
       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
262
       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
229
@@ -302,7 +349,7 @@ alsa_refill_stream(cubeb_stream * stm)
263
@@ -302,7 +355,7 @@
230
     }
264
     }
231
   }
265
   }
232
 
266
 
Lines 235-255 Link Here
235
   assert(p);
269
   assert(p);
236
 
270
 
237
   pthread_mutex_unlock(&stm->mutex);
271
   pthread_mutex_unlock(&stm->mutex);
238
@@ -327,10 +374,10 @@ alsa_refill_stream(cubeb_stream * stm)
272
@@ -311,10 +364,11 @@
273
   if (got < 0) {
274
     pthread_mutex_unlock(&stm->mutex);
275
     stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
276
+    free(p);
277
     return ERROR;
278
   }
279
   if (got > 0) {
280
-    snd_pcm_sframes_t wrote;
281
+    snd_pcm_sframes_t wrote, towrite = got;
282
 
283
     if (stm->params.format == CUBEB_SAMPLE_FLOAT32NE) {
284
       float * b = (float *) p;
285
@@ -327,14 +381,62 @@
239
         b[i] *= stm->volume;
286
         b[i] *= stm->volume;
240
       }
287
       }
241
     }
288
     }
242
-    wrote = snd_pcm_writei(stm->pcm, p, got);
289
-    wrote = snd_pcm_writei(stm->pcm, p, got);
243
+    wrote = WRAP(snd_pcm_writei)(stm->pcm, p, got);
290
-    if (wrote == -EPIPE) {
244
     if (wrote == -EPIPE) {
245
-      snd_pcm_recover(stm->pcm, wrote, 1);
291
-      snd_pcm_recover(stm->pcm, wrote, 1);
246
-      wrote = snd_pcm_writei(stm->pcm, p, got);
292
-      wrote = snd_pcm_writei(stm->pcm, p, got);
247
+      WRAP(snd_pcm_recover)(stm->pcm, wrote, 1);
293
-    }
248
+      wrote = WRAP(snd_pcm_writei)(stm->pcm, p, got);
294
-    assert(wrote >= 0 && wrote == got);
249
     }
295
-    stm->write_position += wrote;
250
     assert(wrote >= 0 && wrote == got);
296
-    gettimeofday(&stm->last_activity, NULL);
251
     stm->write_position += wrote;
297
+    for (;;) {
252
@@ -342,7 +389,7 @@ alsa_refill_stream(cubeb_stream * stm)
298
+      wrote = WRAP(snd_pcm_writei)(stm->pcm, p,
299
+        towrite > avail ? avail : towrite);
300
+      switch(wrote) {
301
+      case -EPIPE:
302
+        if (pipefailures++ > 3) {
303
+          fprintf(stderr, "%s: Too many underflows, giving up\n", __func__);
304
+          stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
305
+          pthread_mutex_unlock(&stm->mutex);
306
+          free(p);
307
+          return ERROR;
308
+        }
309
+        WRAP(snd_pcm_recover)(stm->pcm, wrote, 1);
310
+        continue;
311
+      case -EAGAIN:
312
+        if (againfailures++ > 3) {
313
+          fprintf(stderr, "%s: Too many -EAGAIN errors from snd_pcm_writei, "
314
+	    "giving up\n", __func__);
315
+          stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
316
+          pthread_mutex_unlock(&stm->mutex);
317
+          free(p);
318
+          return ERROR;
319
+        }
320
+        continue;
321
+      case -EBADFD:
322
+        fprintf(stderr, "%s: snc_pcm_writei returned -%s, giving up\n",
323
+                __func__, "EBADFD");
324
+        free(p);
325
+        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
326
+        pthread_mutex_unlock(&stm->mutex);
327
+        return ERROR;
328
+      }
329
+      if (wrote < 0) {
330
+        fprintf(stderr, "%s: snc_pcm_writei returned unexpected error %lld, "
331
+                "giving up\n", __func__, (long long)wrote);
332
+        free(p);
333
+        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
334
+        pthread_mutex_unlock(&stm->mutex);
335
+        return ERROR;
336
+      }
337
+      pipefailures = againfailures = 0;
338
+      stm->write_position += wrote;
339
+      gettimeofday(&stm->last_activity, NULL);
340
+      if (wrote > towrite) {
341
+        fprintf(stderr, "%s: snc_pcm_writei wrote %lld frames, which was more "
342
+	        "than we requested (%lld). This should not happen, giving up\n",
343
+                __func__, (long long)wrote, (long long)towrite);
344
+        free(p);
345
+        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
346
+        pthread_mutex_unlock(&stm->mutex);
347
+        return ERROR;
348
+      }
349
+      if (towrite == wrote)
350
+        break;
351
+      towrite -= wrote;
352
+    }
353
   }
354
   if (got != avail) {
355
     long buffer_fill = stm->buffer_size - (avail - got);
356
@@ -342,7 +444,7 @@
253
 
357
 
254
     /* Fill the remaining buffer with silence to guarantee one full period
358
     /* Fill the remaining buffer with silence to guarantee one full period
255
        has been written. */
359
        has been written. */
Lines 258-264 Link Here
258
 
362
 
259
     set_timeout(&stm->drain_timeout, buffer_time * 1000);
363
     set_timeout(&stm->drain_timeout, buffer_time * 1000);
260
 
364
 
261
@@ -453,26 +500,26 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
365
@@ -453,26 +555,26 @@
262
 
366
 
263
   slave_def = NULL;
367
   slave_def = NULL;
264
 
368
 
Lines 290-296 Link Here
290
     if (r < 0) {
394
     if (r < 0) {
291
       break;
395
       break;
292
     }
396
     }
293
@@ -481,7 +528,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
397
@@ -481,7 +583,7 @@
294
     if (r < 0 || r > (int) sizeof(node_name)) {
398
     if (r < 0 || r > (int) sizeof(node_name)) {
295
       break;
399
       break;
296
     }
400
     }
Lines 299-305 Link Here
299
     if (r < 0) {
403
     if (r < 0) {
300
       break;
404
       break;
301
     }
405
     }
302
@@ -490,7 +537,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
406
@@ -490,7 +592,7 @@
303
   } while (0);
407
   } while (0);
304
 
408
 
305
   if (slave_def) {
409
   if (slave_def) {
Lines 308-314 Link Here
308
   }
412
   }
309
 
413
 
310
   return NULL;
414
   return NULL;
311
@@ -513,22 +560,22 @@ init_local_config_with_workaround(char const * pcm_name)
415
@@ -513,22 +615,22 @@
312
 
416
 
313
   lconf = NULL;
417
   lconf = NULL;
314
 
418
 
Lines 335-341 Link Here
335
     if (r < 0) {
439
     if (r < 0) {
336
       break;
440
       break;
337
     }
441
     }
338
@@ -537,7 +584,7 @@ init_local_config_with_workaround(char const * pcm_name)
442
@@ -537,7 +639,7 @@
339
     if (r < 0 || r > (int) sizeof(node_name)) {
443
     if (r < 0 || r > (int) sizeof(node_name)) {
340
       break;
444
       break;
341
     }
445
     }
Lines 344-350 Link Here
344
     if (r < 0) {
448
     if (r < 0) {
345
       break;
449
       break;
346
     }
450
     }
347
@@ -548,12 +595,12 @@ init_local_config_with_workaround(char const * pcm_name)
451
@@ -548,12 +650,12 @@
348
     }
452
     }
349
 
453
 
350
     /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */
454
     /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */
Lines 359-365 Link Here
359
     if (r < 0) {
463
     if (r < 0) {
360
       break;
464
       break;
361
     }
465
     }
362
@@ -564,18 +611,18 @@ init_local_config_with_workaround(char const * pcm_name)
466
@@ -564,18 +666,18 @@
363
 
467
 
364
     /* Don't clobber an explicit existing handle_underrun value, set it only
468
     /* Don't clobber an explicit existing handle_underrun value, set it only
365
        if it doesn't already exist. */
469
        if it doesn't already exist. */
Lines 381-387 Link Here
381
     if (r < 0) {
485
     if (r < 0) {
382
       break;
486
       break;
383
     }
487
     }
384
@@ -583,7 +630,7 @@ init_local_config_with_workaround(char const * pcm_name)
488
@@ -583,7 +685,7 @@
385
     return lconf;
489
     return lconf;
386
   } while (0);
490
   } while (0);
387
 
491
 
Lines 390-396 Link Here
390
 
494
 
391
   return NULL;
495
   return NULL;
392
 }
496
 }
393
@@ -595,9 +642,9 @@ alsa_locked_pcm_open(snd_pcm_t ** pcm, snd_pcm_stream_t stream, snd_config_t * l
497
@@ -595,9 +697,9 @@
394
 
498
 
395
   pthread_mutex_lock(&cubeb_alsa_mutex);
499
   pthread_mutex_lock(&cubeb_alsa_mutex);
396
   if (local_config) {
500
   if (local_config) {
Lines 402-408 Link Here
402
   }
506
   }
403
   pthread_mutex_unlock(&cubeb_alsa_mutex);
507
   pthread_mutex_unlock(&cubeb_alsa_mutex);
404
 
508
 
405
@@ -610,7 +657,7 @@ alsa_locked_pcm_close(snd_pcm_t * pcm)
509
@@ -610,7 +712,7 @@
406
   int r;
510
   int r;
407
 
511
 
408
   pthread_mutex_lock(&cubeb_alsa_mutex);
512
   pthread_mutex_lock(&cubeb_alsa_mutex);
Lines 411-417 Link Here
411
   pthread_mutex_unlock(&cubeb_alsa_mutex);
515
   pthread_mutex_unlock(&cubeb_alsa_mutex);
412
 
516
 
413
   return r;
517
   return r;
414
@@ -667,12 +714,65 @@ alsa_init(cubeb ** context, char const * context_name)
518
@@ -667,12 +769,65 @@
415
   pthread_attr_t attr;
519
   pthread_attr_t attr;
416
   snd_pcm_t * dummy;
520
   snd_pcm_t * dummy;
417
 
521
 
Lines 478-484 Link Here
478
     cubeb_alsa_error_handler_set = 1;
582
     cubeb_alsa_error_handler_set = 1;
479
   }
583
   }
480
   pthread_mutex_unlock(&cubeb_alsa_mutex);
584
   pthread_mutex_unlock(&cubeb_alsa_mutex);
481
@@ -680,6 +780,8 @@ alsa_init(cubeb ** context, char const * context_name)
585
@@ -680,6 +835,8 @@
482
   ctx = calloc(1, sizeof(*ctx));
586
   ctx = calloc(1, sizeof(*ctx));
483
   assert(ctx);
587
   assert(ctx);
484
 
588
 
Lines 487-493 Link Here
487
   ctx->ops = &alsa_ops;
591
   ctx->ops = &alsa_ops;
488
 
592
 
489
   r = pthread_mutex_init(&ctx->mutex, NULL);
593
   r = pthread_mutex_init(&ctx->mutex, NULL);
490
@@ -729,7 +831,7 @@ alsa_init(cubeb ** context, char const * context_name)
594
@@ -729,7 +886,7 @@
491
        config fails with EINVAL, the PA PCM is too old for this workaround. */
595
        config fails with EINVAL, the PA PCM is too old for this workaround. */
492
     if (r == -EINVAL) {
596
     if (r == -EINVAL) {
493
       pthread_mutex_lock(&cubeb_alsa_mutex);
597
       pthread_mutex_lock(&cubeb_alsa_mutex);
Lines 496-502 Link Here
496
       pthread_mutex_unlock(&cubeb_alsa_mutex);
600
       pthread_mutex_unlock(&cubeb_alsa_mutex);
497
       ctx->local_config = NULL;
601
       ctx->local_config = NULL;
498
     } else if (r >= 0) {
602
     } else if (r >= 0) {
499
@@ -768,9 +870,13 @@ alsa_destroy(cubeb * ctx)
603
@@ -768,9 +925,13 @@
500
   pthread_mutex_destroy(&ctx->mutex);
604
   pthread_mutex_destroy(&ctx->mutex);
501
   free(ctx->fds);
605
   free(ctx->fds);
502
 
606
 
Lines 511-517 Link Here
511
     pthread_mutex_unlock(&cubeb_alsa_mutex);
615
     pthread_mutex_unlock(&cubeb_alsa_mutex);
512
   }
616
   }
513
 
617
 
514
@@ -838,7 +944,7 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
618
@@ -838,7 +999,7 @@
515
     return CUBEB_ERROR;
619
     return CUBEB_ERROR;
516
   }
620
   }
517
 
621
 
Lines 520-526 Link Here
520
   assert(r == 0);
624
   assert(r == 0);
521
 
625
 
522
   /* Ugly hack: the PA ALSA plugin allows buffer configurations that can't
626
   /* Ugly hack: the PA ALSA plugin allows buffer configurations that can't
523
@@ -848,23 +954,23 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
627
@@ -848,23 +1009,23 @@
524
     latency = latency < 500 ? 500 : latency;
628
     latency = latency < 500 ? 500 : latency;
525
   }
629
   }
526
 
630
 
Lines 550-556 Link Here
550
   assert((nfds_t) r == stm->nfds);
654
   assert((nfds_t) r == stm->nfds);
551
 
655
 
552
   r = pthread_cond_init(&stm->cond, NULL);
656
   r = pthread_cond_init(&stm->cond, NULL);
553
@@ -895,7 +1001,7 @@ alsa_stream_destroy(cubeb_stream * stm)
657
@@ -895,7 +1056,7 @@
554
   pthread_mutex_lock(&stm->mutex);
658
   pthread_mutex_lock(&stm->mutex);
555
   if (stm->pcm) {
659
   if (stm->pcm) {
556
     if (stm->state == DRAINING) {
660
     if (stm->state == DRAINING) {
Lines 559-565 Link Here
559
     }
663
     }
560
     alsa_locked_pcm_close(stm->pcm);
664
     alsa_locked_pcm_close(stm->pcm);
561
     stm->pcm = NULL;
665
     stm->pcm = NULL;
562
@@ -937,12 +1043,12 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
666
@@ -937,12 +1098,12 @@
563
     return CUBEB_ERROR;
667
     return CUBEB_ERROR;
564
   }
668
   }
565
 
669
 
Lines 574-580 Link Here
574
   if (rv < 0) {
678
   if (rv < 0) {
575
     return CUBEB_ERROR;
679
     return CUBEB_ERROR;
576
   }
680
   }
577
@@ -962,34 +1068,34 @@ alsa_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) {
681
@@ -962,34 +1123,34 @@
578
 
682
 
579
   /* get a pcm, disabling resampling, so we get a rate the
683
   /* get a pcm, disabling resampling, so we get a rate the
580
    * hardware/dmix/pulse/etc. supports. */
684
    * hardware/dmix/pulse/etc. supports. */
Lines 617-623 Link Here
617
 
721
 
618
   return CUBEB_OK;
722
   return CUBEB_OK;
619
 }
723
 }
620
@@ -1013,7 +1119,7 @@ alsa_stream_start(cubeb_stream * stm)
724
@@ -1013,7 +1174,7 @@
621
   ctx = stm->context;
725
   ctx = stm->context;
622
 
726
 
623
   pthread_mutex_lock(&stm->mutex);
727
   pthread_mutex_lock(&stm->mutex);
Lines 626-632 Link Here
626
   gettimeofday(&stm->last_activity, NULL);
730
   gettimeofday(&stm->last_activity, NULL);
627
   pthread_mutex_unlock(&stm->mutex);
731
   pthread_mutex_unlock(&stm->mutex);
628
 
732
 
629
@@ -1047,7 +1153,7 @@ alsa_stream_stop(cubeb_stream * stm)
733
@@ -1047,7 +1208,7 @@
630
   pthread_mutex_unlock(&ctx->mutex);
734
   pthread_mutex_unlock(&ctx->mutex);
631
 
735
 
632
   pthread_mutex_lock(&stm->mutex);
736
   pthread_mutex_lock(&stm->mutex);
Lines 635-641 Link Here
635
   pthread_mutex_unlock(&stm->mutex);
739
   pthread_mutex_unlock(&stm->mutex);
636
 
740
 
637
   return CUBEB_OK;
741
   return CUBEB_OK;
638
@@ -1063,8 +1169,8 @@ alsa_stream_get_position(cubeb_stream * stm, uint64_t * position)
742
@@ -1063,14 +1224,17 @@
639
   pthread_mutex_lock(&stm->mutex);
743
   pthread_mutex_lock(&stm->mutex);
640
 
744
 
641
   delay = -1;
745
   delay = -1;
Lines 646-652 Link Here
646
     *position = stm->last_position;
750
     *position = stm->last_position;
647
     pthread_mutex_unlock(&stm->mutex);
751
     pthread_mutex_unlock(&stm->mutex);
648
     return CUBEB_OK;
752
     return CUBEB_OK;
649
@@ -1089,7 +1195,7 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
753
   }
754
 
755
-  assert(delay >= 0);
756
+  if (delay < 0) {
757
+    WRAP(snd_pcm_forward)(stm->pcm, -delay);
758
+    delay = 0;
759
+  }
760
 
761
   *position = 0;
762
   if (stm->write_position >= (snd_pcm_uframes_t) delay) {
763
@@ -1089,7 +1253,7 @@
650
   snd_pcm_sframes_t delay;
764
   snd_pcm_sframes_t delay;
651
   /* This function returns the delay in frames until a frame written using
765
   /* This function returns the delay in frames until a frame written using
652
      snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */
766
      snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */

Return to bug 196051