~ubuntu-branches/ubuntu/saucy/jack-audio-connection-kit/saucy

« back to all changes in this revision

Viewing changes to drivers/dummy/dummy_driver.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-12-06 11:05:15 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081206110515-xa9v9pajr9jqvfvg
Tags: 0.115.6-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - Redirect stderr in bash completion (Debian #504488).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c; c-file-style: "linux"; -*- */
 
2
/*
 
3
    Copyright (C) 2003 Robert Ham <rah@bash.sh>
 
4
    Copyright (C) 2001 Paul Davis
 
5
 
 
6
    This program is free software; you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 2 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 
 
20
*/
 
21
 
 
22
#include <math.h>
 
23
#include <stdio.h>
 
24
#include <memory.h>
 
25
#include <unistd.h>
 
26
#include <stdlib.h>
 
27
#include <errno.h>
 
28
#include <stdarg.h>
 
29
#include <sys/mman.h>
 
30
 
 
31
#include <jack/types.h>
 
32
#include <jack/internal.h>
 
33
#include <jack/engine.h>
 
34
#include <sysdeps/time.h>
 
35
 
 
36
#include "dummy_driver.h"
 
37
 
 
38
#undef DEBUG_WAKEUP
 
39
 
 
40
/* this is used for calculate what counts as an xrun */
 
41
#define PRETEND_BUFFER_SIZE 4096
 
42
 
 
43
void
 
44
FakeVideoSync( dummy_driver_t *driver )
 
45
{
 
46
        #define VIDEO_SYNC_PERIOD (48000 / 30)
 
47
        static int vidCounter = VIDEO_SYNC_PERIOD;
 
48
        
 
49
        int period = driver->period_size;
 
50
        jack_position_t *position = &driver->engine->control->current_time;
 
51
 
 
52
        if ( period >= VIDEO_SYNC_PERIOD ) {
 
53
                jack_error("JACK driver period size too large for simple video sync emulation. Halting.");
 
54
                exit(0);
 
55
        }
 
56
 
 
57
        //enable video sync, whether it occurs in this period or not
 
58
        position->audio_frames_per_video_frame = VIDEO_SYNC_PERIOD;
 
59
        position->valid = (jack_position_bits_t) (position->valid | JackAudioVideoRatio);
 
60
 
 
61
        //no video pulse found in this period, just decrement the counter
 
62
        if ( vidCounter > period ) {
 
63
                vidCounter -= period;
 
64
        }
 
65
 
 
66
        //video pulse occurs in this period
 
67
        if ( vidCounter <= period ) {
 
68
                int remainder = period - vidCounter;
 
69
                vidCounter = VIDEO_SYNC_PERIOD - remainder;
 
70
 
 
71
                position->video_offset = vidCounter;
 
72
                position->valid = (jack_position_bits_t) (position->valid | JackVideoFrameOffset);
 
73
        }
 
74
}
 
75
 
 
76
#ifdef HAVE_CLOCK_GETTIME
 
77
static inline unsigned long long ts_to_nsec(struct timespec ts)
 
78
{
 
79
    return ts.tv_sec * 1000000000LL + ts.tv_nsec;
 
80
}
 
81
 
 
82
static inline struct timespec nsec_to_ts(unsigned long long nsecs)
 
83
{
 
84
    struct timespec ts;
 
85
    ts.tv_sec = nsecs / (1000000000LL);
 
86
    ts.tv_nsec = nsecs % (1000000000LL);
 
87
    return ts;
 
88
}
 
89
 
 
90
static inline struct timespec add_ts(struct timespec ts, unsigned int usecs)
 
91
{
 
92
    unsigned long long nsecs = ts_to_nsec(ts);
 
93
    nsecs += usecs * 1000LL;
 
94
    return nsec_to_ts(nsecs);
 
95
}
 
96
 
 
97
static inline int cmp_lt_ts(struct timespec ts1, struct timespec ts2)
 
98
{
 
99
    if(ts1.tv_sec < ts2.tv_sec) {
 
100
        return 1;
 
101
    } else if (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec < ts2.tv_nsec) {
 
102
        return 1;
 
103
    } else return 0;
 
104
}
 
105
 
 
106
static jack_nframes_t 
 
107
dummy_driver_wait (dummy_driver_t *driver, int extra_fd, int *status,
 
108
                   float *delayed_usecs)
 
109
{
 
110
        jack_nframes_t nframes = driver->period_size;
 
111
        struct timespec now;
 
112
 
 
113
        *status = 0;
 
114
        /* this driver doesn't work so well if we report a delay */
 
115
        *delayed_usecs = 0;             /* lie about it */
 
116
 
 
117
        clock_gettime(CLOCK_REALTIME, &now);
 
118
        
 
119
        if (cmp_lt_ts(driver->next_wakeup, now)) {
 
120
                if (driver->next_wakeup.tv_sec == 0) {
 
121
                        /* first time through */
 
122
                        clock_gettime(CLOCK_REALTIME, &driver->next_wakeup);
 
123
                }  else if ((ts_to_nsec(now) - ts_to_nsec(driver->next_wakeup))/1000LL
 
124
                            > (PRETEND_BUFFER_SIZE * 1000000LL
 
125
                               / driver->sample_rate)) {
 
126
                        /* xrun */
 
127
                        jack_error("**** dummy: xrun of %ju usec",
 
128
                                (uintmax_t)(ts_to_nsec(now) - ts_to_nsec(driver->next_wakeup))/1000LL);
 
129
                        nframes = 0;
 
130
                } else {
 
131
                        /* late, but handled by our "buffer"; try to
 
132
                         * get back on track */
 
133
                }
 
134
                driver->next_wakeup = add_ts(driver->next_wakeup, driver->wait_time);
 
135
        } else {
 
136
                if(clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &driver->next_wakeup, NULL)) {
 
137
                        jack_error("error while sleeping");
 
138
                        *status = -1;
 
139
                } else {
 
140
                        clock_gettime(CLOCK_REALTIME, &now);
 
141
                        // guaranteed to sleep long enough for this to be correct
 
142
                        *delayed_usecs = (ts_to_nsec(now) - ts_to_nsec(driver->next_wakeup));
 
143
                        *delayed_usecs /= 1000.0;
 
144
                }
 
145
                driver->next_wakeup = add_ts(driver->next_wakeup, driver->wait_time);
 
146
        }
 
147
 
 
148
        driver->last_wait_ust = jack_get_microseconds ();
 
149
        driver->engine->transport_cycle_start (driver->engine,
 
150
                                               driver->last_wait_ust);
 
151
 
 
152
        return nframes;
 
153
}
 
