~ubuntu-branches/debian/sid/audacious-plugins/sid

« back to all changes in this revision

Viewing changes to src/alsa/alsa.c

  • Committer: Bazaar Package Importer
  • Author(s): Bilal Akhtar
  • Date: 2011-04-10 18:56:21 UTC
  • mfrom: (1.1.14 upstream) (2.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110410185621-7eg1k5a7v3f4aqrn
Tags: 2.4.4-1
* New upstream release.
  - Fix FTBFS with GCC 4.5 (Closes: #621989)
* Upload to unstable.
* debian/control:
  - Update versioned dependencies according to upstream changes.
  - Bump Standards-Version to 3.9.2 (no changes needed).
  - Since the package will be building against the new FFMpeg libs,
    fix the problem of depending on old uninstallable libav*
    packages (Closes: #617603)

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 * the use of this software.
18
18
 */
19
19
 
 
20
/*
 
21
 * Because ALSA is not thread-safe (despite claims to the contrary) we use non-
 
22
 * blocking output in the pump thread with the mutex locked, then unlock the
 
23
 * mutex and wait for more room in the buffer with poll() while other threads
 
24
 * lock the mutex and read the output time.  We poll a pipe of our own as well
 
25
 * as the ALSA file descriptors so that we can wake up the pump thread when
 
26
 * needed.
 
27
 *
 
28
 * When paused, or when it comes to the end of the data given it, the pump will
 
29
 * wait on alsa_cond for the signal to continue.  When it has more data waiting,
 
30
 * however, it will be sitting in poll() waiting for ALSA's signal that more
 
31
 * data can be written.
 
32
 *
 
33
 * * After adding more data to the buffer, and after resuming from pause,
 
34
 *   signal on alsa_cond to wake the pump.  (There is no need to signal when
 
35
 *   entering pause.)
 
36
 * * After setting the pump_quit flag, signal on alsa_cond AND the poll_pipe
 
37
 *   before joining the thread.
 
38
 */
 
39
 
 
40
#include <assert.h>
 
41
#include <errno.h>
 
42
#include <poll.h>
 
43
#include <pthread.h>
 
44
#include <stdint.h>
 
45
#include <time.h>
 
46
#include <unistd.h>
 
47
 
 
48
#include <alsa/asoundlib.h>
 
49
#include <glib.h>
 
50
 
 
51
#include <audacious/audconfig.h>
 
52
#include <audacious/debug.h>
 
53
 
20
54
#include "alsa.h"
21
55
 
22
 
#define LEAST_BUFFER 100 /* milliseconds */
23
 
 
24
 
GMutex * alsa_mutex;
 
56
#define CHECK_VAL_RECOVER(value, function, ...) \
 
57
do { \
 
58
    (value) = function (__VA_ARGS__); \
 
59
    if ((value) < 0) { \
 
60
        CHECK (snd_pcm_recover, alsa_handle, (value), 0); \
 
61
        CHECK_VAL ((value), function, __VA_ARGS__); \
 
62
    } \
 
63
} while (0)
 
64
 
 
65
#define CHECK_RECOVER(function, ...) \
 
66
do { \
 
67
    int error2; \
 
68
    CHECK_VAL_RECOVER (error2, function, __VA_ARGS__); \
 
69
} while (0)
 
70
 
25
71
static snd_pcm_t * alsa_handle;
26
 
static GCond * alsa_cond;
27
 
static gboolean initted;
 
72
static char alsa_initted;
 
73
static pthread_mutex_t alsa_mutex = PTHREAD_MUTEX_INITIALIZER;
 
74
static pthread_cond_t alsa_cond = PTHREAD_COND_INITIALIZER;
28
75
 
29
76
static snd_pcm_format_t alsa_format;
30
 
static gint alsa_channels, alsa_rate;
 
77
static int alsa_channels, alsa_rate;
31
78
 
32
79
static void * alsa_buffer;
33
 
static gint alsa_buffer_length, alsa_buffer_data_start, alsa_buffer_data_length;
34
 
static gboolean read_locked;
35
 
 
36
 
static gint64 alsa_time; /* microseconds */
37
 
static gboolean alsa_paused;
38
 
static gint alsa_paused_time;
39
 
 
40
 
static gboolean pump_quit;
41
 
static GThread * pump_thread;
 
80
static int alsa_buffer_length, alsa_buffer_data_start, alsa_buffer_data_length;
 
81
static int alsa_period; /* milliseconds */
 
82
 
 
83
static int64_t alsa_written; /* frames */
 
84
static char alsa_prebuffer, alsa_paused;
 
85
static int alsa_paused_time; /* milliseconds */
 
86
 
 
87
static int poll_pipe[2];
 
88
static int poll_count;
 
89
static struct pollfd * poll_handles;
 
90
 
 
91
static char pump_quit;
 
92
static pthread_t pump_thread;
42
93
 
43
94
static snd_mixer_t * alsa_mixer;
44
95
static snd_mixer_elem_t * alsa_mixer_element;
45
96
 
 
97
static char poll_setup (void)
 
98
{
 
99
    if (pipe (poll_pipe))
 
100
    {
 
101
        ERROR ("Failed to create pipe: %s.\n", strerror (errno));
 
102
        return 0;
 
103
    }
 
104
 
 
105
    if (fcntl (poll_pipe[0], F_SETFL, O_NONBLOCK))
 
106
    {
 
107
        ERROR ("Failed to set O_NONBLOCK on pipe: %s.\n", strerror (errno));
 
108
        close (poll_pipe[0]);
 
109
        close (poll_pipe[1]);
 
110
        return 0;
 
111
    }
 
112
 
 
113
    poll_count = 1 + snd_pcm_poll_descriptors_count (alsa_handle);
 
114
    poll_handles = malloc (sizeof (struct pollfd) * poll_count);
 
115
    poll_handles[0].fd = poll_pipe[0];
 
116
    poll_handles[0].events = POLLIN;
 
117
    poll_count = 1 + snd_pcm_poll_descriptors (alsa_handle, poll_handles + 1,
 
118
     poll_count - 1);
 
119
 
 
120
    return 1;
 
121
}
 
122
 
 
123
static void poll_sleep (void)
 
124
{
 
125
    if (poll (poll_handles, poll_count, -1) < 0)
 
126
    {
 
127
        ERROR ("Failed to poll: %s.\n", strerror (errno));
 
128
        return;
 
129
    }
 
130
 
 
131
    if (poll_handles[0].revents & POLLIN)
 
132
    {
 
133
        char c;
 
134
        while (read (poll_pipe[0], & c, 1) == 1)
 
135
            ;
 
136
    }
 
137
}
 
138
 
 
139
static void poll_wake (void)
 
140
{
 
141
    const char c = 0;
 
142
    if (write (poll_pipe[1], & c, 1) < 0)
 
143
        ERROR ("Failed to write to pipe: %s.\n", strerror (errno));
 
144
}
 
145
 
 
146
static void poll_cleanup (void)
 
147
{
 
148
    close (poll_pipe[0]);
 
149
    close (poll_pipe[1]);
 
150
    free (poll_handles);
 
151
}
 
152
 
46
153
static void * pump (void * unused)
47
154
{
48
 
    snd_pcm_status_t * status;
49
 
    gint length;
50
 
 
51
 
    g_mutex_lock (alsa_mutex);
52
 
    read_locked = FALSE;
53
 
    g_cond_signal (alsa_cond);
54
 
 
55
 
    snd_pcm_status_alloca (& status);
 
155
    pthread_mutex_lock (& alsa_mutex);
 
156
    pthread_cond_broadcast (& alsa_cond); /* signal thread started */
 
157
 
 
158
    gboolean workaround = FALSE;
 
159
    gint slept = 0;
56
160
 
57
161
    while (! pump_quit)
58
162
    {
59
 
        if (alsa_paused)
 
163
        if (alsa_prebuffer || alsa_paused || ! snd_pcm_bytes_to_frames
 
164
         (alsa_handle, alsa_buffer_data_length))
60
165
        {
61
 
            g_cond_wait (alsa_cond, alsa_mutex);
 
166
            pthread_cond_wait (& alsa_cond, & alsa_mutex);
62
167
            continue;
63
168
        }
64
169
 
65
 
        length = snd_pcm_frames_to_bytes (alsa_handle, LEAST_BUFFER / 2 *
66
 
         alsa_rate / 1000);
 
170
        int length;
 
171
        CHECK_VAL_RECOVER (length, snd_pcm_avail_update, alsa_handle);
 
172
 
 
173
        if (! length)
 
174
            goto WAIT;
 
175
 
 
176
        slept = 0;
 
177
 
 
178
        length = snd_pcm_frames_to_bytes (alsa_handle, length);
67
179
        length = MIN (length, alsa_buffer_data_length);
68
180
        length = MIN (length, alsa_buffer_length - alsa_buffer_data_start);
69
 
 
70
 
        if (length == 0)
71
 
        {
72
 
            g_cond_wait (alsa_cond, alsa_mutex);
73
 
            continue;
74
 
        }
75
 
 
76
 
        read_locked = TRUE;
77
 
        g_mutex_unlock (alsa_mutex);
78
 
 
79
 
        length = snd_pcm_writei (alsa_handle, (gchar *) alsa_buffer +
80
 
         alsa_buffer_data_start, snd_pcm_bytes_to_frames (alsa_handle, length));
81
 
 
82
 
        g_mutex_lock (alsa_mutex);
83
 
 
84
 
        if (length < 0)
85
 
        {
86
 
            if (! pump_quit && ! alsa_paused) /* ignore errors caused by drop */
87
 
                CHECK (snd_pcm_recover, alsa_handle, length, 0);
88
 
 
89
 
        FAILED:
90
 
            length = 0;
91
 
        }
92
 
 
93
 
        length = snd_pcm_frames_to_bytes (alsa_handle, length);
94
 
 
95
 
        alsa_buffer_data_start = (alsa_buffer_data_start + length) %
96
 
         alsa_buffer_length;
97
 
        alsa_buffer_data_length -= length;
98
 
 
99
 
        read_locked = FALSE;
100
 
        g_cond_signal (alsa_cond);
 
181
        length = snd_pcm_bytes_to_frames (alsa_handle, length);
 
182
 
 
183
        int written;
 
184
        CHECK_VAL_RECOVER (written, snd_pcm_writei, alsa_handle, (char *)
 
185
         alsa_buffer + alsa_buffer_data_start, length);
 
186
 
 
187
        written = snd_pcm_frames_to_bytes (alsa_handle, written);
 
188
        alsa_buffer_data_start += written;
 
189
        alsa_buffer_data_length -= written;
 
190
 
 
191
        pthread_cond_broadcast (& alsa_cond); /* signal write complete */
 
192
 
 
193
        if (alsa_buffer_data_start == alsa_buffer_length)
 
194
        {
 
195
            alsa_buffer_data_start = 0;
 
196
            continue;
 
197
        }
 
198
 
 
199
        if (! snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer_data_length))
 
200
            continue;
 
201
 
 
202
    WAIT:
 
203
        pthread_mutex_unlock (& alsa_mutex);
 
204
 
 
205
        if (slept > 4)
 
206
        {
 
207
            static gboolean warned = FALSE;
 
208
            if (! warned)
 
209
            {
 
210
                fprintf (stderr, "\n** WARNING **\nAudacious has detected that "
 
211
                 "your ALSA device has a broken timer.  A workaround\nis being "
 
212
                 "used to prevent CPU overload.  Please report this problem to "
 
213
                 "your\nLinux distributor or to the ALSA developers.\n\n");
 
214
                warned = TRUE;
 
215
            }
 
216
 
 
217
            workaround = TRUE;
 
218
        }
 
219
 
 
220
        if (workaround && slept)
 
221
        {
 
222
            const struct timespec delay = {.tv_sec = 0, .tv_nsec = 600000 *
 
223
             alsa_period};
 
224
            nanosleep (& delay, NULL);
 
225
        }
 
226
        else
 
227
        {
 
228
            poll_sleep ();
 
229
            slept ++;
 
230
        }
 
231
 
 
232
        pthread_mutex_lock (& alsa_mutex);
101
233
    }
102
234
 
103
 
    g_mutex_unlock (alsa_mutex);
 
235
FAILED:
 
236
    pthread_mutex_unlock (& alsa_mutex);
104
237
    return NULL;
105
238
}
106
239
 
 
240
static void pump_start (void)
 
241
{
 
242
    AUDDBG ("Starting pump.\n");
 
243
    pthread_create (& pump_thread, NULL, pump, NULL);
 
244
    pthread_cond_wait (& alsa_cond, & alsa_mutex);
 
245
}
 
246
 
 
247
static void pump_stop (void)
 
248
{
 
249
    AUDDBG ("Stopping pump.\n");
 
250
    pump_quit = 1;
 
251
    pthread_cond_broadcast (& alsa_cond);
 
252
    poll_wake ();
 
253
    pthread_mutex_unlock (& alsa_mutex);
 
254
    pthread_join (pump_thread, NULL);
 
255
    pthread_mutex_lock (& alsa_mutex);
 
256
    pump_quit = 0;
 
257
}
 
258
 
107
259
static void start_playback (void)
108
260
{
109
261
    AUDDBG ("Starting playback.\n");
110
 
 
111
 
    if (snd_pcm_state (alsa_handle) == SND_PCM_STATE_PAUSED)
112
 
        CHECK (snd_pcm_pause, alsa_handle, 0);
113
 
    else
114
 
        CHECK (snd_pcm_prepare, alsa_handle);
115
 
 
116
 
FAILED:
117
 
    alsa_paused = FALSE;
118
 
    g_cond_signal (alsa_cond);
119
 
}
120
 
 
121
 
static gint real_output_time (void)
122
 
{
123
 
    snd_pcm_status_t * status;
124
 
    gint time = 0;
125
 
 
126
 
    snd_pcm_status_alloca (& status);
127
 
    CHECK (snd_pcm_status, alsa_handle, status);
128
 
    time = (alsa_time - (gint64) (snd_pcm_bytes_to_frames (alsa_handle,
129
 
     alsa_buffer_data_length) + snd_pcm_status_get_delay (status)) * 1000000 /
130
 
     alsa_rate) / 1000;
131
 
 
132
 
FAILED:
133
 
    return time;
 
262
    CHECK (snd_pcm_prepare, alsa_handle);
 
263
 
 
264
FAILED:
 
265
    alsa_prebuffer = 0;
 
266
    pthread_cond_broadcast (& alsa_cond);
 
267
}
 
268
 
 
269
static int get_delay (void)
 
270
{
 
271
    snd_pcm_sframes_t delay = 0;
 
272
 
 
273
    CHECK_RECOVER (snd_pcm_delay, alsa_handle, & delay);
 
274
 
 
275
FAILED:
 
276
    return delay;
 
277
}
 
278
 
 
279
static int get_output_time (void)
 
280
{
 
281
    return (int64_t) (alsa_written - snd_pcm_bytes_to_frames (alsa_handle,
 
282
     alsa_buffer_data_length) - get_delay ()) * 1000 / alsa_rate;
134
283
}
135
284
 
136
285
OutputPluginInitStatus alsa_init (void)
137
286
{
138
 
    alsa_mutex = g_mutex_new ();
139
287
    alsa_handle = NULL;
140
 
    alsa_cond = g_cond_new ();
141
 
    initted = FALSE;
142
 
 
 
288
    alsa_initted = 0;
143
289
    return OUTPUT_PLUGIN_INIT_FOUND_DEVICES;
144
290
}
145
291
 
146
292
void alsa_soft_init (void)
147
293
{
148
 
    if (! initted)
 
294
    pthread_mutex_lock (& alsa_mutex);
 
295
 
 
296
    if (! alsa_initted)
149
297
    {
150
298
        AUDDBG ("Initialize.\n");
151
299
        alsa_config_load ();
152
300
        alsa_open_mixer ();
153
 
        initted = TRUE;
 
301
        alsa_initted = 1;
154
302
    }
 
303
 
 
304
    pthread_mutex_unlock (& alsa_mutex);
155
305
}
156
306
 
157
307
void alsa_cleanup (void)
158
308
{
159
 
    if (initted)
 
309
    if (alsa_initted)
160
310
    {
161
311
        AUDDBG ("Cleanup.\n");
162
312
        alsa_close_mixer ();
163
313
        alsa_config_save ();
164
314
    }
165
 
 
166
 
    g_mutex_free (alsa_mutex);
167
 
    g_cond_free (alsa_cond);
168
315
}
169
316
 
170
 
static snd_pcm_format_t convert_aud_format (AFormat aud_format)
 
317
static int convert_aud_format (int aud_format)
171
318
{
172
319
    const struct
173
320
    {
174
 
        AFormat aud_format;
175
 
        snd_pcm_format_t format;
 
321
        int aud_format, format;
176
322
    }
177
323
    table[] =
178
324
    {
193
339
        {FMT_U32_BE, SND_PCM_FORMAT_U32_BE},
194
340
    };
195
341
 
196
 
    gint count;
197
 
 
198
 
    for (count = 0; count < G_N_ELEMENTS (table); count ++)
 
342
    for (int count = 0; count < G_N_ELEMENTS (table); count ++)
199
343
    {
200
 
         if (table[count].aud_format == aud_format)
201
 
             return table[count].format;
 
344
        if (table[count].aud_format == aud_format)
 
345
            return table[count].format;
202
346
    }
203
347
 
204
348
    return SND_PCM_FORMAT_UNKNOWN;
205
349
}
206
350
 
207
 
gint alsa_open_audio (AFormat aud_format, gint rate, gint channels)
 
351
int alsa_open_audio (int aud_format, int rate, int channels)
208
352
{
209
 
    snd_pcm_format_t format = convert_aud_format (aud_format);
210
 
    snd_pcm_hw_params_t * params;
211
 
    guint useconds;
212
 
    snd_pcm_uframes_t frames, period;
213
 
    gint hard_buffer, soft_buffer;
214
 
 
215
 
    g_mutex_lock (alsa_mutex);
216
353
    alsa_soft_init ();
217
 
 
 
354
    pthread_mutex_lock (& alsa_mutex);
 
355
 
 
356
    assert (alsa_handle == NULL);
 
357
 
 
358
    int format = convert_aud_format (aud_format);
218
359
    AUDDBG ("Opening PCM device %s for %s, %d channels, %d Hz.\n",
219
360
     alsa_config_pcm, snd_pcm_format_name (format), channels, rate);
220
361
    CHECK_NOISY (snd_pcm_open, & alsa_handle, alsa_config_pcm,
221
362
     SND_PCM_STREAM_PLAYBACK, 0);
222
363
 
 
364
    snd_pcm_hw_params_t * params;
223
365
    snd_pcm_hw_params_alloca (& params);
224
366
    CHECK_NOISY (snd_pcm_hw_params_any, alsa_handle, params);
225
367
    CHECK_NOISY (snd_pcm_hw_params_set_access, alsa_handle, params,
226
368
     SND_PCM_ACCESS_RW_INTERLEAVED);
 
369
 
227
370
    CHECK_NOISY (snd_pcm_hw_params_set_format, alsa_handle, params, format);
228
371
    CHECK_NOISY (snd_pcm_hw_params_set_channels, alsa_handle, params, channels);
229
372
    CHECK_NOISY (snd_pcm_hw_params_set_rate, alsa_handle, params, rate, 0);
230
 
    useconds = 1000 * LEAST_BUFFER;
231
 
    CHECK_NOISY (snd_pcm_hw_params_set_buffer_time_min, alsa_handle, params,
232
 
     & useconds, 0);
233
 
    useconds = 1000 * MAX (LEAST_BUFFER * 11 / 10, aud_cfg->output_buffer_size /
234
 
     2);
235
 
    CHECK_NOISY (snd_pcm_hw_params_set_buffer_time_max, alsa_handle, params,
236
 
     & useconds, 0);
237
 
    CHECK_NOISY (snd_pcm_hw_params, alsa_handle, params);
238
373
 
239
374
    alsa_format = format;
240
375
    alsa_channels = channels;
241
376
    alsa_rate = rate;
242
377
 
243
 
    CHECK_NOISY (snd_pcm_get_params, alsa_handle, & frames, & period);
244
 
    hard_buffer = (gint64) frames * 1000 / rate;
245
 
    soft_buffer = MAX (LEAST_BUFFER, aud_cfg->output_buffer_size - hard_buffer);
246
 
    AUDDBG ("Hardware buffer %d ms, software buffer %d ms.\n", hard_buffer,
247
 
     soft_buffer);
248
 
 
249
 
    alsa_buffer_length = snd_pcm_frames_to_bytes (alsa_handle, (gint64)
 
378
    unsigned int useconds = 1000 * MIN (1000, aud_cfg->output_buffer_size / 2);
 
379
    int direction = 0;
 
380
    CHECK_NOISY (snd_pcm_hw_params_set_buffer_time_near, alsa_handle, params,
 
381
     & useconds, & direction);
 
382
    int hard_buffer = useconds / 1000;
 
383
 
 
384
    useconds = 1000 * (hard_buffer / 4);
 
385
    direction = 0;
 
386
    CHECK_NOISY (snd_pcm_hw_params_set_period_time_near, alsa_handle, params,
 
387
     & useconds, & direction);
 
388
    alsa_period = useconds / 1000;
 
389
 
 
390
    CHECK_NOISY (snd_pcm_hw_params, alsa_handle, params);
 
391
 
 
392
    int soft_buffer = MAX (aud_cfg->output_buffer_size / 2,
 
393
     aud_cfg->output_buffer_size - hard_buffer);
 
394
    AUDDBG ("Buffer: hardware %d ms, software %d ms, period %d ms.\n",
 
395
     hard_buffer, soft_buffer, alsa_period);
 
396
 
 
397
    alsa_buffer_length = snd_pcm_frames_to_bytes (alsa_handle, (int64_t)
250
398
     soft_buffer * rate / 1000);
251
 
    alsa_buffer = g_malloc (alsa_buffer_length);
 
399
    alsa_buffer = malloc (alsa_buffer_length);
252
400
    alsa_buffer_data_start = 0;
253
401
    alsa_buffer_data_length = 0;
254
402
 
255
 
    alsa_time = 0;
256
 
    alsa_paused = TRUE; /* for buffering */
 
403
    alsa_written = 0;
 
404
    alsa_prebuffer = 1;
 
405
    alsa_paused = 0;
257
406
    alsa_paused_time = 0;
258
407
 
259
 
    pump_quit = FALSE;
260
 
    pump_thread = g_thread_create (pump, NULL, TRUE, NULL);
261
 
    g_cond_wait (alsa_cond, alsa_mutex);
262
 
 
263
 
    g_mutex_unlock (alsa_mutex);
 
408
    if (! poll_setup ())
 
409
        goto FAILED;
 
410
 
 
411
    pump_start ();
 
412
 
 
413
    pthread_mutex_unlock (& alsa_mutex);
264
414
    return 1;
265
415
 
266
416
FAILED:
270
420
        alsa_handle = NULL;
271
421
    }
272
422
 
273
 
    g_mutex_unlock (alsa_mutex);
 
423
    pthread_mutex_unlock (& alsa_mutex);
274
424
    return 0;
275
425
}
276
426
 
277
427
void alsa_close_audio (void)
278
428
{
279
429
    AUDDBG ("Closing audio.\n");
280
 
    g_mutex_lock (alsa_mutex);
281
 
    pump_quit = TRUE;
282
 
 
283
 
    if (! alsa_config_drop_workaround)
284
 
        CHECK (snd_pcm_drop, alsa_handle);
 
430
    pthread_mutex_lock (& alsa_mutex);
 
431
 
 
432
    assert (alsa_handle != NULL);
 
433
 
 
434
    pump_stop ();
 
435
    CHECK (snd_pcm_drop, alsa_handle);
285
436
 
286
437
FAILED:
287
 
    g_cond_signal (alsa_cond);
288
 
    g_mutex_unlock (alsa_mutex);
289
 
    g_thread_join (pump_thread);
290
 
    g_mutex_lock (alsa_mutex);
291
 
 
292
 
    g_free (alsa_buffer);
 
438
    free (alsa_buffer);
 
439
    poll_cleanup ();
293
440
    snd_pcm_close (alsa_handle);
294
441
    alsa_handle = NULL;
295
 
    g_mutex_unlock (alsa_mutex);
296
 
}
297
 
 
298
 
void alsa_write_audio (void * data, gint length)
299
 
{
300
 
    g_mutex_lock (alsa_mutex);
301
 
 
302
 
    while (1)
303
 
    {
304
 
        gint writable = MIN (alsa_buffer_length - alsa_buffer_data_length,
305
 
         length);
306
 
        gint start = (alsa_buffer_data_start + alsa_buffer_data_length) %
307
 
         alsa_buffer_length;
308
 
 
309
 
        if (writable > alsa_buffer_length - start)
 
442
 
 
443
    pthread_mutex_unlock (& alsa_mutex);
 
444
}
 
445
 
 
446
int alsa_buffer_free (void)
 
447
{
 
448
    pthread_mutex_lock (& alsa_mutex);
 
449
    int avail = alsa_buffer_length - alsa_buffer_data_length;
 
450
    pthread_mutex_unlock (& alsa_mutex);
 
451
    return avail;
 
452
}
 
453
 
 
454
void alsa_write_audio (void * data, int length)
 
455
{
 
456
    pthread_mutex_lock (& alsa_mutex);
 
457
 
 
458
    int start = (alsa_buffer_data_start + alsa_buffer_data_length) %
 
459
     alsa_buffer_length;
 
460
 
 
461
    assert (length <= alsa_buffer_length - alsa_buffer_data_length);
 
462
 
 
463
    if (length > alsa_buffer_length - start)
 
464
    {
 
465
        int part = alsa_buffer_length - start;
 
466
 
 
467
        memcpy ((char *) alsa_buffer + start, data, part);
 
468
        memcpy (alsa_buffer, (char *) data + part, length - part);
 
469
    }
 
470
    else
 
471
        memcpy ((char *) alsa_buffer + start, data, length);
 
472
 
 
473
    alsa_buffer_data_length += length;
 
474
    alsa_written += snd_pcm_bytes_to_frames (alsa_handle, length);
 
475
 
 
476
    if (! alsa_paused)
 
477
        pthread_cond_broadcast (& alsa_cond);
 
478
 
 
479
    pthread_mutex_unlock (& alsa_mutex);
 
480
}
 
481
 
 
482
void alsa_period_wait (void)
 
483
{
 
484
    pthread_mutex_lock (& alsa_mutex);
 
485
 
 
486
    while (alsa_buffer_data_length == alsa_buffer_length)
 
487
    {
 
488
        if (! alsa_paused)
310
489
        {
311
 
            gint part = alsa_buffer_length - start;
312
 
 
313
 
            memcpy ((gint8 *) alsa_buffer + start, data, part);
314
 
            memcpy (alsa_buffer, (gint8 *) data + part, writable - part);
 
490
            if (alsa_prebuffer)
 
491
                start_playback ();
 
492
            else
 
493
                pthread_cond_broadcast (& alsa_cond);
315
494
        }
316
 
        else
317
 
            memcpy ((gint8 *) alsa_buffer + start, data, writable);
318
 
 
319
 
        data = (gint8 *) data + writable;
320
 
        length -= writable;
321
 
 
322
 
        alsa_buffer_data_length += writable;
323
 
        alsa_time += (gint64) snd_pcm_bytes_to_frames (alsa_handle, writable) *
324
 
         1000000 / alsa_rate;
325
 
 
326
 
        if (! length)
327
 
            break;
328
 
 
329
 
        if (alsa_paused) /* buffering completed */
330
 
            start_playback ();
331
 
 
332
 
        g_cond_signal (alsa_cond);
333
 
        g_cond_wait (alsa_cond, alsa_mutex);
 
495
 
 
496
        pthread_cond_wait (& alsa_cond, & alsa_mutex);
334
497
    }
335
498
 
336
 
    g_mutex_unlock (alsa_mutex);
 
499
    pthread_mutex_unlock (& alsa_mutex);
337
500
}
338
501
 
339
502
void alsa_drain (void)
340
503
{
341
504
    AUDDBG ("Drain.\n");
342
 
    g_mutex_lock (alsa_mutex);
343
 
 
344
 
    while (alsa_buffer_data_length > 0)
345
 
    {
346
 
        if (alsa_paused) /* buffering completed */
347
 
            start_playback ();
348
 
 
349
 
        g_cond_wait (alsa_cond, alsa_mutex);
350
 
    }
351
 
 
352
 
    g_mutex_unlock (alsa_mutex);
353
 
 
354
 
    CHECK (snd_pcm_drain, alsa_handle);
 
505
    pthread_mutex_lock (& alsa_mutex);
 
506
 
 
507
    assert (! alsa_paused);
 
508
 
 
509
    if (alsa_prebuffer)
 
510
        start_playback ();
 
511
 
 
512
    while (snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer_data_length))
 
513
        pthread_cond_wait (& alsa_cond, & alsa_mutex);
 
514
 
 
515
    pump_stop ();
 
516
 
 
517
    if (alsa_config_drain_workaround)
 
518
    {
 
519
        int d = get_delay () * 1000 / alsa_rate;
 
520
        struct timespec delay = {.tv_sec = d / 1000, .tv_nsec = d % 1000 *
 
521
         1000000};
 
522
 
 
523
        pthread_mutex_unlock (& alsa_mutex);
 
524
        nanosleep (& delay, NULL);
 
525
        pthread_mutex_lock (& alsa_mutex);
 
526
    }
 
527
    else
 
528
    {
 
529
        while (1)
 
530
        {
 
531
            int state;
 
532
            CHECK_VAL (state, snd_pcm_state, alsa_handle);
 
533
 
 
534
            if (state != SND_PCM_STATE_RUNNING && state !=
 
535
             SND_PCM_STATE_DRAINING)
 
536
                break;
 
537
 
 
538
            pthread_mutex_unlock (& alsa_mutex);
 
539
            poll_sleep ();
 
540
            pthread_mutex_lock (& alsa_mutex);
 
541
        }
 
542
    }
 
543
 
 
544
    pump_start ();
355
545
 
356
546
FAILED:
 
547
    pthread_mutex_unlock (& alsa_mutex);
357
548
    return;
358
549
}
359
550
 
360
 
void alsa_set_written_time (gint time)
 
551
void alsa_set_written_time (int time)
361
552
{
362
553
    AUDDBG ("Setting time counter to %d.\n", time);
363
 
    g_mutex_lock (alsa_mutex);
364
 
    alsa_time = 1000 * (gint64) time;
365
 
    g_mutex_unlock (alsa_mutex);
366
 
}
367
 
 
368
 
gint alsa_written_time (void)
369
 
{
370
 
    gint time;
371
 
 
372
 
    g_mutex_lock (alsa_mutex);
373
 
    time = alsa_time / 1000;
374
 
    g_mutex_unlock (alsa_mutex);
375
 
    return time;
376
 
}
377
 
 
378
 
gint alsa_output_time (void)
379
 
{
380
 
    gint time = 0;
381
 
 
382
 
    g_mutex_lock (alsa_mutex);
383
 
 
384
 
    if (alsa_paused)
385
 
        time = alsa_paused_time;
386
 
    else
387
 
        time = real_output_time ();
388
 
 
389
 
    g_mutex_unlock (alsa_mutex);
390
 
    return time;
391
 
}
392
 
 
393
 
void alsa_flush (gint time)
 
554
    pthread_mutex_lock (& alsa_mutex);
 
555
    alsa_written = (int64_t) time * alsa_rate / 1000;
 
556
    pthread_mutex_unlock (& alsa_mutex);
 
557
}
 
558
 
 
559
int alsa_written_time (void)
 
560
{
 
561
    pthread_mutex_lock (& alsa_mutex);
 
562
    int time = (int64_t) alsa_written * 1000 / alsa_rate;
 
563
    pthread_mutex_unlock (& alsa_mutex);
 
564
    return time;
 
565
}
 
566
 
 
567
int alsa_output_time (void)
 
568
{
 
569
    pthread_mutex_lock (& alsa_mutex);
 
570
    int time = (alsa_prebuffer || alsa_paused) ? alsa_paused_time :
 
571
     get_output_time ();
 
572
    pthread_mutex_unlock (& alsa_mutex);
 
573
    return time;
 
574
}
 
575
 
 
576
void alsa_flush (int time)
394
577
{
395
578
    AUDDBG ("Seek requested; discarding buffer.\n");
396
 
    g_mutex_lock (alsa_mutex);
397
 
 
398
 
    alsa_time = (gint64) time * 1000;
399
 
    alsa_paused = TRUE; /* for buffering */
 
579
    pthread_mutex_lock (& alsa_mutex);
 
580
 
 
581
    pump_stop ();
 
582
    CHECK (snd_pcm_drop, alsa_handle);
 
583
 
 
584
FAILED:
 
585
    alsa_buffer_data_start = 0;
 
586
    alsa_buffer_data_length = 0;
 
587
 
 
588
    alsa_written = (int64_t) time * alsa_rate / 1000;
 
589
    alsa_prebuffer = 1;
400
590
    alsa_paused_time = time;
401
591
 
402
 
    if (! alsa_config_drop_workaround)
403
 
        CHECK (snd_pcm_drop, alsa_handle);
404
 
 
405
 
FAILED:
406
 
    while (read_locked)
407
 
        g_cond_wait (alsa_cond, alsa_mutex);
408
 
 
409
 
    alsa_buffer_data_start = 0;
410
 
    alsa_buffer_data_length = 0;
411
 
 
412
 
    g_cond_signal (alsa_cond);
413
 
    g_mutex_unlock (alsa_mutex);
 
592
    pthread_cond_broadcast (& alsa_cond); /* interrupt period wait */
 
593
 
 
594
    pump_start ();
 
595
 
 
596
    pthread_mutex_unlock (& alsa_mutex);
414
597
}
415
598
 
416
 
void alsa_pause (gshort pause)
 
599
void alsa_pause (short pause)
417
600
{
418
601
    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
419
 
    g_mutex_lock (alsa_mutex);
 
602
    pthread_mutex_lock (& alsa_mutex);
 
603
 
 
604
    alsa_paused = pause;
 
605
 
 
606
    if (! alsa_prebuffer)
 
607
    {
 
608
        if (pause)
 
609
            alsa_paused_time = get_output_time ();
 
610
 
 
611
        CHECK (snd_pcm_pause, alsa_handle, pause);
 
612
    }
 
613
 
 
614
DONE:
 
615
    if (! pause)
 
616
        pthread_cond_broadcast (& alsa_cond);
 
617
 
 
618
    pthread_mutex_unlock (& alsa_mutex);
 
619
    return;
 
620
 
 
621
FAILED:
 
622
    AUDDBG ("Trying to work around broken pause.\n");
420
623
 
421
624
    if (pause)
422
 
    {
423
 
        alsa_paused = TRUE;
424
 
        alsa_paused_time = real_output_time ();
425
 
 
426
 
        CHECK (snd_pcm_pause, alsa_handle, pause);
427
 
    }
428
 
 
429
 
FAILED:
430
 
    g_cond_signal (alsa_cond);
431
 
    g_mutex_unlock (alsa_mutex);
 
625
        snd_pcm_drop (alsa_handle);
 
626
    else
 
627
        snd_pcm_prepare (alsa_handle);
 
628
 
 
629
    goto DONE;
432
630
}
433
631
 
434
632
void alsa_open_mixer (void)
473
671
        snd_mixer_close (alsa_mixer);
474
672
}
475
673
 
