Statistics
| Branch: | Tag: | Revision:

root / gr-audio-jack / src / audio_jack_source.cc @ d692a41f

History | View | Annotate | Download (6.8 kB)

1 5d69a524 jcorgan
/* -*- c++ -*- */
2 5d69a524 jcorgan
/*
3 0a9b999b Eric Blossom
 * Copyright 2005,2006,2010 Free Software Foundation, Inc.
4 5d69a524 jcorgan
 * 
5 5d69a524 jcorgan
 * This file is part of GNU Radio
6 5d69a524 jcorgan
 * 
7 5d69a524 jcorgan
 * GNU Radio is free software; you can redistribute it and/or modify
8 5d69a524 jcorgan
 * it under the terms of the GNU General Public License as published by
9 937b719d eb
 * the Free Software Foundation; either version 3, or (at your option)
10 5d69a524 jcorgan
 * any later version.
11 5d69a524 jcorgan
 * 
12 5d69a524 jcorgan
 * GNU Radio is distributed in the hope that it will be useful,
13 5d69a524 jcorgan
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 5d69a524 jcorgan
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 5d69a524 jcorgan
 * GNU General Public License for more details.
16 5d69a524 jcorgan
 * 
17 5d69a524 jcorgan
 * You should have received a copy of the GNU General Public License
18 5d69a524 jcorgan
 * along with GNU Radio; see the file COPYING.  If not, write to
19 86f5c924 eb
 * the Free Software Foundation, Inc., 51 Franklin Street,
20 86f5c924 eb
 * Boston, MA 02110-1301, USA.
21 5d69a524 jcorgan
 */
