LCOV - code coverage report
Current view: top level - src/audio/backend - jack_backend.cpp (source / functions) Coverage Total Hit
Test: merged.info Lines: 97.8 % 91 89
Test Date: 2026-06-07 15:51:50 Functions: 100.0 % 16 16

            Line data    Source code
       1              : #include "audio/backend/jack_backend.h"
       2              : 
       3              : #include <iostream>
       4              : #include <string>
       5              : 
       6              : #include "audio/engine/i_audio_engine.h"
       7              : 
       8              : namespace Amplitron {
       9              : 
      10              : #ifdef WITH_JACK
      11            2 : static int jack_process(jack_nframes_t nframes, void *arg) {
      12            2 :     auto *backend = static_cast<JackBackend *>(arg);
      13            2 :     if (!backend || !backend->get_engine()) return 0;
      14              : 
      15            1 :     auto *in_port = backend->get_in_port();
      16            1 :     auto *out_port = backend->get_out_port();
      17            1 :     if (!in_port || !out_port) return 0;
      18              : 
      19            1 :     float *in = static_cast<float *>(jack_port_get_buffer(in_port, nframes));
      20            1 :     float *out = static_cast<float *>(jack_port_get_buffer(out_port, nframes));
      21            1 :     if (in && out) {
      22            1 :         backend->get_engine()->process_audio(in, out, static_cast<int>(nframes));
      23              :     }
      24              : 
      25            1 :     return 0;
      26              : }
      27              : #endif
      28              : 
      29            5 : JackBackend::JackBackend() = default;
      30           10 : JackBackend::~JackBackend() { shutdown(); }
      31              : 
      32            6 : bool JackBackend::initialize(IAudioEngine *engine) {
      33            6 :     if (initialized_) return true;
      34            5 :     engine_ = engine;
      35              : 
      36              : #ifdef WITH_JACK
      37            5 :     jack_status_t status = static_cast<jack_status_t>(0);
      38            5 :     client_ = jack_client_open("Amplitron", JackNoStartServer, &status);
      39            5 :     if (!client_) {
      40            2 :         std::string status_details = "";
      41            2 :         if (status & JackFailure) status_details += "JackFailure ";
      42            2 :         if (status & JackInvalidOption) status_details += "JackInvalidOption ";
      43            2 :         if (status & JackNameNotUnique) status_details += "JackNameNotUnique ";
      44            2 :         if (status & JackServerStarted) status_details += "JackServerStarted ";
      45            2 :         if (status & JackServerFailed) status_details += "JackServerFailed ";
      46            2 :         if (status & JackServerError) status_details += "JackServerError ";
      47            2 :         if (status & JackNoSuchClient) status_details += "JackNoSuchClient ";
      48            2 :         if (status & JackLoadFailure) status_details += "JackLoadFailure ";
      49            2 :         if (status & JackInitFailure) status_details += "JackInitFailure ";
      50            2 :         if (status & JackShmFailure) status_details += "JackShmFailure ";
      51            2 :         if (status & JackVersionError) status_details += "JackVersionError ";
      52            2 :         if (status & JackBackendError) status_details += "JackBackendError ";
      53            2 :         if (status & JackClientZombie) status_details += "JackClientZombie ";
      54              : 
      55            2 :         std::cerr << "[Amplitron] JACK: could not open JACK server (is jackd running?). Status: 0x"
      56            2 :                   << std::hex << static_cast<int>(status) << std::dec;
      57            2 :         if (!status_details.empty()) {
      58            0 :             std::cerr << " (" << status_details << ")";
      59              :         }
      60            2 :         std::cerr << std::endl;
      61            2 :     }
      62              : #endif
      63              : 
      64            5 :     initialized_ = true;
      65            5 :     return true;
      66              : }
      67              : 
      68           11 : void JackBackend::shutdown() {
      69           11 :     stop();
      70              : #ifdef WITH_JACK
      71           11 :     if (client_) {
      72            3 :         jack_client_close(client_);
      73            3 :         client_ = nullptr;
      74            3 :         in_port_ = nullptr;
      75            3 :         out_port_ = nullptr;
      76            3 :         ports_registered_ = false;
      77              :     }
      78              : #endif
      79           11 :     initialized_ = false;
      80           11 : }
      81              : 
      82            6 : bool JackBackend::start() {
      83            6 :     if (!initialized_ || running_) return false;
      84              : 
      85              : #ifdef WITH_JACK
      86            6 :     if (!client_) return false;
      87              : 
      88            4 :     if (!ports_registered_) {
      89            3 :         in_port_ = jack_port_register(client_, "in_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
      90            3 :         out_port_ =
      91            3 :             jack_port_register(client_, "out_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
      92            3 :         if (!in_port_ || !out_port_) {
      93            1 :             std::cerr << "[Amplitron] JACK: failed to register in/out ports." << std::endl;
      94            1 :             return false;
      95              :         }
      96            2 :         jack_set_process_callback(client_, jack_process, this);
      97            2 :         ports_registered_ = true;
      98              :     }
      99              : 
     100            3 :     if (jack_activate(client_)) {
     101            1 :         std::cerr << "[Amplitron] JACK: failed to activate JACK client." << std::endl;
     102            1 :         return false;
     103              :     }
     104              : 
     105            2 :     running_ = true;
     106            2 :     return true;
     107              : #else
     108              :     return false;
     109              : #endif
     110              : }
     111              : 
     112           19 : void JackBackend::stop() {
     113              : #ifdef WITH_JACK
     114           19 :     if (client_ && running_) {
     115            2 :         jack_deactivate(client_);
     116              :     }
     117              : #endif
     118           19 :     running_ = false;
     119           19 : }
     120              : 
     121            1 : std::vector<AudioDeviceInfo> JackBackend::get_input_devices() const {
     122            4 :     return {{0, "JACK in_1", 1, 0, static_cast<double>(get_sample_rate()), false}};
     123            3 : }
     124              : 
     125            1 : std::vector<AudioDeviceInfo> JackBackend::get_output_devices() const {
     126            4 :     return {{0, "JACK out_1", 0, 1, static_cast<double>(get_sample_rate()), false}};
     127            3 : }
     128              : 
     129            2 : bool JackBackend::set_input_device(int device_index) { return device_index == 0; }
     130              : 
     131            2 : bool JackBackend::set_output_device(int device_index) { return device_index == 0; }
     132              : 
     133            3 : std::string JackBackend::get_input_device_name() const { return "JACK in_1"; }
     134              : 
     135            3 : std::string JackBackend::get_output_device_name() const { return "JACK out_1"; }
     136              : 
     137            4 : int JackBackend::get_sample_rate() const {
     138              : #ifdef WITH_JACK
     139            4 :     if (client_) {
     140            2 :         return static_cast<int>(jack_get_sample_rate(client_));
     141              :     }
     142              : #endif
     143            2 :     return engine_ ? engine_->get_sample_rate() : 48000;
     144              : }
     145              : 
     146            2 : int JackBackend::get_buffer_size() const {
     147              : #ifdef WITH_JACK
     148            2 :     if (client_) {
     149            2 :         return static_cast<int>(jack_get_buffer_size(client_));
     150              :     }
     151              : #endif
     152            0 :     return engine_ ? engine_->get_buffer_size() : 512;
     153              : }
     154              : 
     155              : }  // namespace Amplitron
        

Generated by: LCOV version 2.0-1