154
 
 
155
#else
 
156
 
 
157
static jack_nframes_t 
 
158
dummy_driver_wait (dummy_driver_t *driver, int extra_fd, int *status,
 
159
                   float *delayed_usecs)
 
160
{
 
161
        jack_time_t now = jack_get_microseconds();
 
162
 
 
163
        if (driver->next_time < now) {
 
164
                if (driver->next_time == 0) {
 
165
                        /* first time through */
 
166
                        driver->next_time = now + driver->wait_time;
 
167
                }  else if (now - driver->next_time
 
168
                            > (PRETEND_BUFFER_SIZE * 1000000LL
 
169
                               / driver->sample_rate)) {
 
170
                        /* xrun */
 
171
                        jack_error("**** dummy: xrun of %ju usec",
 
172
                                (uintmax_t)now - driver->next_time);
 
173
                        driver->next_time = now + driver->wait_time;
 
174
                } else {
 
175
                        /* late, but handled by our "buffer"; try to
 
176
                         * get back on track */
 
177
                        driver->next_time += driver->wait_time;
 
178
                }
 
179
        } else {
 
180
                jack_time_t wait = driver->next_time - now;
 
181
                struct timespec ts = { .tv_sec = wait / 1000000,
 
182
                                       .tv_nsec = (wait % 1000000) * 1000 };
 
183
                nanosleep(&ts,NULL);
 
184
                driver->next_time += driver->wait_time;
 
185
        }
 
186
 
 
187
        driver->last_wait_ust = jack_get_microseconds ();
 
188
        driver->engine->transport_cycle_start (driver->engine,
 
189
                                               driver->last_wait_ust);
 
190
 
 
191
        /* this driver doesn't work so well if we report a delay */
 
192
        *delayed_usecs = 0;             /* lie about it */
 
193
        *status = 0;
 
194
        return driver->period_size;
 
195
}
 