22 5d69a524 jcorgan
23 5d69a524 jcorgan
#ifdef HAVE_CONFIG_H
24 5d69a524 jcorgan
#include "config.h"
25 5d69a524 jcorgan
#endif
26 5d69a524 jcorgan
27 5d69a524 jcorgan
#include <audio_jack_source.h>
28 5d69a524 jcorgan
#include <gr_io_signature.h>
29 5d69a524 jcorgan
#include <gr_prefs.h>
30 5d69a524 jcorgan
#include <stdio.h>
31 5d69a524 jcorgan
#include <iostream>
32 5d69a524 jcorgan
#include <stdexcept>
33 5d69a524 jcorgan
#include <gri_jack.h>
34 5d69a524 jcorgan
35 5d69a524 jcorgan
#ifndef NO_PTHREAD
36 5d69a524 jcorgan
#include <pthread.h>
37 5d69a524 jcorgan
#endif
38 5d69a524 jcorgan
39 5d69a524 jcorgan
typedef jack_default_audio_sample_t sample_t;
40 5d69a524 jcorgan
41 5d69a524 jcorgan
42 5d69a524 jcorgan
// Number of jack buffers in the ringbuffer
43 5d69a524 jcorgan
// TODO: make it to match at least the quantity of items passed to work()
44 5d69a524 jcorgan
static const unsigned int N_BUFFERS = 16;
45 5d69a524 jcorgan
46 5d69a524 jcorgan
static std::string 
47 5d69a524 jcorgan
default_device_name ()
48 5d69a524 jcorgan
{
49 5d69a524 jcorgan
  return gr_prefs::singleton()->get_string("audio_jack", "default_input_device", "gr_source");
50 5d69a524 jcorgan
}
51 5d69a524 jcorgan
52 5d69a524 jcorgan
53 5d69a524 jcorgan
int
54 5d69a524 jcorgan
jack_source_process (jack_nframes_t nframes, void *arg)
55 5d69a524 jcorgan
{
56 5d69a524 jcorgan
  audio_jack_source *self = (audio_jack_source *)arg;
57 5d69a524 jcorgan
  unsigned int write_size = nframes*sizeof(sample_t);
58 5d69a524 jcorgan
59 5d69a524 jcorgan
  if (jack_ringbuffer_write_space (self->d_ringbuffer) < write_size) {
60 5d69a524 jcorgan
    self->d_noverruns++;
61 5d69a524 jcorgan
    // FIXME: move this fputs out, we shouldn't use blocking calls in process()
62 5d69a524 jcorgan
    fputs ("jO", stderr);
63 5d69a524 jcorgan
    return 0;
64 5d69a524 jcorgan
  }
65 5d69a524 jcorgan
66 5d69a524 jcorgan
  char *buffer = (char *) jack_port_get_buffer (self->d_jack_input_port, nframes);
67 5d69a524 jcorgan
68 5d69a524 jcorgan
  jack_ringbuffer_write (self->d_ringbuffer, buffer, write_size);
69 5d69a524 jcorgan
70 5d69a524 jcorgan
#ifndef NO_PTHREAD
71 5d69a524 jcorgan
  // Tell the source thread there is data in the ringbuffer.
72 5d69a524 jcorgan
  // If it is already running, the lock will not be available.
73 5d69a524 jcorgan
  // We can't wait here in the process() thread, but we don't
74 5d69a524 jcorgan
  // need to signal in that case, because the source thread will 
75 5d69a524 jcorgan
  // check for data availability.
76 5d69a524 jcorgan
77 5d69a524 jcorgan
  if (pthread_mutex_trylock (&self->d_jack_process_lock) == 0) {
78 5d69a524 jcorgan
    pthread_cond_signal (&self->d_ringbuffer_ready);
79 5d69a524 jcorgan
    pthread_mutex_unlock (&self->d_jack_process_lock);
80 5d69a524 jcorgan
  }
81 5d69a524 jcorgan
#endif
82 5d69a524 jcorgan
83 5d69a524 jcorgan
  return 0;
84 5d69a524 jcorgan
}
85 5d69a524 jcorgan
86 5d69a524 jcorgan
// ----------------------------------------------------------------
87 5d69a524 jcorgan
88 5d69a524 jcorgan
audio_jack_source_sptr
89 5d69a524 jcorgan
audio_jack_make_source (int sampling_rate, const std::string dev, bool ok_to_block)
90 5d69a524 jcorgan
{
91 0a9b999b Eric Blossom
  return gnuradio::get_initial_sptr(new audio_jack_source (sampling_rate, dev, ok_to_block));
92 5d69a524 jcorgan
}
93 5d69a524 jcorgan
94 5d69a524 jcorgan
audio_jack_source::audio_jack_source (int sampling_rate,
95 5d69a524 jcorgan
                                      const std::string device_name,
96 5d69a524 jcorgan
                                      bool ok_to_block)
97 5d69a524 jcorgan
  : gr_sync_block ("audio_jack_source",
98 5d69a524 jcorgan
                   gr_make_io_signature (0, 0, 0),
99 5d69a524 jcorgan
                   gr_make_io_signature (0, 0, 0)),
100 5d69a524 jcorgan
    d_sampling_rate (sampling_rate),
101 5d69a524 jcorgan
    d_device_name (device_name.empty() ? default_device_name() : device_name),
102 5d69a524 jcorgan
    d_ok_to_block(ok_to_block),
103 5d69a524 jcorgan
    d_jack_client (0),
104 5d69a524 jcorgan
    d_ringbuffer (0),
105 5d69a524 jcorgan
    d_noverruns (0)
