JackAudioAdapter.cpp 6.36 KB
Newer Older
sletz's avatar
sletz committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
Copyright (C) 2008 Grame

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

sletz's avatar
sletz committed
20
#include "JackAudioAdapter.h"
sletz's avatar
sletz committed
21
#include "JackError.h"
22
#include "JackCompilerDeps.h"
23
#include "JackTools.h"
24
#include "JackTime.h"
25
#include "jslist.h"
sletz's avatar
sletz committed
26
#include <stdio.h>
sletz's avatar
sletz committed
27
#include <stdlib.h>
sletz's avatar
sletz committed
28
#include <assert.h>
sletz's avatar
sletz committed
29
30
31
32
33

using namespace std;

namespace Jack
{
sletz's avatar
sletz committed
34

moret's avatar
moret committed
35
//static methods ***********************************************************
sletz's avatar
sletz committed
36
    int JackAudioAdapter::Process (jack_nframes_t frames, void* arg)
37
    {
sletz's avatar
sletz committed
38
        JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
sletz's avatar
sletz committed
39
40
        jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()];
        jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
sletz's avatar
sletz committed
41
42

        // Always clear output
sletz's avatar
sletz committed
43
        for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
sletz's avatar
sletz committed
44
45
            inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames);
            memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t));
46
        }
sletz's avatar
sletz committed
47

sletz's avatar
sletz committed
48
        for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
sletz's avatar
sletz committed
49
            outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
50
        }
sletz's avatar
sletz committed
51

sletz's avatar
sletz committed
52
        adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
sletz's avatar
sletz committed
53
      	return 0;
sletz's avatar
sletz committed
54
    }
55

56
    int JackAudioAdapter::BufferSize ( jack_nframes_t buffer_size, void* arg )
57
    {
58
        JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg );
59
        adapter->Reset();
60
        adapter->fAudioAdapter->SetHostBufferSize ( buffer_size );
61
        return 0;
sletz's avatar
sletz committed
62
    }
sletz's avatar
sletz committed
63

64
    int JackAudioAdapter::SampleRate ( jack_nframes_t sample_rate, void* arg )
65
    {
66
        JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg );
67
        adapter->Reset();
68
        adapter->fAudioAdapter->SetHostSampleRate ( sample_rate );
69
70
        return 0;
    }
sletz's avatar
sletz committed
71

moret's avatar
moret committed
72
//JackAudioAdapter *********************************************************
sletz's avatar
sletz committed
73

sletz's avatar
sletz committed
74
     JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system)
sletz's avatar
sletz committed
75
76
77
78
79
        :fJackClient(jack_client), fAudioAdapter(audio_io)
    {
        const JSList* node;
        const jack_driver_param_t* param;
        fAutoConnect = false;
sletz's avatar
sletz committed
80

sletz's avatar
sletz committed
81
82
83
84
        for (node = params; node; node = jack_slist_next(node)) {
            param = (const jack_driver_param_t*) node->data;
            switch (param->character) {
                case 'c':
sletz's avatar
sletz committed
85
                    fAutoConnect = true;
sletz's avatar
sletz committed
86
87
88
89
                    break;
            }
        }
    }
sletz's avatar
sletz committed
90

91
92
93
94
    JackAudioAdapter::~JackAudioAdapter()
    {
        // When called, Close has already been used for the client, thus ports are already unregistered.
        delete fAudioAdapter;
sletz's avatar
sletz committed
95
96
    }

97
98
    void JackAudioAdapter::FreePorts()
    {
sletz's avatar
sletz committed
99
        for (int i = 0; i < fAudioAdapter->GetInputs(); i++ )
100
101
            if ( fCapturePortList[i] )
                jack_port_unregister ( fJackClient, fCapturePortList[i] );
sletz's avatar
sletz committed
102
        for (int i = 0; i < fAudioAdapter->GetOutputs(); i++ )
103
            if ( fPlaybackPortList[i] )
104
                jack_port_unregister ( fJackClient, fPlaybackPortList[i] );
sletz's avatar
sletz committed
105

106
107
108
        delete[] fCapturePortList;
        delete[] fPlaybackPortList;
    }
sletz's avatar
sletz committed
109

sletz's avatar
sletz committed
110
111
112
    void JackAudioAdapter::ConnectPorts()
    {
        const char **ports;
sletz's avatar
sletz committed
113

sletz's avatar
sletz committed
114
115
116
117
118
119
120
        ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
        if (ports != NULL) {
            for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) {
                jack_connect(fJackClient,jack_port_name(fCapturePortList[i]),  ports[i]);
            }
            free(ports);
        }
sletz's avatar
sletz committed
121

sletz's avatar
sletz committed
122
123
124
125
126
127
128
129
        ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
        if (ports != NULL) {
            for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) {
                jack_connect(fJackClient, ports[i], jack_port_name(fPlaybackPortList[i]));
            }
            free(ports);
        }
    }
sletz's avatar
sletz committed
130

moret's avatar
moret committed
131
132
133
134
135
    void JackAudioAdapter::Reset()
    {
        fAudioAdapter->Reset();
    }

136
137
138
    int JackAudioAdapter::Open()
    {
        char name[32];
sletz's avatar
sletz committed
139
140
        jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs());
        fAudioAdapter->Create();
sletz's avatar
sletz committed
141

142
        //jack ports
sletz's avatar
sletz committed
143
144
        fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()];
        fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()];
145

sletz's avatar
sletz committed
146
        for (int i = 0; i < fAudioAdapter->GetInputs(); i++)
147
        {
sletz's avatar
sletz committed
148
149
            sprintf(name, "capture_%d", i + 1);
            if ((fCapturePortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
150
151
152
                goto fail;
        }

sletz's avatar
sletz committed
153
        for (int i = 0; i < fAudioAdapter->GetOutputs(); i++)
154
        {
sletz's avatar
sletz committed
155
156
            sprintf(name, "playback_%d", i + 1);
            if ((fPlaybackPortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 )) == NULL)
157
158
159
160
                goto fail;
        }

        //callbacks and activation
161
        if ( jack_set_process_callback ( fJackClient, Process, this ) < 0 )
162
            goto fail;
163
        if ( jack_set_buffer_size_callback ( fJackClient, BufferSize, this ) < 0 )
164
            goto fail;
165
        if ( jack_set_sample_rate_callback ( fJackClient, SampleRate, this ) < 0 )
166
            goto fail;
167
        if ( jack_activate ( fJackClient ) < 0 )
168
            goto fail;
sletz's avatar
sletz committed
169

sletz's avatar
sletz committed
170
171
        if (fAutoConnect)
            ConnectPorts();
172

sletz's avatar
sletz committed
173
        // Ring buffer are now allocated..
174
175
        return fAudioAdapter->Open();

176
    fail:
177
        FreePorts();
sletz's avatar
sletz committed
178
        fAudioAdapter->Destroy();
sletz's avatar
sletz committed
179
        return -1;
180
181
182
183
    }

    int JackAudioAdapter::Close()
    {
sletz's avatar
sletz committed
184
185
186
        fAudioAdapter->Close();
        fAudioAdapter->Destroy();
        return 0;
187
    }
sletz's avatar
sletz committed
188

sletz's avatar
sletz committed
189
} //namespace