196
#endif
 
197
 
 
198
static inline int
 
199
dummy_driver_run_cycle (dummy_driver_t *driver)
 
200
{
 
201
        jack_engine_t *engine = driver->engine;
 
202
        int wait_status;
 
203
        float delayed_usecs;
 
204
 
 
205
        jack_nframes_t nframes = dummy_driver_wait (driver, -1, &wait_status,
 
206
                                                   &delayed_usecs);
 
207
        if (nframes == 0) {
 
208
                /* we detected an xrun and restarted: notify
 
209
                 * clients about the delay. */
 
210
                engine->delay (engine, delayed_usecs);
 
211
                return 0;
 
212
        } 
 
213
 
 
214
        // FakeVideoSync (driver);
 
215
 
 
216
        if (wait_status == 0)
 
217
                return engine->run_cycle (engine, nframes, delayed_usecs);
 
218
 
 
219
        if (wait_status < 0)
 
220
                return -1;
 
221
        else
 
222
                return 0;
 
223
}
 
224
 
 
225
static int
 
226
dummy_driver_null_cycle (dummy_driver_t* driver, jack_nframes_t nframes)
 
227
{
 
228
        return 0;
 
229
}
 
230
 
 
231
static int
 
232
dummy_driver_bufsize (dummy_driver_t* driver, jack_nframes_t nframes)
 
233
{
 
234
        driver->period_size = nframes;  
 
235
        driver->period_usecs = driver->wait_time =
 
236
                (jack_time_t) floor ((((float) nframes) / driver->sample_rate)
 
237
                                     * 1000000.0f);
 
238
 
 
239
        /* tell the engine to change its buffer size */
 
240
        driver->engine->set_buffer_size (driver->engine, nframes);
 
241
 
 
242
        return 0;
 
243
}
 
244
 
 
245
static int
 
246
dummy_driver_write (dummy_driver_t* driver, jack_nframes_t nframes)
 
247
{
 
248
        return 0;
 
249
}
 
250
 
 
251
 
 
252
static int
 
253
dummy_driver_attach (dummy_driver_t *driver)
 
254
{
 
255
        jack_port_t * port;
 
256
        char buf[32];
 
257
        unsigned int chn;
 
258
        int port_flags;
 
259
 
 
260
        driver->engine->set_buffer_size (driver->engine, driver->period_size);
 
261
        driver->engine->set_sample_rate (driver->engine, driver->sample_rate);
 
262
 
 
263
        port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
 
264
 
 
265
        for (chn = 0; chn < driver->capture_channels; chn++)
 
266
        {
 
267
                snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);
 
268
 
 
269
                port = jack_port_register (driver->client, buf,
 
270
                                           JACK_DEFAULT_AUDIO_TYPE,
 
271
                                           port_flags, 0);
 
272
                if (!port)
 
273
                {
 
274
                        jack_error ("DUMMY: cannot register port for %s", buf);
 
275
                        break;
 
276
                }
 
277
 
 
278
                driver->capture_ports =
 
279
                        jack_slist_append (driver->capture_ports, port);
 
280
        }
 
281
        
 
282
        port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
 
283
 
 
284
        for (chn = 0; chn < driver->playback_channels; chn++)
 
285
        {
 
286
                snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);
 
287
 
 
288
                port = jack_port_register (driver->client, buf,
 
289
                                           JACK_DEFAULT_AUDIO_TYPE,
 
290
                                           port_flags, 0);
 
291
 
 
292
                if (!port)
 
293
                {
 
294
                        jack_error ("DUMMY: cannot register port for %s", buf);
 
295
                        break;
 
296
                }
 
297
 
 
298
                driver->playback_ports =
 
299
                        jack_slist_append (driver->playback_ports, port);
 
300
        }
 
301
 
 
302
        jack_activate (driver->client);
 
303
 
 
304
        return 0;
 
305
}
 