106 5d69a524 jcorgan
{
107 5d69a524 jcorgan
#ifndef NO_PTHREAD
108 5d69a524 jcorgan
    pthread_cond_init(&d_ringbuffer_ready, NULL);;
109 5d69a524 jcorgan
    pthread_mutex_init(&d_jack_process_lock, NULL);
110 5d69a524 jcorgan
#endif
111 5d69a524 jcorgan
112 5d69a524 jcorgan
  // try to become a client of the JACK server
113 5d69a524 jcorgan
  if ((d_jack_client = jack_client_new (d_device_name.c_str ())) == 0) {
114 5d69a524 jcorgan
    fprintf (stderr, "audio_jack_source[%s]: jack server not running?\n",
115 5d69a524 jcorgan
             d_device_name.c_str());
116 5d69a524 jcorgan
    throw std::runtime_error ("audio_jack_source");
117 5d69a524 jcorgan
  }
118 5d69a524 jcorgan
119 5d69a524 jcorgan
  // tell the JACK server to call `jack_source_process()' whenever
120 5d69a524 jcorgan
  // there is work to be done.
121 5d69a524 jcorgan
  jack_set_process_callback (d_jack_client, &jack_source_process, (void*)this);
122 5d69a524 jcorgan
123 5d69a524 jcorgan
  // tell the JACK server to call `jack_shutdown()' if
124 5d69a524 jcorgan
  // it ever shuts down, either entirely, or if it
125 5d69a524 jcorgan
  // just decides to stop calling us.
126 5d69a524 jcorgan
127 5d69a524 jcorgan
  //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this);
128 5d69a524 jcorgan
 
129 5d69a524 jcorgan
  d_jack_input_port = jack_port_register (d_jack_client, "in", 
130 5d69a524 jcorgan
                                          JACK_DEFAULT_AUDIO_TYPE,
131 5d69a524 jcorgan
                                          JackPortIsInput, 0);
132 5d69a524 jcorgan
133 5d69a524 jcorgan
134 5d69a524 jcorgan
  d_jack_buffer_size = jack_get_buffer_size (d_jack_client);
135 5d69a524 jcorgan
136 5d69a524 jcorgan
  set_output_multiple (d_jack_buffer_size);
137 5d69a524 jcorgan
138 5d69a524 jcorgan
  d_ringbuffer = jack_ringbuffer_create (N_BUFFERS*d_jack_buffer_size*sizeof(sample_t));
139 5d69a524 jcorgan
  if (d_ringbuffer == NULL)
140 5d69a524 jcorgan
    bail ("jack_ringbuffer_create failed", 0);
141 5d69a524 jcorgan
142 5d69a524 jcorgan
  assert(sizeof(float)==sizeof(sample_t));
143 5d69a524 jcorgan
  set_output_signature (gr_make_io_signature (1, 1, sizeof (sample_t)));
144 5d69a524 jcorgan
145 5d69a524 jcorgan
146 5d69a524 jcorgan
  jack_nframes_t sample_rate = jack_get_sample_rate (d_jack_client);
147 5d69a524 jcorgan
148 5d69a524 jcorgan
  if ((jack_nframes_t)sampling_rate != sample_rate){
149 5d69a524 jcorgan
    fprintf (stderr, "audio_jack_source[%s]: unable to support sampling rate %d\n",
150 5d69a524 jcorgan
             d_device_name.c_str (), sampling_rate);
151 5d69a524 jcorgan
    fprintf (stderr, "  card requested %d instead.\n", sample_rate);
152 5d69a524 jcorgan
  }
153 5d69a524 jcorgan
}
154 5d69a524 jcorgan
155 5d69a524 jcorgan
156 5d69a524 jcorgan
bool
157 5d69a524 jcorgan
audio_jack_source::check_topology (int ninputs, int noutputs)
158 5d69a524 jcorgan
{
159 5d69a524 jcorgan
  // tell the JACK server that we are ready to roll 
160 5d69a524 jcorgan
  if (jack_activate (d_jack_client))
161 5d69a524 jcorgan
    throw std::runtime_error ("audio_jack_source");
162 5d69a524 jcorgan
163 5d69a524 jcorgan
  return true;
164 5d69a524 jcorgan
}
165 5d69a524 jcorgan
166 5d69a524 jcorgan
audio_jack_source::~audio_jack_source ()
167 5d69a524 jcorgan
{
168 5d69a524 jcorgan
  jack_client_close (d_jack_client);
169 5d69a524 jcorgan
  jack_ringbuffer_free (d_ringbuffer);
170 5d69a524 jcorgan
}
171 5d69a524 jcorgan
172 5d69a524 jcorgan
int
173 5d69a524 jcorgan
audio_jack_source::work (int noutput_items,
174 5d69a524 jcorgan
                         gr_vector_const_void_star &input_items,
175 5d69a524 jcorgan
                         gr_vector_void_star &output_items)