476
 
void alsa_get_volume (gint * left, gint * right)
 
674
void alsa_get_volume (int * left, int * right)
477
675
{
478
 
    glong left_l = 0, right_l = 0;
479
 
 
480
 
    g_mutex_lock (alsa_mutex);
481
676
    alsa_soft_init ();
 
677
    pthread_mutex_lock (& alsa_mutex);
 
678
 
 
679
    long left_l = 0, right_l = 0;
482
680
 
483
681
    if (alsa_mixer == NULL)
484
682
        goto FAILED;
500
698
    }
501
699
 
502
700
FAILED:
503
 
    g_mutex_unlock (alsa_mutex);
 
701
    pthread_mutex_unlock (& alsa_mutex);
504
702
 
505
703
    * left = left_l;
506
704
    * right = right_l;
507
705
}
508
706
 
509
 
void alsa_set_volume (gint left, gint right)
 
707
void alsa_set_volume (int left, int right)
510
708
{
511
 
    g_mutex_lock (alsa_mutex);
512
709
    alsa_soft_init ();
 
710
    pthread_mutex_lock (& alsa_mutex);
513
711
 
514
712
    if (alsa_mixer == NULL)
515
713
        goto FAILED;
548
746
    CHECK (snd_mixer_handle_events, alsa_mixer);
549
747
 
550
748
FAILED:
551
 
    g_mutex_unlock (alsa_mutex);
 
749
    pthread_mutex_unlock (& alsa_mutex);
552
750
}