306
 
 
307
static int
 
308
dummy_driver_detach (dummy_driver_t *driver)
 
309
{
 
310
        JSList * node;
 
311
 
 
312
        if (driver->engine == 0)
 
313
                return 0;
 
314
 
 
315
        for (node = driver->capture_ports; node; node = jack_slist_next (node))
 
316
                jack_port_unregister (driver->client,
 
317
                                      ((jack_port_t *) node->data));
 
318
 
 
319
        jack_slist_free (driver->capture_ports);
 
320
        driver->capture_ports = NULL;
 
321
 
 
322
                
 
323
        for (node = driver->playback_ports; node; node = jack_slist_next (node))
 
324
                jack_port_unregister (driver->client,
 
325
                                      ((jack_port_t *) node->data));
 
326
 
 
327
        jack_slist_free (driver->playback_ports);
 
328
        driver->playback_ports = NULL;
 
329
 
 
330
        return 0;
 
331
}
 
332
 
 
333
 
 
334
static void
 
335
dummy_driver_delete (dummy_driver_t *driver)
 
336
{
 
337
        jack_driver_nt_finish ((jack_driver_nt_t *) driver);
 
338
        free (driver);
 
339
}
 
340
 
 
341
static jack_driver_t *
 
342
dummy_driver_new (jack_client_t * client,
 
343
                  char *name,
 
344
                  unsigned int capture_ports,
 
345
                  unsigned int playback_ports,
 
346
                  jack_nframes_t sample_rate,
 
347
                  jack_nframes_t period_size,
 
348
                  unsigned long wait_time)
 
349
{
 
350
        dummy_driver_t * driver;
 
351
 
 
352
        jack_info ("creating dummy driver ... %s|%" PRIu32 "|%" PRIu32
 
353
                "|%lu|%u|%u", name, sample_rate, period_size, wait_time,
 
354
                capture_ports, playback_ports);
 
355
 
 
356
        driver = (dummy_driver_t *) calloc (1, sizeof (dummy_driver_t));
 
357
 
 
358
        jack_driver_nt_init ((jack_driver_nt_t *) driver);
 
359
 
 
360
        driver->write         = (JackDriverReadFunction)       dummy_driver_write;
 
361
        driver->null_cycle    = (JackDriverNullCycleFunction)  dummy_driver_null_cycle;
 
362
        driver->nt_attach     = (JackDriverNTAttachFunction)   dummy_driver_attach;
 
363
        driver->nt_detach     = (JackDriverNTDetachFunction)   dummy_driver_detach;
 
364
        driver->nt_bufsize    = (JackDriverNTBufSizeFunction)  dummy_driver_bufsize;
 
365
        driver->nt_run_cycle  = (JackDriverNTRunCycleFunction) dummy_driver_run_cycle;
 
366
 
 
367
        driver->period_usecs =
 
368
                (jack_time_t) floor ((((float) period_size) / sample_rate)
 
369
                                     * 1000000.0f);
 
370
        driver->sample_rate = sample_rate;
 
371
        driver->period_size = period_size;
 
372
        driver->wait_time   = wait_time;
 
373
        //driver->next_time   = 0; // not needed since calloc clears the memory
 
374
        driver->last_wait_ust = 0;
 
375
 
 
376
        driver->capture_channels  = capture_ports;
 
377
        driver->capture_ports     = NULL;
 
378
        driver->playback_channels = playback_ports;
 
379
        driver->playback_ports    = NULL;
 
380
 
 
381
        driver->client = client;
 
382
        driver->engine = NULL;
 
383
 
 
384
        return (jack_driver_t *) driver;
 
385
}
 
386
 
 
387
 
 
388
/* DRIVER "PLUGIN" INTERFACE */
 
389
 
 
390
jack_driver_desc_t *
 
391
driver_get_descriptor ()
 
