src/audio_out/audio_jack_out.c
author Diego 'Flameeyes' Pettenò <flameeyes@gmail.com>
Wed, 12 Dec 2007 20:14:46 +0100
changeset 9766 362f4bd323e5
parent 9443 7681ab0a1136
parent 9745 d3edc010110d
permissions -rw-r--r--
Merge from 1.2 main branch.
     1 /* 
     2  * Copyright (C) 2000-2007 the xine project
     3  * 
     4  * This file is part of xine, a free video player.
     5  * 
     6  * xine 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  * xine 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
    19  */
    20 
    21 #ifdef HAVE_CONFIG_H
    22 #include "config.h"
    23 #endif
    24 
    25 #include <stdio.h>
    26 #include <errno.h>
    27 #include <string.h>
    28 #include <stdlib.h>
    29 #include <fcntl.h>
    30 #include <math.h>
    31 #include <unistd.h>
    32 #include <inttypes.h>
    33 
    34 #include "xine_internal.h"
    35 #include "xineutils.h"
    36 #include "audio_out.h"
    37 
    38 #include <jack/jack.h>
    39 
    40 #define AO_OUT_JACK_IFACE_VERSION 9
    41 
    42 #define GAP_TOLERANCE        AO_MAX_GAP
    43 #define BUFSIZE              81920
    44 
    45 /* CHECKME: should this be conditional on autotools? */
    46 extern const char *__progname;
    47 
    48 typedef struct jack_driver_s {
    49 
    50     ao_driver_t    ao_driver;
    51     xine_t        *xine;
    52 
    53     int            capabilities;
    54 
    55     sample_format_t sample_format;
    56     int32_t        sample_rate;
    57     uint32_t       num_channels;
    58     uint32_t       bytes_per_frame;
    59 
    60     jack_client_t *client;
    61     jack_port_t   *port_1;
    62     jack_port_t   *port_2;
    63     float          buf_1[BUFSIZE];
    64     float          buf_2[BUFSIZE];
    65     uint32_t       buf_read;
    66     uint32_t       buf_write;
    67 
    68     uint32_t       volume;
    69     uint32_t       mute;
    70 
    71 } jack_driver_t;
    72 
    73 typedef struct {
    74     audio_driver_class_t  driver_class;
    75     config_values_t      *config;
    76     xine_t               *xine;
    77 } jack_class_t;
    78 
    79 
    80 static int jack_process(jack_nframes_t nframes, void *arg)
    81 {
    82   jack_driver_t *this = (jack_driver_t *)arg;
    83   uint32_t local_buf_write = this->buf_write, local_buf_read;
    84   uint32_t target_channel;
    85 
    86   if (!this->client) return 0;
    87   if (this->num_channels == 0) return 0;
    88 
    89   for (target_channel = 0; target_channel < this->num_channels; target_channel++) {
    90     jack_port_t *const port = (target_channel ? this->port_2 : this->port_1);
    91     const float *const buf = (target_channel ? this->buf_2 : this->buf_1);
    92     float *out;
    93     uint32_t frame = 0;
    94 
    95     if (!port) continue;
    96 
    97     out = (float *)jack_port_get_buffer(port, nframes);
    98     local_buf_read = this->buf_read;
    99 
   100     while (frame < nframes && local_buf_read != local_buf_write) {
   101       /* local_buf_write doesn't change during this process,
   102        * so we can safely defer updating buf_read until after
   103        */
   104 
   105       out[frame++] = buf[local_buf_read];
   106       if (++local_buf_read == BUFSIZE) local_buf_read = 0;
   107     }
   108 
   109     if (frame < nframes) {
   110       lprintf("jack_process: underrun %u required, %u available\n", nframes, frame);
   111       memset(&out[frame], 0, sizeof(float)*(nframes-frame));
   112     }
   113   }
   114 
   115   this->buf_read = local_buf_read;
   116 
   117 
   118   lprintf("jack_process: buf_read %u, buf_write %u\n", this->buf_read, this->buf_write);
   119 
   120   return 0;
   121 }
   122     
   123 
   124 static void jack_shutdown(void *arg)
   125 {
   126     jack_driver_t *this = (jack_driver_t *)arg;
   127     this->client = 0;
   128 }
   129 
   130 /*
   131  * open the audio device for writing to
   132  */
   133 static int ao_jack_open(ao_driver_t *this_gen, ao_format_t format)
   134 {
   135   jack_driver_t *this = (jack_driver_t *) this_gen;
   136 
   137   this->sample_rate = jack_get_sample_rate(this->client);
   138   lprintf("ao_jack_open: JACK sample rate is %u\n", this->sample_rate);
   139 
   140   this->sample_format          = format.sample_format;
   141   this->sample_rate            = format.rate;
   142   this->num_channels           = _x_ao_mode2channels( format.mode );
   143   this->bytes_per_frame        = sample_bytes_table[format.sample_format] * this->num_channels;
   144 
   145   this->buf_read = this->buf_write = 0;
   146   this->capabilities = AO_CAP_FLOAT32 | AO_CAP_MODE_MONO | \
   147     AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL;
   148 
   149   xprintf (this->xine, XINE_VERBOSITY_DEBUG,
   150 	   "audio_jack_out: ao_open format=%d rate=%d, mode=%d\n",
   151 	   format.sample_format, format.rate, format.mode);
   152 
   153   return this->sample_rate;
   154 }
   155 
   156 
   157 static int ao_jack_num_channels(ao_driver_t *this_gen)
   158 {
   159     jack_driver_t *this = (jack_driver_t *) this_gen;
   160     return this->num_channels;
   161 }
   162 
   163 static int ao_jack_bytes_per_frame(ao_driver_t *this_gen)
   164 {
   165     jack_driver_t *this = (jack_driver_t *) this_gen;
   166     return this->bytes_per_frame;
   167 }
   168 
   169 static int ao_jack_get_gap_tolerance (ao_driver_t *this_gen)
   170 {
   171     return GAP_TOLERANCE;
   172 }
   173 
   174 static int last_write_space = 0;
   175 
   176 static int ao_jack_write(ao_driver_t *this_gen, void *data_gen,
   177                          uint32_t num_frames)
   178 {
   179   jack_driver_t *this = (jack_driver_t *) this_gen;
   180   const float *data = (const float*) data_gen;
   181   uint32_t frame, channel;
   182 
   183   uint32_t local_buf_read = this->buf_read;
   184   uint32_t local_buf_write = this->buf_write;
   185   uint32_t space = (local_buf_read + BUFSIZE - local_buf_write - 1) % BUFSIZE;    
   186   uint32_t first_frame = 0;
   187 
   188   int c = 0;
   189   while (space < num_frames) {
   190     if (++c == 10) return 0;
   191     usleep(10000);
   192     local_buf_read = this->buf_read;
   193     space = (local_buf_read + BUFSIZE - local_buf_write - 1) % BUFSIZE; 
   194   }
   195 
   196   //    if (space < num_frames) return 0;
   197 
   198   lprintf("ao_jack_write: %u frames on %u channels, space is %u\n", num_frames, this->num_channels, space);
   199   last_write_space = space;
   200 
   201   for (frame = first_frame; frame < num_frames; ++frame) {
   202     for (channel = 0; channel < this->num_channels; ++channel) {
   203       float *const buf = (channel ? this->buf_2 : this->buf_1);
   204       buf[local_buf_write] = data[frame * this->num_channels + channel];
   205     }
   206     if (++local_buf_write == BUFSIZE) local_buf_write = 0;
   207   }
   208 
   209   this->buf_write = local_buf_write;
   210 
   211   lprintf("ao_jack_write: buf_read %u, buf_write %u\n", this->buf_read, this->buf_write);
   212 
   213   return 1;
   214 }
   215 
   216 static int ao_jack_delay (ao_driver_t *this_gen)
   217 {
   218     jack_driver_t *this = (jack_driver_t *) this_gen;
   219 
   220     uint32_t local_buf_read = this->buf_read;
   221     uint32_t local_buf_write = this->buf_write;
   222 
   223     int delay = 0;
   224 
   225     if (local_buf_write > local_buf_read) {
   226         delay = local_buf_write - local_buf_read;
   227     } else {
   228         delay = ((local_buf_write + BUFSIZE - local_buf_read) % BUFSIZE);
   229     }
   230 
   231     return delay;// - jack_get_buffer_size(this->client);
   232 }
   233 
   234 static void ao_jack_close(ao_driver_t *this_gen)
   235 {
   236     // nothing
   237 }
   238 
   239 static uint32_t ao_jack_get_capabilities (ao_driver_t *this_gen) {
   240     jack_driver_t *this = (jack_driver_t *) this_gen;
   241     return this->capabilities;
   242 }
   243 
   244 static void ao_jack_exit(ao_driver_t *this_gen)
   245 {
   246     jack_driver_t *this = (jack_driver_t *) this_gen;
   247     jack_client_t *client = this->client;
   248     ao_jack_close(this_gen);
   249     this->client = 0;
   250     if (client) jack_client_close(client);
   251     free (this);
   252 }
   253 
   254 static int ao_jack_get_property (ao_driver_t *this_gen, int property) {
   255     jack_driver_t *this = (jack_driver_t *) this_gen;
   256 
   257     switch(property) {
   258     case AO_PROP_PCM_VOL:
   259     case AO_PROP_MIXER_VOL:
   260 //	printf("ao_jack_get_property(AO_PROP_MIXER_VOL): %u\n", this->volume);
   261 	return this->volume;
   262 	break;
   263     case AO_PROP_MUTE_VOL:
   264 //	printf("ao_jack_get_property(AO_PROP_MUTE_VOL): %u\n", this->mute);
   265 	return this->mute;
   266 	break;
   267     }
   268 
   269     return 0;
   270 }
   271 
   272 static int ao_jack_set_property (ao_driver_t *this_gen, int property, int value) {
   273     jack_driver_t *this = (jack_driver_t *) this_gen;
   274 
   275     switch(property) {
   276     case AO_PROP_PCM_VOL:
   277     case AO_PROP_MIXER_VOL:
   278 //	printf("ao_jack_set_property(AO_PROP_MIXER_VOL): %u\n", value);
   279 	this->volume = value;
   280 	break;
   281     case AO_PROP_MUTE_VOL:
   282 //	printf("ao_jack_get_property(AO_PROP_MUTE_VOL): %u\n", value);
   283 	this->mute = value;
   284 	break;
   285     }
   286 
   287     return ~value;
   288 }
   289 
   290 static int ao_jack_ctrl(ao_driver_t *this_gen, int cmd, ...) {
   291     jack_driver_t *this = (jack_driver_t *) this_gen;
   292 
   293     switch (cmd) {
   294 
   295     case AO_CTRL_PLAY_PAUSE:
   296 	break;
   297 
   298     case AO_CTRL_PLAY_RESUME:
   299 	break;
   300 
   301     case AO_CTRL_FLUSH_BUFFERS:
   302 	lprintf("ao_jack_ctrl(AO_CTRL_FLUSH_BUFFERS)\n");
   303 	this->buf_write = this->buf_read = 0;
   304 	break;
   305     }
   306 
   307     return 0;
   308 }
   309 
   310 static ao_driver_t *open_jack_plugin (audio_driver_class_t *class_gen,
   311 				      const void *data)
   312 {
   313     jack_class_t  *class = (jack_class_t *) class_gen;
   314     jack_driver_t *this;
   315     jack_client_t *client;
   316     uint32_t rate;
   317     const char **port_names;
   318     int i;
   319 
   320     if ((client = jack_client_new(__progname)) == 0) {
   321       char *name;
   322       
   323       asprintf(&name, "%s (%d)", __progname, (int)getpid());
   324 
   325       if ((client = jack_client_new(name)) == 0) {
   326 	lprintf("\nopen_jack_plugin: Error: Failed to connect to JACK server\n"
   327 		"open_jack_plugin: (did you start 'jackd' server?)\n");
   328 	return 0;
   329       }
   330     }
   331 
   332     this = (jack_driver_t *) xine_xmalloc (sizeof (jack_driver_t));
   333     
   334     this->client = client;
   335 
   336     jack_set_process_callback(client, jack_process, this);
   337     jack_on_shutdown(client, jack_shutdown, this);
   338 
   339     rate = jack_get_sample_rate(client);
   340     lprintf("open_jack_plugin: JACK sample rate is %u\n", rate);
   341 
   342     // We support up to 2-channel output
   343 
   344     for (i = 0; i < 2; ++i) {
   345 	jack_port_t *port = jack_port_register
   346 	    (client, (i ? "out_r" : "out_l"),
   347 	     JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
   348 	if (!port) {
   349 	    lprintf("ao_jack_open: failed to register port %u\n", i);
   350 	}
   351 	if (i) this->port_2 = port;
   352 	else   this->port_1 = port;
   353     }
   354 
   355     this->buf_read = this->buf_write = 0;
   356     this->volume = 100;
   357     this->mute = 0;
   358 
   359     if (jack_activate(client)) {
   360 	lprintf("ao_jack_open: failed to activate JACK client\n");
   361 	return 0;
   362     }
   363 
   364     if ((port_names = jack_get_ports(client, NULL, NULL,
   365 				     JackPortIsPhysical | JackPortIsInput)) != NULL) {
   366 	if (port_names[0]) {
   367 	    jack_connect(client, jack_port_name(this->port_1), port_names[0]);
   368 	}
   369 	if (port_names[1] && this->port_2) {
   370 	    jack_connect(client, jack_port_name(this->port_2), port_names[1]);
   371 	}
   372 	free(port_names);
   373     }
   374 
   375     this->sample_rate = rate;
   376 
   377     this->xine = class->xine;
   378     this->capabilities = AO_CAP_FLOAT32 | AO_CAP_MODE_MONO | 
   379 	AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL;
   380 
   381     this->ao_driver.get_capabilities    = ao_jack_get_capabilities;
   382     this->ao_driver.get_property        = ao_jack_get_property;
   383     this->ao_driver.set_property        = ao_jack_set_property;
   384     this->ao_driver.open                = ao_jack_open;
   385     this->ao_driver.num_channels        = ao_jack_num_channels;
   386     this->ao_driver.bytes_per_frame     = ao_jack_bytes_per_frame;
   387     this->ao_driver.delay               = ao_jack_delay;
   388     this->ao_driver.write               = ao_jack_write;
   389     this->ao_driver.close               = ao_jack_close;
   390     this->ao_driver.exit                = ao_jack_exit;
   391     this->ao_driver.get_gap_tolerance   = ao_jack_get_gap_tolerance;
   392     this->ao_driver.control             = ao_jack_ctrl;
   393 
   394     lprintf("jack open_jack_plugin returning %p\n", (void *)(&this->ao_driver));
   395     return &this->ao_driver;
   396 }
   397 
   398 /*
   399  * class functions
   400  */
   401 static void *init_class (xine_t *xine, void *data) {
   402 
   403     jack_class_t        *this;
   404 
   405     this = (jack_class_t *) xine_xmalloc (sizeof (jack_class_t));
   406 
   407     this->driver_class.open_plugin     = open_jack_plugin;
   408     this->driver_class.identifier      = "jack";
   409     this->driver_class.description     = N_("xine output plugin for JACK Audio Connection Kit");
   410     this->driver_class.dispose         = default_audio_driver_class_dispose;
   411 
   412     this->config = xine->config;
   413     this->xine   = xine;
   414 
   415     lprintf("jack init_class returning %p\n", (void *)this);
   416 
   417     return this;
   418 }
   419 
   420 static ao_info_t ao_info_jack = {
   421     6
   422 };
   423 
   424 /*
   425  * exported plugin catalog entry
   426  */
   427 
   428 const plugin_info_t xine_plugin_info[] EXPORTED = {
   429     /* type, API, "name", version, special_info, init_function */
   430     { PLUGIN_AUDIO_OUT, AO_OUT_JACK_IFACE_VERSION, "jack", XINE_VERSION_CODE /* XINE_VERSION_CODE */, &ao_info_jack, init_class },
   431     { PLUGIN_NONE, 0, "", 0, NULL, NULL }
   432 };
   433