MythTV master
audiooutputjack.cpp
Go to the documentation of this file.
1/*
2 * JACK AudioOutput module
3 * Written by Ed Wildgoose in 2010 with improvements from various authors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <algorithm>
21#include <cerrno>
22#include <cmath>
23#include <cstdio>
24#include <cstdlib>
25#include <cstring>
26#include <fcntl.h>
27#include <sys/time.h>
28#include <unistd.h>
29
33
34#include "audiooutputjack.h"
35
36#define LOC QString("AOJack: ")
37
39 AudioOutputBase(settings)
40{
41 m_ports.fill( nullptr);
42 m_chanVolumes.fill(100);
43
44 // Set everything up
45 InitSettings(settings);
46 if (settings.m_init)
47 Reconfigure(settings);
48}
49
51{
52 // Set up to automatically close client at function exit
53 auto cleanup_fn = [&](AudioOutputJACK* /*p*/) {
55 };
56 std::unique_ptr<AudioOutputJACK, decltype(cleanup_fn)> cleanup { this, cleanup_fn };
57
58 int rate = 0;
59 auto settings = std::make_unique<AudioOutputSettings>();
60
62 if (!m_client)
63 {
64 QString message {LOC + tr("Cannot start/connect to jack server (to check supported rate/channels)")};
65 dispatchError(message);
66 LOG(VB_GENERAL, LOG_ERR, message);
67 return nullptr;
68 }
69
70 if (m_client)
71 rate = jack_get_sample_rate(m_client);
72
73 if (!rate)
74 {
75 QString message {LOC + tr("Unable to retrieve jack server sample rate")};
76 dispatchError(message);
77 LOG(VB_GENERAL, LOG_ERR, message);
78 return nullptr;
79 }
80 settings->AddSupportedRate(rate);
81
82 // Jack only wants float format samples (de-interleaved for preference)
83 settings->AddSupportedFormat(FORMAT_FLT);
84
85 // Find some Jack ports to connect to. Release at function exit.
86 std::unique_ptr<const char *, decltype(&jack_free)>
87 matching_ports { JackGetPorts(), &jack_free };
88 if (!matching_ports || !matching_ports.get()[0])
89 {
90 QString message {LOC + tr("No ports available to connect to")};
91 dispatchError(message);
92 LOG(VB_GENERAL, LOG_ERR, message);
93 return nullptr;
94 }
95 // Count matching ports from 2nd port upwards
96 for (int i=1; (i < JACK_CHANNELS_MAX) && matching_ports.get()[i]; i++)
97 {
98 settings->AddSupportedChannels(i+1);
99 LOG(VB_AUDIO, LOG_INFO, LOC + QString("Adding channels: %1").arg(i+1));
100 }
101
102 // Return settings instead of deleting it
103 return settings.release();
104}
105
106
108{
109 // Close down all audio stuff
110 KillAudio();
111}
112
114{
115 // Set up to automatically close client at function exit
116 auto cleanup_fn = [](AudioOutputJACK *p)
117 { if (p->m_client) p->JackClientClose(&p->m_client); };
118 std::unique_ptr<AudioOutputJACK, decltype(cleanup_fn)>
119 cleanup { this, cleanup_fn };
120
121 // We have a hard coded channel limit - check we haven't exceeded it
123 {
124 QString message {LOC + tr("Requested more channels: (%1), than the maximum: %2")
125 .arg(m_channels).arg(JACK_CHANNELS_MAX)};
126 dispatchError(message);
127 LOG(VB_GENERAL, LOG_ERR, message);
128 return false;
129 }
130
131 LOG(VB_AUDIO, LOG_INFO, LOC + QString("Opening JACK audio device: '%1'.")
132 .arg(m_mainDevice));
133
134 // Setup volume control
135 if (m_internalVol)
136 VolumeInit();
137
138 // Connect to the Jack audio server
140 if (!m_client)
141 {
142 QString message {LOC + tr("Cannot start/connect to jack server")};
143 dispatchError(message);
144 LOG(VB_GENERAL, LOG_ERR, message);
145 return false;
146 }
147
148 // Find some Jack ports to connect to. Release at function exit.
149 std::unique_ptr<const char *, decltype(&jack_free)>
150 matching_ports { JackGetPorts(), &jack_free };
151 if (!matching_ports || !matching_ports.get()[0])
152 {
153 QString message {LOC + tr("No ports available to connect to")};
154 dispatchError(message);
155 LOG(VB_GENERAL, LOG_ERR, message);
156 return false;
157 }
158
159 // Count matching ports
160 int i = 1;
161 while (matching_ports.get()[i])
162 i++;
163 // ensure enough ports to satisfy request
164 if (m_channels > i)
165 {
166 QString message {LOC + tr("Not enough ports available to connect to")};
167 dispatchError(message);
168 LOG(VB_GENERAL, LOG_ERR, message);
169 return false;
170 }
171
172 // Create our output ports
173 for (i = 0; i < m_channels; i++)
174 {
175 QString port_name = QString("out_%1").arg(i);
176 m_ports[i] = jack_port_register(m_client, port_name.toLatin1().constData(),
177 JACK_DEFAULT_AUDIO_TYPE,
178 JackPortIsOutput, 0);
179 if (!m_ports[i])
180 {
181 QString message {LOC + tr("Error while registering new jack port: %1").arg(i)};
182 dispatchError(message);
183 LOG(VB_GENERAL, LOG_ERR, message);
184 return false;
185 }
186 }
187
188 // Note some basic soundserver parameters
189 m_sampleRate = jack_get_sample_rate(m_client);
190
191 // Get the size of our callback buffer in bytes
192 m_fragmentSize = jack_get_buffer_size(m_client) * m_outputBytesPerFrame;
193
194 // Allocate a new temp buffer to de-interleave our audio data
195 delete[] m_auBuf;
196 m_auBuf = new unsigned char[m_fragmentSize];
197
198 // Set our callbacks
199 // These will actually get called after jack_activate()!
200 // ...Possibly even before this OpenDevice sub returns...
201 if (jack_set_process_callback(m_client, JackCallbackHelper, this))
202 {
203 QString message {LOC + tr("Error. Unable to set process callback?!")};
204 dispatchError(message);
205 LOG(VB_GENERAL, LOG_ERR, message);
206 }
207 if (jack_set_xrun_callback(m_client, JackXRunCallbackHelper, this))
208 {
209 QString message {LOC + tr("Error. Unable to set xrun callback?!")};
210 dispatchError(message);
211 LOG(VB_GENERAL, LOG_ERR, message);
212 }
213 if (jack_set_graph_order_callback(m_client, JackGraphOrderCallbackHelper, this))
214 {
215 QString message {LOC + tr("Error. Unable to set graph order change callback?!")};
216 dispatchError(message);
217 LOG(VB_GENERAL, LOG_ERR, message);
218 }
219
220 // Activate! Everything comes into life after here. Beware races
221 if (jack_activate(m_client))
222 {
223 QString message {LOC + tr("Calling jack_activate failed")};
224 dispatchError(message);
225 LOG(VB_GENERAL, LOG_ERR, message);
226 return false;
227 }
228
229 // Connect our output ports
230 if (! JackConnectPorts(matching_ports.get()))
231 return false;
232
233 // Device opened successfully. Skip client cleanup function.
234 cleanup.release();
235 return true;
236}
237
239{
242 if (m_auBuf)
243 {
244 delete[] m_auBuf;
245 m_auBuf = nullptr;
246 }
247
248 LOG(VB_AUDIO, LOG_INFO, LOC + "Jack: Stop Event");
249 Event e(Event::kStopped);
250 dispatch(e);
251}
252
253
255{
256 int frames_played = jack_frames_since_cycle_start (this->m_client);
257 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_INFO,
258 QString("Stats: frames_since_cycle_start:%1 fragment_size:%2")
259 .arg(frames_played).arg(m_fragmentSize));
260 return (m_fragmentSize * 2) - (frames_played * m_outputBytesPerFrame);
261}
262
263/* Converts buffer to jack buffers
264 Input: aubuf: interleaved buffer of currently assumed to be 32bit floats
265 nframes: number of frames of output required
266 Output: bufs: non interleaved float values.
267*/
268void AudioOutputJACK::DeinterleaveAudio(const float *aubuf, float **bufs, int nframes,
269 const jack_vol_array& channel_volumes)
270{
271 // Convert to floats and de-interleave
272 // TODO: Implicit assumption dealing with float input only.
273 short sample = 0;
274
275 // Create a local float version of the channel_volumes array
276 // TODO: This can probably be removed
277 // if we have float software volume control in AOB?
278 std::array<float,JACK_CHANNELS_MAX> volumes {};
279 for (int channel = 0; channel < m_channels; channel++)
280 {
281 if (m_internalVol)
282 {
283 // Software volume control - we use an exponential adjustment
284 // (perhaps should be log?)
285 volumes[channel] = (float) (( channel_volumes[channel] *
286 channel_volumes[channel] ) /
287 10000.0);
288 }
289 else
290 {
291 volumes[channel] = 1.0 / 1.0; // ie no effect
292 }
293 }
294
295 if (m_channels == 2)
296 {
297 for (int frame = 0; frame < nframes; frame++)
298 {
299 bufs[0][frame] = aubuf[sample++] * volumes[0];
300 bufs[1][frame] = aubuf[sample++] * volumes[1];
301 }
302 }
303 else if (m_channels == 6)
304 {
305 for (int frame = 0; frame < nframes; frame++)
306 {
307 // Audio supplied in SMPTE l,r,ce,lfe,lr,rr
308 // We probably want it in ALSA format l,r,lr,rr,ce,lfe
309 bufs[0][frame] = aubuf[sample++] * volumes[0];
310 bufs[1][frame] = aubuf[sample++] * volumes[1];
311 bufs[4][frame] = aubuf[sample++] * volumes[4];
312 bufs[5][frame] = aubuf[sample++] * volumes[5];
313 bufs[2][frame] = aubuf[sample++] * volumes[2];
314 bufs[3][frame] = aubuf[sample++] * volumes[3];
315 }
316 }
317 else if (m_channels == 8)
318 {
319 for (int frame = 0; frame < nframes; frame++)
320 {
321 // Audio supplied in SMPTE l,r,ce,lfe,lr,rr,ml,mr ?
322 // We probably want it in ALSA format l,r,lr,rr,ce,lfe,ml,mr ?
323 // TODO - unknown if this channel ordering is correct?
324 bufs[0][frame] = aubuf[sample++] * volumes[0];
325 bufs[1][frame] = aubuf[sample++] * volumes[1];
326 bufs[4][frame] = aubuf[sample++] * volumes[4];
327 bufs[5][frame] = aubuf[sample++] * volumes[5];
328 bufs[2][frame] = aubuf[sample++] * volumes[2];
329 bufs[3][frame] = aubuf[sample++] * volumes[3];
330 bufs[6][frame] = aubuf[sample++] * volumes[6];
331 bufs[7][frame] = aubuf[sample++] * volumes[7];
332 }
333 }
334 else
335 {
336 for (int frame = 0; frame < nframes; frame++)
337 {
338 // Straightforward de-interleave for all other cases.
339 // Note no channel re-ordering...
340 for (int channel = 0; channel < m_channels; channel++)
341 {
342 bufs[channel][frame] = aubuf[sample++] * volumes[channel];
343 }
344 }
345 }
346
347}
348
349/* ***************************************************************************
350 Jack Callbacks
351 ****************************************************************************/
352
353/* Our Jack callback.
354 Jack will call this from a separate thread whenever it needs "feeding"
355 Simply calls our real code
356*/
357int AudioOutputJACK::JackCallbackHelper(jack_nframes_t nframes, void *arg)
358{
359 auto *aoj = static_cast<AudioOutputJACK*>(arg);
360 return aoj->JackCallback(nframes);
361}
362
363/* Useful bit of the callback
364 This callback is called when the sound system requests
365 data. We don't want to block here, because that would
366 just cause dropouts anyway, so we always return whatever
367 data is available. If we haven't received enough, either
368 because we've finished playing or we have a buffer
369 underrun, we play silence to fill the unused space.
370 Return: 0 on success, non zero on error
371*/
372int AudioOutputJACK::JackCallback(jack_nframes_t nframes)
373{
374 std::array<float*,JACK_CHANNELS_MAX> bufs {};
375 int bytes_needed = nframes * m_outputBytesPerFrame;
376 int bytes_read = 0;
377
378 // Check for stale_client set during shutdown callback
380
381 // Deal with xruns which may have occured
382 // Basically read and discard the data which should have been played
383 int t_jack_xruns = m_jackXruns;
384 for (int i = 0; i < t_jack_xruns; i++)
385 {
386 bytes_read = GetAudioData(m_auBuf, m_fragmentSize, true);
387 LOG(VB_GENERAL, LOG_ERR, LOC + "Discarded one audio fragment to compensate for xrun");
388 }
389 m_jackXruns -= t_jack_xruns;
390
391 // Get jack output buffers. Zero out the extra space in the array
392 // to prevent clang-tidy from complaining that DeinterleaveAudio()
393 // can reference a garbage value.
394 int i = 0;
395 for ( ; i < m_channels; i++)
396 bufs[i] = (float*)jack_port_get_buffer(m_ports[i], nframes);
397 for ( ; i < JACK_CHANNELS_MAX; i++)
398 bufs[i] = nullptr;
399
401 {
402 if (!m_actuallyPaused)
403 {
404 LOG(VB_AUDIO, LOG_INFO, LOC + "JackCallback: audio paused");
405 Event e(Event::kPaused);
406 dispatch(e);
407 m_wasPaused = true;
408 }
409
410 m_actuallyPaused = true;
411 }
412 else
413 {
414 if (m_wasPaused)
415 {
416 LOG(VB_AUDIO, LOG_INFO, LOC + "JackCallback: Play Event");
417 Event e(Event::kPlaying);
418 dispatch(e);
419 m_wasPaused = false;
420 }
421 bytes_read = GetAudioData(m_auBuf, bytes_needed, false);
422 }
423
424 // Pad with silence
425 if (bytes_needed > bytes_read)
426 {
427 // play silence on buffer underrun
428 memset(m_auBuf + bytes_read, 0, bytes_needed - bytes_read);
429 if (!m_pauseAudio)
430 {
431 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Having to insert silence because GetAudioData "
432 "hasn't returned enough data. Wanted: %1 Got: %2")
433 .arg(bytes_needed).arg(bytes_read));
434 }
435 }
436 // Now deinterleave audio (and convert to float)
437 DeinterleaveAudio((float*)m_auBuf, bufs.data(), nframes, m_chanVolumes);
438
439 if (!m_pauseAudio)
440 {
441 // Output a status event - needed for Music player
442 Status();
443 }
444
445 return 0;
446}
447
448
449/* Our Jack XRun callback.
450 Jack will call this from a separate thread whenever an xrun occurs
451 Simply calls our real code
452*/
454{
455 auto *aoj = static_cast<AudioOutputJACK*>(arg);
456 return aoj->JackXRunCallback();
457}
458
459/* Useful bit of the XRun callback
460 Return: 0 on success, non zero on error
461*/
463{
464 float delay = jack_get_xrun_delayed_usecs(m_client); // usecs
465 // Increment our counter of "callbacks missed".
466 // All we want to do is chuck away some audio from the ring buffer
467 // to keep our audio output roughly where it should be if we didn't xrun
468 int fragments = (int)ceilf( ((delay / 1000000.0F) * m_sampleRate )
470 m_jackXruns += fragments; //should be at least 1...
471 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Jack XRun Callback: %1 usecs delayed, xruns now %2")
472 .arg(delay).arg(m_jackXruns) );
473
474 return 0;
475}
476
477/* Our Jack Graph Order Change callback.
478 Jack will call this from a separate thread whenever an xrun occurs
479 Simply calls our real code
480*/
482{
483 auto *aoj = static_cast<AudioOutputJACK*>(arg);
484 return aoj->JackGraphOrderCallback();
485}
486
487/* Useful bit of the Graph Order Change callback
488 Called when the Jack graph changes. We update our latency info
489 Return: 0 on success, non zero on error
490*/
492{
493 jack_latency_range_t latency_range;
494 jack_nframes_t max_latency = 0;
495
496 for (int i = 0; i < m_channels; ++i)
497 {
498 jack_port_get_latency_range( m_ports[i], JackPlaybackLatency, &latency_range );
499 jack_nframes_t port_latency = latency_range.max;
500 max_latency = std::max(port_latency, max_latency);
501 }
502
503 m_jackLatency = max_latency;
504 LOG(VB_AUDIO, LOG_INFO, LOC + QString("JACK graph reordered. Maximum latency=%1")
505 .arg(m_jackLatency));
506
507 return 0;
508}
509
510
511/* Volume related handling */
513{
514 int volume = 100;
515 if (m_setInitialVol)
516 {
517 QString controlLabel = gCoreContext->GetSetting("MixerControl", "PCM");
518 controlLabel += "MixerVolume";
519 volume = gCoreContext->GetNumSetting(controlLabel, 80);
520 }
521
522 m_chanVolumes.fill(volume);
523}
524
526{
527 unsigned int vol = 0;
528
529 if (!m_internalVol)
530 return 100;
531
532 if (channel < JACK_CHANNELS_MAX)
533 vol = m_chanVolumes[channel];
534
535 return vol;
536}
537
538void AudioOutputJACK::SetVolumeChannel(int channel, int volume)
539{
540 if (m_internalVol && (channel < JACK_CHANNELS_MAX))
541 {
542 m_chanVolumes[channel] = volume;
543 if (channel == 0)
544 {
545 // Left
546 m_chanVolumes[2] = volume; // left rear
547 }
548 else if (channel == 1)
549 {
550 // Right
551 m_chanVolumes[3] = volume; // right rear
552 }
553
554 // LFE and Center
556 (m_chanVolumes[0] + m_chanVolumes[1]) / 2;
557 }
558}
559
560
561/* We don't need an audio output thread for Jack
562 Everything handled by callbacks here
563 Therefore we can loose all the Start/StopOutputThread, WriteAudio, etc
564*/
566{
567 return true;
568}
569
571{
572}
573
574// Don't need WriteAudio - this is only for the base class audio loop
575void AudioOutputJACK::WriteAudio([[maybe_unused]] unsigned char *aubuf,
576 [[maybe_unused]] int size)
577{
578 // unneeded and unused in JACK
579}
580
581/* **********************************************
582 Jack wrapper and convenience functions
583 ***********************************************/
584
586{
587 QString client_name = QString("mythtv_%1").arg(getpid());
588 auto open_options = (jack_options_t)(JackUseExactName | JackNoStartServer);
589 jack_status_t open_status = JackFailure;
590
591 jack_client_t *client = jack_client_open(client_name.toLatin1().constData(),
592 open_options, &open_status);
593
594 return client;
595}
596
598{
599 const char **matching_ports = nullptr;
600 unsigned long port_flags=JackPortIsInput;
601 const char *port_name = nullptr;
602
603 // Have we been given a target port to connect to
604 if (!m_mainDevice.isEmpty())
605 {
606 port_name = m_mainDevice.toLatin1().constData();
607 }
608 else
609 {
610 port_flags |= JackPortIsPhysical;
611 }
612
613 // list matching ports
614 matching_ports = jack_get_ports(m_client, port_name, nullptr, port_flags);
615 return matching_ports;
616}
617
618
619bool AudioOutputJACK::JackConnectPorts(const char** matching_ports)
620{
621 int i=0;
622
623 // Connect our output ports
624 for (i = 0; i < m_channels; i++)
625 {
626 if (jack_connect(m_client, jack_port_name(m_ports[i]), matching_ports[i]))
627 {
628 QString message {LOC + tr("Calling jack_connect failed on port: %1\n").arg(i)};
629 dispatchError(message);
630 LOG(VB_GENERAL, LOG_ERR, message);
631 return false;
632 }
633 }
634
635 return true;
636}
637
638void AudioOutputJACK::JackClientClose(jack_client_t **client)
639{
640 if (*client)
641 {
642 int err = jack_client_close(*client);
643 if (err != 0)
644 {
645 QString message {LOC + tr("Error closing Jack output device. Error: %1")
646 .arg(err)};
647 dispatchError(message);
648 LOG(VB_GENERAL, LOG_ERR, message);
649 }
650 *client = nullptr;
651 }
652}
653
654/* vim: set expandtab tabstop=4 shiftwidth=4: */
#define LOC
std::array< int, JACK_CHANNELS_MAX > jack_vol_array
static constexpr int8_t JACK_CHANNELS_MAX
@ FORMAT_FLT
void KillAudio(void)
Kill the output thread and cleanup.
void Reconfigure(const AudioSettings &settings) override
(Re)Configure AudioOutputBase
void InitSettings(const AudioSettings &settings)
virtual void Status(void)
Report status via an AudioOutput::Event.
int GetAudioData(uchar *buffer, int buf_size, bool full_buffer, volatile uint *local_raud=nullptr)
Copy frames from the audiobuffer into the buffer provided.
static int JackXRunCallbackHelper(void *arg)
void CloseDevice(void) override
void JackClientClose(jack_client_t **client)
jack_client_t * m_client
static int JackCallbackHelper(jack_nframes_t nframes, void *arg)
const char ** JackGetPorts(void)
void StopOutputThread(void) override
void SetVolumeChannel(int channel, int volume) override
static int JackGraphOrderCallbackHelper(void *arg)
int JackCallback(jack_nframes_t nframes)
jack_vol_array m_chanVolumes
AudioOutputJACK(const AudioSettings &settings)
unsigned char * m_auBuf
AudioOutputSettings * GetOutputSettings(bool digital) override
~AudioOutputJACK() override
jack_client_t * m_staleClient
static jack_client_t * JackClientOpen(void)
void DeinterleaveAudio(const float *aubuf, float **bufs, int nframes, const jack_vol_array &channel_volumes)
void WriteAudio(unsigned char *aubuf, int size) override
bool OpenDevice(void) override
bool JackConnectPorts(const char **)
int GetVolumeChannel(int channel) const override
int GetBufferedOnSoundcard(void) const override
Return the size in bytes of frames currently in the audio buffer adjusted with the audio playback lat...
bool StartOutputThread(void) override
jack_port_array m_ports
void dispatchError(const QString &e)
bool m_init
If set to false, AudioOutput instance will not try to initially open the audio device.
Definition: audiosettings.h:85
Event details.
Definition: zmdefines.h:28
QString GetSetting(const QString &key, const QString &defaultval="")
int GetNumSetting(const QString &key, int defaultval=0)
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
bool m_internalVol
Definition: volumebase.h:43
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static QString cleanup(const QString &str)