176 5d69a524 jcorgan
{
177 5d69a524 jcorgan
  // read_size and work_size are in bytes
178 5d69a524 jcorgan
  unsigned int read_size;
179 5d69a524 jcorgan
180 5d69a524 jcorgan
  // Minimize latency
181 5d69a524 jcorgan
  noutput_items = std::min (noutput_items, (int)d_jack_buffer_size);
182 5d69a524 jcorgan
183 5d69a524 jcorgan
  int work_size = noutput_items*sizeof(sample_t);
184 5d69a524 jcorgan
185 5d69a524 jcorgan
  while (work_size > 0) {
186 5d69a524 jcorgan
    unsigned int read_space;        // bytes
187 5d69a524 jcorgan
188 5d69a524 jcorgan
#ifdef NO_PTHREAD
189 5d69a524 jcorgan
    while ((read_space=jack_ringbuffer_read_space (d_ringbuffer)) < 
190 5d69a524 jcorgan
           d_jack_buffer_size*sizeof(sample_t)) {
191 5d69a524 jcorgan
      usleep(1000000*((d_jack_buffer_size-read_space/sizeof(sample_t))/d_sampling_rate));
192 5d69a524 jcorgan
    }
193 5d69a524 jcorgan
#else
194 5d69a524 jcorgan
    // JACK actually requires POSIX
195 5d69a524 jcorgan
196 5d69a524 jcorgan
    pthread_mutex_lock (&d_jack_process_lock);
197 5d69a524 jcorgan
    while ((read_space=jack_ringbuffer_read_space (d_ringbuffer)) < 
198 5d69a524 jcorgan
                    d_jack_buffer_size*sizeof(sample_t)) {
199 5d69a524 jcorgan
200 5d69a524 jcorgan
      // wait until jack_source_process() signals more data
201 5d69a524 jcorgan
      pthread_cond_wait (&d_ringbuffer_ready, &d_jack_process_lock);
202 5d69a524 jcorgan
    }
203 5d69a524 jcorgan
    pthread_mutex_unlock (&d_jack_process_lock);
204 5d69a524 jcorgan
#endif
205 5d69a524 jcorgan
206 5d69a524 jcorgan
    read_space -= read_space%(d_jack_buffer_size*sizeof(sample_t));
207 5d69a524 jcorgan
    read_size = std::min(read_space, (unsigned int)work_size);
208 5d69a524 jcorgan
209 5d69a524 jcorgan
    if (jack_ringbuffer_read (d_ringbuffer, (char *) output_items[0],
210 5d69a524 jcorgan
                              read_size) < read_size) {
211 5d69a524 jcorgan
      bail ("jack_ringbuffer_read failed", 0);
212 5d69a524 jcorgan
    }
213 5d69a524 jcorgan
    work_size -= read_size;
214 5d69a524 jcorgan
  }
215 5d69a524 jcorgan
216 5d69a524 jcorgan
  return noutput_items;
217 5d69a524 jcorgan
}
218 5d69a524 jcorgan
219 5d69a524 jcorgan
void
220 5d69a524 jcorgan
audio_jack_source::output_error_msg (const char *msg, int err)
221 5d69a524 jcorgan
{
222 5d69a524 jcorgan
  fprintf (stderr, "audio_jack_source[%s]: %s: %d\n",
223 5d69a524 jcorgan
           d_device_name.c_str (), msg,  err);
224 5d69a524 jcorgan
}
225 5d69a524 jcorgan
226 5d69a524 jcorgan
void
227 5d69a524 jcorgan
audio_jack_source::bail (const char *msg, int err) throw (std::runtime_error)
228 5d69a524 jcorgan
{
229 5d69a524 jcorgan
  output_error_msg (msg, err);
230 5d69a524 jcorgan
  throw std::runtime_error ("audio_jack_source");
231 5d69a524 jcorgan
}