392
{
 
393
        jack_driver_desc_t * desc;
 
394
        jack_driver_param_desc_t * params;
 
395
        unsigned int i;
 
396
 
 
397
        desc = calloc (1, sizeof (jack_driver_desc_t));
 
398
        strcpy (desc->name, "dummy");
 
399
        desc->nparams = 5;
 
400
 
 
401
        params = calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
 
402
 
 
403
        i = 0;
 
404
        strcpy (params[i].name, "capture");
 
405
        params[i].character  = 'C';
 
406
        params[i].type       = JackDriverParamUInt;
 
407
        params[i].value.ui   = 2U;
 
408
        strcpy (params[i].short_desc, "Number of capture ports");
 
409
        strcpy (params[i].long_desc, params[i].short_desc);
 
410
 
 
411
        i++;
 
412
        strcpy (params[i].name, "playback");
 
413
        params[i].character  = 'P';
 
414
        params[i].type       = JackDriverParamUInt;
 
415
        params[1].value.ui   = 2U;
 
416
        strcpy (params[i].short_desc, "Number of playback ports");
 
417
        strcpy (params[i].long_desc, params[i].short_desc);
 
418
 
 
419
        i++;
 
420
        strcpy (params[i].name, "rate");
 
421
        params[i].character  = 'r';
 
422
        params[i].type       = JackDriverParamUInt;
 
423
        params[i].value.ui   = 48000U;
 
424
        strcpy (params[i].short_desc, "Sample rate");
 
425
        strcpy (params[i].long_desc, params[i].short_desc);
 
426
 
 
427
        i++;
 
428
        strcpy (params[i].name, "period");
 
429
        params[i].character  = 'p';
 
430
        params[i].type       = JackDriverParamUInt;
 
431
        params[i].value.ui   = 1024U;
 
432
        strcpy (params[i].short_desc, "Frames per period");
 
433
        strcpy (params[i].long_desc, params[i].short_desc);
 
434
 
 
435
        i++;
 
436
        strcpy (params[i].name, "wait");
 
437
        params[i].character  = 'w';
 
438
        params[i].type       = JackDriverParamUInt;
 
439
        params[i].value.ui   = 21333U;
 
440
        strcpy (params[i].short_desc,
 
441
                "Number of usecs to wait between engine processes");
 
442
        strcpy (params[i].long_desc, params[i].short_desc);
 
443
 
 
444
        desc->params = params;
 
445
 
 
446
        return desc;
 
447
}
 
448
 
 
449
const char driver_client_name[] = "dummy_pcm";
 
450
 
 
451
jack_driver_t *
 
452
driver_initialize (jack_client_t *client, const JSList * params)
 
453
{
 
454
        jack_nframes_t sample_rate = 48000;
 
455
        jack_nframes_t period_size = 1024;
 
456
        unsigned int capture_ports = 2;
 
457
        unsigned int playback_ports = 2;
 
458
        int wait_time_set = 0;
 
459
        unsigned long wait_time = 0;
 
460
        const JSList * node;
 
461
        const jack_driver_param_t * param;
 
462
 
 
463
        for (node = params; node; node = jack_slist_next (node)) {
 
464
                param = (const jack_driver_param_t *) node->data;
 
465
 
 
466
                switch (param->character) {
 
467
 
 
468
                case 'C':
 
469
                  capture_ports = param->value.ui;
 
470
                  break;
 
471
 
 
472
                case 'P':
 
473
                  playback_ports = param->value.ui;
 
474
                  break;
 
475
 
 
476
                case 'r':
 
477
                  sample_rate = param->value.ui;
 
478
                  break;
 
479
 
 
480
                case 'p':
 
481
                  period_size = param->value.ui;
 
482
                  break;
 
483
 
 
484
                case 'w':
 
485
                  wait_time = param->value.ui;
 
486
                  wait_time_set = 1;
 
487
                  break;
 
488
                                
 
489
                }
 
490
        }
 
491
 
 
492
        if (!wait_time_set)
 
493
          wait_time = (((float)period_size) / ((float)sample_rate)) * 1000000.0;
 
494
 
 
495
        return dummy_driver_new (client, "dummy_pcm", capture_ports,
 
496
                                 playback_ports, sample_rate, period_size,
 
497
                                 wait_time);
 
498
}
 
499
 
 
500
void
 
501
driver_finish (jack_driver_t *driver)
 
502
{
 
503
        dummy_driver_delete ((dummy_driver_t *) driver);
 
504
}
 
505