Revision 0:02467299402e JackDevice

View differences:

JackDevice/ContextJack.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

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

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
 This file incorporates work covered by the following copyright and permission notice: 
22

  
23
    Copyright (c) 2014, The Cinder Project
24

  
25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

  
27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

  
30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

  
35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

  
46

  
47
#include "cinder/audio/linux/ContextJack.h"
48
#include "cinder/audio/Exception.h"
49

  
50
#define NUM_CHANNELS 2
51

  
52
namespace cinder { namespace audio { namespace linux {
53

  
54

  
55

  
56
//--------------------------------------static utilities------------------------------------------
57

  
58
inline void zeroJackPort( jack_port_t *port, jack_nframes_t nframes )
59
{   
60
  // FIXME seg fault at shutdown 
61
  // memset(port, 0, sizeof(jack_default_audio_sample_t) * nframes); 
62
}
63

  
64
// copy audio from node buffer to jack port 
65
inline void copyToJackPort(jack_port_t *port, float *source, jack_nframes_t nframes )
66
{
67
    jack_default_audio_sample_t *out;
68
    out = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
69

  
70
    memcpy( out, source, sizeof(jack_default_audio_sample_t) * nframes ) ;
71
}
72

  
73
// copy audio from jack port to  node buffer
74
inline void copyFromJackPort(jack_port_t *port, float *dest, jack_nframes_t nframes )
75
{
76
    jack_default_audio_sample_t *in;
77
    in = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
78

  
79
    memcpy( dest, in, sizeof(jack_default_audio_sample_t) * nframes ) ;
80
}
81

  
82

  
83
// -------------------------------OutputDeviceNodeJack-------------------------------------------
84

  
85
int OutputDeviceNodeJack::jackCallback(jack_nframes_t nframes, void* userData)
86
{
87
    // retrieve user data 
88
    RenderData *renderData = static_cast<RenderData *>( userData );
89

  
90
    OutputDeviceNodeJack *outputDeviceNode = static_cast<OutputDeviceNodeJack *>( renderData->outputNode );
91

  
92
    auto ctx = renderData->outputNode->getContext();
93
    if( ! ctx ) {
94
        // this is from some cinder library code but it should not happen in Collidoscope as the context is set
95
        for( size_t chan = 0; chan < NUM_CHANNELS; chan++)
96
            zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
97

  
98
        return 0;
99
    }
100

  
101
    std::lock_guard<std::mutex> lock( ctx->getMutex() );
102
    
103
    // verify associated context still exists, which may not be true if we blocked in ~Context() and were then deallocated.
104
    ctx = renderData->outputNode->getContext();
105
    if( ! ctx ) {
106

  
107
        for( size_t chan = 0; chan < NUM_CHANNELS; chan++)
108
            zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
109

  
110
        return 0;
111
    }
112

  
113

  
114
    Buffer *internalBuffer = outputDeviceNode->getInternalBuffer();
115
    internalBuffer->zero();
116

  
117
    ctx->preProcess();
118
    // process the whole audio graph using by recursively pulling the input all the way to the top of the graph 
119
    outputDeviceNode->pullInputs( internalBuffer );
120
    
121
    // if clip detection is enabled and buffer clipped, silence it
122
    //if( outputDeviceNode->checkNotClipping() ){
123
        //for( size_t chan = 0; chan < NUM_CHANNELS; chan++)
124
        //    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
125
    //} 
126
    //else {
127
        for( size_t chan = 0; chan < NUM_CHANNELS; chan++)
128
            copyToJackPort( outputDeviceNode->mOutputPorts[chan], internalBuffer->getChannel( chan ), nframes  );
129
    //}
130

  
131
    ctx->postProcess();
132

  
133
    return 0;
134
}
135

  
136
inline void OutputDeviceNodeJack::setInput( InputDeviceNodeRef inputDeviceNode) 
137
{
138
    mInputDeviceNode = std::static_pointer_cast<InputDeviceNodeJack>(inputDeviceNode);
139
}
140

  
141
OutputDeviceNodeJack::OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
142
    OutputDeviceNode( device, format),
143
    mCinderContext( context )
144
{
145
}
146

  
147
void OutputDeviceNodeJack::initialize()
148
{
149

  
150
    const char *client_name = "Collidoscope";
151
    const char *server_name = NULL;
152
    jack_options_t options = JackNullOption;
153
    jack_status_t status;
154

  
155
    // connect to Jack server 
156
    mClient = jack_client_open (client_name, options, &status, server_name);
157
    if( mClient == NULL){
158

  
159
        std::string msg = "jack_client_open() failed. "; 
160
        if(status & JackServerFailed) 
161
            msg += "Unable to connect to Jack server";
162

  
163
        throw cinder::audio::AudioContextExc(msg);
164
    }
165

  
166
    
167
    // prepare user data for callback 
168
    mRenderData.outputNode = this;
169
    mRenderData.inputNode = mInputDeviceNode.get();
170
    CI_ASSERT(mInputDeviceNode != nullptr);
171
    mRenderData.context = static_cast<ContextJack *>( getContext().get() );
172

  
173
    // install callback
174
    jack_set_process_callback (mClient, jackCallback, &mRenderData );
175

  
176
    // jack shutdown ? 
177
    
178

  
179
    // setup output ports 
180
    mOutputPorts[0] = jack_port_register (mClient, "output1",
181
                       JACK_DEFAULT_AUDIO_TYPE,
182
                       JackPortIsOutput, 0);
183
    
184
    mOutputPorts[1] = jack_port_register (mClient, "output2",
185
                       JACK_DEFAULT_AUDIO_TYPE,
186
                       JackPortIsOutput, 0);
187
    
188
     if ((mOutputPorts[0] == NULL) || (mOutputPorts[0] == NULL)) {
189
        throw cinder::audio::AudioContextExc("no more JACK ports available");
190
     }
191

  
192
    // setup input ports. Note that the reference to the input node is used. 
193
    mInputDeviceNode->mInputPorts[0] = jack_port_register (mClient, "input1",
194
                       JACK_DEFAULT_AUDIO_TYPE,
195
                       JackPortIsInput, 0);
196

  
197
    mInputDeviceNode->mInputPorts[1] = jack_port_register (mClient, "input2",
198
                       JACK_DEFAULT_AUDIO_TYPE,
199
                       JackPortIsInput, 0);
200

  
201

  
202
    /* Tell the Jack server that we are ready to roll.  Our callback will start running now. */
203
    if (jack_activate (mClient)) {
204
        throw cinder::audio::AudioContextExc("cannot activate client");
205
    }
206

  
207
    // connect input ports to physical device (microphones)
208
    const char **mikePorts = jack_get_ports (mClient, NULL, NULL,
209
        JackPortIsPhysical|JackPortIsOutput);
210

  
211
    if (mikePorts == NULL) {
212
        throw cinder::audio::AudioContextExc("no physical input ports available");
213
    }
214

  
215
    if (jack_connect (mClient,  mikePorts[0], jack_port_name (mInputDeviceNode->mInputPorts[0]))) {
216
        throw cinder::audio::AudioContextExc("cannot connect input port 0");
217
    }
218

  
219
    if (jack_connect (mClient, mikePorts[1], jack_port_name( mInputDeviceNode->mInputPorts[1]) )) {
220
        throw cinder::audio::AudioContextExc("cannot connect input port 1");
221
    }
222

  
223
    // connect output ports to physical device (audio out )
224
    const char **speakerPorts = jack_get_ports (mClient, NULL, NULL,
225
                JackPortIsPhysical|JackPortIsInput);
226

  
227
    if (speakerPorts == NULL) {
228
        throw cinder::audio::AudioContextExc("no physical output ports available");
229
    }
230

  
231
    if (jack_connect (mClient, jack_port_name (mOutputPorts[0]), speakerPorts[0])) {
232
        throw cinder::audio::AudioContextExc("cannot connect output port 0");
233
    }
234

  
235
    if (jack_connect (mClient, jack_port_name (mOutputPorts[1]), speakerPorts[1])) {
236
        throw cinder::audio::AudioContextExc("cannot connect output port 1");
237
    }
238

  
239
    jack_free( mikePorts );
240
    jack_free( speakerPorts );
241
}
242

  
243

  
244
void OutputDeviceNodeJack::uninitialize()
245
{
246
    jack_client_close( mClient );
247
}
248

  
249
void OutputDeviceNodeJack::enableProcessing()
250
{
251
}
252

  
253
void OutputDeviceNodeJack::disableProcessing()
254
{
255
}
256

  
257

  
258
//----------------------------------------- InputDeviceNodeJack ---------------------------------------------------
259

  
260

  
261
InputDeviceNodeJack::InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
262
    InputDeviceNode( device, format)
263
{
264
}
265

  
266
void InputDeviceNodeJack::initialize() 
267
{
268
}
269

  
270
void InputDeviceNodeJack::uninitialize()
271
{
272
}
273

  
274
void InputDeviceNodeJack::enableProcessing()
275
{
276
}
277

  
278
void InputDeviceNodeJack::disableProcessing()
279
{
280
}
281

  
282
// This is called when the output node pull all the inputs in the jack callback. 
283
// Takes audio interface input from the jack port and copies it in the node buffer
284
void InputDeviceNodeJack::process( Buffer *buffer )
285
{
286
    for( size_t chan = 0; chan < NUM_CHANNELS; chan++){
287
       copyFromJackPort(mInputPorts[chan], buffer->getChannel( chan ), buffer->getNumFrames() ); 
288
    }
289
}
290

  
291

  
292
//-------------------------------------------ContextJack-----------------------------------------------------------
293

  
294
OutputDeviceNodeRef ContextJack::createOutputDeviceNode( const DeviceRef &device, const Node::Format &format )
295
{
296
    
297
    if( mOutputDeviceNode  == nullptr ) {
298
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
299

  
300
        mOutputDeviceNode = makeNode( new OutputDeviceNodeJack( device, Node::Format().channels(NUM_CHANNELS), thisRef ) ) ;
301

  
302
        // the output device node must have a reference to input device node. In OutputDeviceNodeJack::initialize() 
303
        // the input node is passed the jack input ports that it will use to fetch incoming audio from the audio interface
304
        // Whichever node (input or ouput) gets initialized after the other, executes the following block:
305
        if( mInputDeviceNode != nullptr){
306
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
307
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
308
        }
309
    }
310

  
311
    return mOutputDeviceNode;
312
}
313

  
314
InputDeviceNodeRef ContextJack::createInputDeviceNode( const DeviceRef &device, const Node::Format &format  )
315
{
316
    if( mInputDeviceNode  == nullptr ) {
317
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
318

  
319
        mInputDeviceNode = makeNode( new InputDeviceNodeJack( device, Node::Format().channels( NUM_CHANNELS ), thisRef ) ) ;
320

  
321
        // the output device node must have a reference to input device node. In OutputDeviceNodeJack::initialize() 
322
        // the input node is passed the jack input ports that it will use to fetch incoming audio from the audio interface
323
        // Whichever node (input or ouput) gets initialized after the other, executes the following block:
324
        if( mOutputDeviceNode != nullptr){
325
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
326
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
327
        }
328
    }
329

  
330
    return mInputDeviceNode;
331
}
332

  
333

  
334

  
335

  
336

  
337
} } } // namespace cinder::audio::linux
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#include "cinder/audio/linux/ContextJack.h"
25
#include "cinder/audio/Exception.h"
26

  
27
namespace cinder { namespace audio { namespace linux {
28

  
29
inline void zeroJackPort( jack_port_t *port, jack_nframes_t nframes )
30
{   
31
  // memset(port, 0, sizeof(jack_default_audio_sample_t) * nframes); 
32
}
33

  
34
inline void copyToJackPort(jack_port_t *port, float *source, jack_nframes_t nframes )
35
{
36
    // dest, source, n 
37
    jack_default_audio_sample_t *out;
38
    out = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
39

  
40
    memcpy( out, source, sizeof(jack_default_audio_sample_t) * nframes ) ;
41
}
42

  
43
inline void copyFromJackPort(jack_port_t *port, float *dest, jack_nframes_t nframes )
44
{
45
    // dest, source, n 
46
    jack_default_audio_sample_t *in;
47
    in = (jack_default_audio_sample_t *) jack_port_get_buffer( port, nframes );
48

  
49
    memcpy( dest, in, sizeof(jack_default_audio_sample_t) * nframes ) ;
50
}
51

  
52

  
53
int OutputDeviceNodeJack::jackCallback(jack_nframes_t nframes, void* userData)
54
{
55
	RenderData *renderData = static_cast<RenderData *>( userData );
56

  
57
	OutputDeviceNodeJack *outputDeviceNode = static_cast<OutputDeviceNodeJack *>( renderData->outputNode );
58

  
59
	auto ctx = renderData->outputNode->getContext();
60
	if( ! ctx ) {
61
        for( size_t chan = 0; chan < 2; chan++)
62
            // FIXME segfault at shutdown 
63
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
64

  
65
		return 0;
66
	}
67

  
68
	std::lock_guard<std::mutex> lock( ctx->getMutex() );
69
    
70
	// verify associated context still exists, which may not be true if we blocked in ~Context() and were then deallocated.
71
	ctx = renderData->outputNode->getContext();
72
	if( ! ctx ) {
73

  
74
        for( size_t chan = 0; chan < 2; chan++)
75
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
76

  
77
		return 0;
78
	}
79

  
80

  
81
	Buffer *internalBuffer = outputDeviceNode->getInternalBuffer();
82
	internalBuffer->zero();
83

  
84
	ctx->preProcess();
85
	outputDeviceNode->pullInputs( internalBuffer );
86
    
87
	// if clip detection is enabled and buffer clipped, silence it
88
	if( false && outputDeviceNode->checkNotClipping() ){
89
        for( size_t chan = 0; chan < 2; chan++)
90
		    zeroJackPort( outputDeviceNode->mOutputPorts[chan], nframes );
91
	} 
92
    else {
93
        for( size_t chan = 0; chan < 2; chan++)
94
            copyToJackPort( outputDeviceNode->mOutputPorts[chan], internalBuffer->getChannel( chan ), nframes  );
95
    }
96

  
97
	ctx->postProcess();
98

  
99
    return 0;
100
}
101

  
102
inline void OutputDeviceNodeJack::setInput( InputDeviceNodeRef inputDeviceNode) 
103
{
104
    mInputDeviceNode = std::static_pointer_cast<InputDeviceNodeJack>(inputDeviceNode);
105
}
106

  
107
ContextJack::ContextJack()
108
{
109

  
110
}
111

  
112
ContextJack::~ContextJack()
113
{
114

  
115
}
116

  
117

  
118
OutputDeviceNodeRef	ContextJack::createOutputDeviceNode( const DeviceRef &device, const Node::Format &format )
119
{
120
	
121
    if( mOutputDeviceNode  == nullptr ) {
122
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
123

  
124
        mOutputDeviceNode = makeNode( new OutputDeviceNodeJack( device, Node::Format().channels(2), thisRef ) ) ;
125

  
126
        if( mInputDeviceNode != nullptr){
127
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
128
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
129
        }
130
    }
131

  
132
	return mOutputDeviceNode;
133
}
134

  
135
InputDeviceNodeRef ContextJack::createInputDeviceNode( const DeviceRef &device, const Node::Format &format  )
136
{
137
    if( mInputDeviceNode  == nullptr ) {
138
        auto thisRef = std::static_pointer_cast<ContextJack>( shared_from_this() );
139

  
140
        mInputDeviceNode = makeNode( new InputDeviceNodeJack( device, Node::Format().channels(2), thisRef ) ) ;
141

  
142
        if( mOutputDeviceNode != nullptr){
143
            auto castedOutputDeviceNode = std::static_pointer_cast<OutputDeviceNodeJack>( mOutputDeviceNode );
144
            castedOutputDeviceNode->setInput( mInputDeviceNode );   
145
        }
146
    }
147

  
148
	return mInputDeviceNode;
149
}
150

  
151

  
152
// OutputDeviceNodeJack 
153

  
154
OutputDeviceNodeJack::OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
155
    OutputDeviceNode( device, format),
156
    mCinderContext( context )
157
{
158
}
159

  
160
void OutputDeviceNodeJack::initialize()
161
{
162

  
163
    const char *client_name = "Collidoscope";
164
    const char *server_name = NULL;
165
    jack_options_t options = JackNullOption;
166
    jack_status_t status;
167

  
168
    // connect to JAck server 
169
    mClient = jack_client_open (client_name, options, &status, server_name);
170
    if( mClient == NULL){
171

  
172
        std::string msg = "jack_client_open() failed. "; 
173
        if(status & JackServerFailed) 
174
            msg += "Unable to connect to Jack server";
175

  
176
        throw cinder::audio::AudioContextExc(msg);
177
    }
178

  
179
    
180
    mRenderData.outputNode = this;
181
    mRenderData.inputNode = mInputDeviceNode.get();
182
    CI_ASSERT(mInputDeviceNode != nullptr);
183
    mRenderData.context = static_cast<ContextJack *>( getContext().get() );
184

  
185
    // install callback
186
    jack_set_process_callback (mClient, jackCallback, &mRenderData );
187

  
188
    // jack shutdown ? 
189
    
190

  
191
    // setup output ports 
192
    mOutputPorts[0] = jack_port_register (mClient, "output1",
193
                       JACK_DEFAULT_AUDIO_TYPE,
194
                       JackPortIsOutput, 0);
195
    
196
    mOutputPorts[1] = jack_port_register (mClient, "output2",
197
                       JACK_DEFAULT_AUDIO_TYPE,
198
                       JackPortIsOutput, 0);
199
    
200
     if ((mOutputPorts[0] == NULL) || (mOutputPorts[0] == NULL)) {
201
        throw cinder::audio::AudioContextExc("no more JACK ports available");
202
     }
203

  
204
    // setup input ports 
205
    mInputDeviceNode->mInputPorts[0] = jack_port_register (mClient, "input1",
206
                       JACK_DEFAULT_AUDIO_TYPE,
207
                       JackPortIsInput, 0);
208

  
209
    mInputDeviceNode->mInputPorts[1] = jack_port_register (mClient, "input2",
210
                       JACK_DEFAULT_AUDIO_TYPE,
211
                       JackPortIsInput, 0);
212

  
213

  
214
    /* Tell the JACK server that we are ready to roll.  Our callback will start running now. */
215
    if (jack_activate (mClient)) {
216
        throw cinder::audio::AudioContextExc("cannot activate client");
217
    }
218

  
219
    // connect input ports to physical device (microphones)
220
    const char **mikePorts = jack_get_ports (mClient, NULL, NULL,
221
		JackPortIsPhysical|JackPortIsOutput);
222

  
223
	if (mikePorts == NULL) {
224
        throw cinder::audio::AudioContextExc("no physical input ports available");
225
	}
226

  
227
	if (jack_connect (mClient,  mikePorts[0], jack_port_name (mInputDeviceNode->mInputPorts[0]))) {
228
        throw cinder::audio::AudioContextExc("cannot connect input port 0");
229
	}
230

  
231
	if (jack_connect (mClient, mikePorts[1], jack_port_name( mInputDeviceNode->mInputPorts[1]) )) {
232
        throw cinder::audio::AudioContextExc("cannot connect input port 1");
233
	}
234

  
235
    // connect output ports to physical device (audio out )
236
    const char **speakerPorts = jack_get_ports (mClient, NULL, NULL,
237
				JackPortIsPhysical|JackPortIsInput);
238

  
239
	if (speakerPorts == NULL) {
240
        throw cinder::audio::AudioContextExc("no physical output ports available");
241
	}
242

  
243
	if (jack_connect (mClient, jack_port_name (mOutputPorts[0]), speakerPorts[0])) {
244
        throw cinder::audio::AudioContextExc("cannot connect output port 0");
245
	}
246

  
247
	if (jack_connect (mClient, jack_port_name (mOutputPorts[1]), speakerPorts[1])) {
248
        throw cinder::audio::AudioContextExc("cannot connect output port 1");
249
	}
250

  
251
	jack_free( mikePorts );
252
	jack_free( speakerPorts );
253
}
254

  
255

  
256
void OutputDeviceNodeJack::uninitialize()
257
{
258
    jack_client_close( mClient );
259
}
260

  
261
void OutputDeviceNodeJack::enableProcessing()
262
{
263
}
264

  
265
void OutputDeviceNodeJack::disableProcessing()
266
{
267
}
268

  
269

  
270
//-------------------------- InputDeviceNodeJack -------------------------------
271

  
272

  
273
InputDeviceNodeJack::InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context ):
274
    InputDeviceNode( device, format)
275
{
276
}
277

  
278
void InputDeviceNodeJack::initialize() 
279
{
280
}
281

  
282
void InputDeviceNodeJack::uninitialize()
283
{
284
}
285

  
286
void InputDeviceNodeJack::enableProcessing()
287
{
288
}
289

  
290
void InputDeviceNodeJack::disableProcessing()
291
{
292
}
293

  
294
void InputDeviceNodeJack::process( Buffer *buffer )
295
{
296
    for( size_t chan = 0; chan < 2; chan++){
297
       copyFromJackPort(mInputPorts[chan], buffer->getChannel( chan ), buffer->getNumFrames() ); 
298
    }
299
}
300

  
301
} } } // namespace cinder::audio::linux
JackDevice/ContextJack.h
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

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

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
 This file incorporates work covered by the following copyright and permission notice: 
22

  
23
    Copyright (c) 2014, The Cinder Project
24

  
25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

  
27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

  
30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

  
35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

  
46
#pragma once
47

  
48
#include "cinder/audio/Context.h" 
49
#include <jack/jack.h>
50

  
51
namespace cinder { namespace audio { namespace linux {
52

  
53
class ContextJack;
54
class InputDeviceNodeJack;
55

  
56
/**
57
 * OutputNode (as in the cinder::audio::OutputNode) that sends audio to the sound card using the jack audio callback method. 
58
 */ 
59
class OutputDeviceNodeJack : public OutputDeviceNode {
60
  public:
61
    OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
62

  
63
    /** Gives this output node a reference to the JackInputNode. 
64
     *  In initialize() the reference is used to give the input node access to jack input ports 
65
     */
66
    void setInput(InputDeviceNodeRef inputDeviceNode);
67

  
68
  protected:
69
    void initialize()               override;
70
    void uninitialize()             override;
71
    void enableProcessing()         override;
72
    void disableProcessing()        override;
73
    bool supportsProcessInPlace() const override    { return false; }
74

  
75
  private:
76
    // this is called by jack in the audio thread at every tick of the sound card 
77
    static int jackCallback(jack_nframes_t nframes, void* userData);
78

  
79

  
80
    void renderToBufferFromInputs();
81

  
82
    /**
83
     * RenderData is passed as user_data to jack when the jack process callback is installed
84
     */ 
85
    struct RenderData{
86
        RenderData() : inputNode(nullptr), outputNode(nullptr), context(nullptr){}
87
        ~RenderData() { inputNode = nullptr; outputNode = nullptr;  context = nullptr; }
88
        Node* outputNode;
89
        Node* inputNode;
90
        ContextJack* context;
91
    } mRenderData;
92

  
93
    std::weak_ptr<ContextJack>  mCinderContext;
94

  
95
    jack_client_t *mClient;
96

  
97
    std::array< jack_port_t*, 2 > mOutputPorts;
98

  
99
    std::shared_ptr<InputDeviceNodeJack> mInputDeviceNode;
100
};
101

  
102
/**
103
 * InputNode (as in the cinder::audio::OutputNode) that reads audio from the sound card using the jack audio callback method. 
104
 */ 
105
class InputDeviceNodeJack : public InputDeviceNode {
106
  friend OutputDeviceNodeJack;
107

  
108
  public:
109
    InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
110

  
111
  protected:
112
    void initialize()               override;
113
    void uninitialize()             override;
114
    void enableProcessing()         override;
115
    void disableProcessing()        override;
116
    void process( Buffer *buffer )  override;
117

  
118
  private:
119
    std::array< jack_port_t*, 2 > mInputPorts;
120
};
121

  
122
class ContextJack : public Context {
123
  public:
124
    ContextJack() {}
125
    virtual ~ContextJack() {}
126
    
127

  
128
    OutputDeviceNodeRef createOutputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format() ) override;
129
    InputDeviceNodeRef  createInputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format()  ) override;
130

  
131
    OutputDeviceNodeRef mOutputDeviceNode;
132
    InputDeviceNodeRef  mInputDeviceNode;
133

  
134

  
135
  private:
136
};  
137

  
138
} } } // namespace cinder::audio::linux
139

  
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#pragma once
25

  
26
#include "cinder/audio/Context.h" 
27
#include <jack/jack.h>
28

  
29
namespace cinder { namespace audio { namespace linux {
30

  
31
class ContextJack;
32
class InputDeviceNodeJack;
33

  
34
class OutputDeviceNodeJack : public OutputDeviceNode {
35
  public:
36
	OutputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
37

  
38
    void setInput(InputDeviceNodeRef inputDeviceNode);
39

  
40
  protected:
41
	void initialize()				override;
42
	void uninitialize()				override;
43
	void enableProcessing()			override;
44
	void disableProcessing()		override;
45
	bool supportsProcessInPlace() const	override	{ return false; }
46

  
47
  private:
48
    static int jackCallback(jack_nframes_t nframes, void* userData);
49

  
50

  
51
	void renderToBufferFromInputs();
52

  
53
    struct RenderData{
54
        RenderData() : inputNode(nullptr), outputNode(nullptr), context(nullptr){}
55
        ~RenderData() { inputNode = nullptr; outputNode = nullptr;  context = nullptr; }
56
        Node* outputNode;
57
        Node* inputNode;
58
        ContextJack* context;
59
    } mRenderData;
60

  
61
    std::weak_ptr<ContextJack>  mCinderContext;
62

  
63
	jack_client_t *mClient;
64

  
65
    std::array< jack_port_t*, 2 > mOutputPorts;
66

  
67
    std::shared_ptr<InputDeviceNodeJack> mInputDeviceNode;
68
};
69

  
70
class InputDeviceNodeJack : public InputDeviceNode {
71
  friend OutputDeviceNodeJack;
72

  
73
  public:
74
	InputDeviceNodeJack( const DeviceRef &device, const Format &format, const std::shared_ptr<ContextJack> &context );
75

  
76
  protected:
77
	void initialize()				override;
78
	void uninitialize()				override;
79
	void enableProcessing()			override;
80
	void disableProcessing()		override;
81
	void process( Buffer *buffer )	override;
82

  
83
  private:
84
    std::array< jack_port_t*, 2 > mInputPorts;
85
};
86

  
87
class ContextJack : public Context {
88
  public:
89
	ContextJack();
90
	virtual ~ContextJack();
91
    
92

  
93
	OutputDeviceNodeRef	createOutputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format() ) override;
94
	InputDeviceNodeRef	createInputDeviceNode( const DeviceRef &device, const Node::Format &format = Node::Format()  ) override;
95

  
96
    OutputDeviceNodeRef	mOutputDeviceNode;
97
    InputDeviceNodeRef	mInputDeviceNode;
98

  
99

  
100
  private:
101
};	
102

  
103
} } } // namespace cinder::audio::linux
JackDevice/DeviceManagerJack.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

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

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
 This file incorporates work covered by the following copyright and permission notice: 
22

  
23
    Copyright (c) 2014, The Cinder Project
24

  
25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

  
27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

  
30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

  
35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

  
46
#include "cinder/audio/linux/DeviceManagerJack.h"
47
#include "cinder/audio/Exception.h"
48
#include <jack/jack.h>
49

  
50

  
51
namespace cinder { namespace audio { namespace linux {
52

  
53
DeviceManagerJack::DeviceManagerJack() 
54
{
55

  
56
    // hardcoded devices. They are always JackIn and JackOut 
57
    mDevices.push_back( addDevice("JackIn") );
58
    mDevices.push_back( addDevice("JackOut") );
59

  
60
    jack_status_t status;
61
    
62
    // open a jack client, get info and close
63
    jack_client_t *client = jack_client_open ("device info", JackNullOption, &status, NULL);
64
    if( client == NULL){
65

  
66
        std::string msg = "jack_client_open() failed. "; 
67
        if(status & JackServerFailed) 
68
            msg += "Unable to connect to Jack server";
69

  
70
        throw cinder::audio::AudioContextExc(msg);
71
    }
72

  
73
    mSampleRate = jack_get_sample_rate( client );
74
    mBufferSize = jack_get_buffer_size( client );
75

  
76
    jack_client_close( client );
77
}
78

  
79
DeviceManagerJack::~DeviceManagerJack()
80
{
81
    
82
}
83

  
84
const std::vector<DeviceRef>& DeviceManagerJack::getDevices()
85
{
86
   return mDevices;
87
}
88

  
89
DeviceRef DeviceManagerJack::getDefaultOutput()
90
{
91
    return mDevices[1];
92
}
93

  
94
DeviceRef DeviceManagerJack::getDefaultInput()
95
{
96
    return mDevices[0];
97
}
98

  
99
//hardcoded name same as key 
100
std::string DeviceManagerJack::getName( const DeviceRef &device )
101
{
102
    return device->getKey();
103
}
104

  
105
size_t DeviceManagerJack::getNumInputChannels( const DeviceRef &device )
106
{
107
    if( device->getKey() == mDevices[0]->getKey() )
108
        return 2;
109
    else
110
        return 0;
111
}
112

  
113
size_t DeviceManagerJack::getNumOutputChannels( const DeviceRef &device )
114
{
115
    if( device->getKey() == mDevices[1]->getKey() )
116
        return 2;
117
    else
118
        return 0;
119
}
120

  
121
size_t DeviceManagerJack::getSampleRate( const DeviceRef &device )
122
{
123
    return mSampleRate;
124
}
125

  
126
size_t DeviceManagerJack::getFramesPerBlock( const DeviceRef &device )
127
{
128
    return mBufferSize;
129
}
130

  
131

  
132
void DeviceManagerJack::setSampleRate( const DeviceRef &device, size_t sampleRate )
133
{
134
    throw "setSampleRate not supported";
135
}
136

  
137
void DeviceManagerJack::setFramesPerBlock( const DeviceRef &device, size_t framesPerBlock )
138
{
139
    throw "setFramesPerBlock not supported";
140
}
141

  
142

  
143
//! Returns the hardware's actual frames per block, which might not be a power of two.
144
//        size_t getFramesPerBlockHardware( const DeviceRef &device );
145
//
146

  
147
size_t DeviceManagerJack::getFramesPerBlockHardware( const DeviceRef &device )
148
{
149
    return mBufferSize;
150
}
151

  
152

  
153

  
154

  
155

  
156

  
157
} } } // namespace cinder::audio::linux
JackDevice/DeviceManagerJack.h
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

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

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
 This file incorporates work covered by the following copyright and permission notice: 
22

  
23
    Copyright (c) 2014, The Cinder Project
24

  
25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

  
27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

  
30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

  
35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

  
46
#pragma once
47

  
48
#include "cinder/audio/Device.h"
49

  
50
namespace cinder { namespace audio { namespace linux {
51

  
52
/**
53
 * DeviceManager ( as in cinder::audio::DeviceManager ) that handle the hardware device through the jack library.
54
 * Note that this is not suitable for general purpose use. Most of the functionalities are indeed hard coded
55
 * just to suit Collidoscope needs. In particular only two input and two output ports are assumed. 
56
 *
57
 */ 
58
class DeviceManagerJack : public DeviceManager {
59
  public:
60

  
61
    DeviceManagerJack();
62
    virtual ~DeviceManagerJack();
63

  
64
    const std::vector<DeviceRef>& getDevices()      override;
65
    DeviceRef getDefaultOutput()                override;
66
    DeviceRef getDefaultInput()             override;
67

  
68
    std::string getName( const DeviceRef &device )      override;
69
    size_t getNumInputChannels( const DeviceRef &device )   override;
70
    size_t getNumOutputChannels( const DeviceRef &device )  override;
71
    size_t getSampleRate( const DeviceRef &device )     override;
72
    size_t getFramesPerBlock( const DeviceRef &device ) override;
73

  
74
    void setSampleRate( const DeviceRef &device, size_t sampleRate )        override;
75
    void setFramesPerBlock( const DeviceRef &device, size_t framesPerBlock )    override;
76

  
77
    //! Returns the hardware's actual frames per block, which might not be a power of two.
78
    size_t getFramesPerBlockHardware( const DeviceRef &device );
79

  
80
private:
81

  
82
    std::vector<DeviceRef> mDevices;
83
    DeviceRef   mDefaultOutDevice;
84
    DeviceRef   mDefaultInDevice;
85
    size_t mSampleRate;
86
    size_t mBufferSize;
87
};  
88

  
89
} } } // namespace cinder::audio::linux     
1
/*
2
 Copyright (c) 2015, The Cinder Project
3

  
4
 This code is intended to be used with the Cinder C++ library, http://libcinder.org
5

  
6
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
7
 the following conditions are met:
8

  
9
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
10
	the following disclaimer.
11
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
	the following disclaimer in the documentation and/or other materials provided with the distribution.
13

  
14
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
15
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
16
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
17
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
18
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21
 POSSIBILITY OF SUCH DAMAGE.
22
*/
23

  
24
#pragma once
25

  
26
#include "cinder/audio/Device.h"
27

  
28
namespace cinder { namespace audio { namespace linux {
29

  
30
class DeviceManagerJack : public DeviceManager {
31
  public:
32

  
33
	DeviceManagerJack();
34
	virtual ~DeviceManagerJack();
35

  
36
	const std::vector<DeviceRef>& getDevices()		override;
37
	DeviceRef getDefaultOutput()				override;
38
	DeviceRef getDefaultInput()				override;
39

  
40
	std::string getName( const DeviceRef &device ) 		override;
41
	size_t getNumInputChannels( const DeviceRef &device )	override;
42
	size_t getNumOutputChannels( const DeviceRef &device )	override;
43
	size_t getSampleRate( const DeviceRef &device )		override;
44
	size_t getFramesPerBlock( const DeviceRef &device )	override;
45

  
46
	void setSampleRate( const DeviceRef &device, size_t sampleRate )		override;
47
	void setFramesPerBlock( const DeviceRef &device, size_t framesPerBlock )	override;
48

  
49
	//! Returns the hardware's actual frames per block, which might not be a power of two.
50
	size_t getFramesPerBlockHardware( const DeviceRef &device );
51

  
52
private:
53

  
54
	std::vector<DeviceRef> mDevices;
55
	DeviceRef   mDefaultOutDevice;
56
	DeviceRef   mDefaultInDevice;
57
    size_t mSampleRate;
58
    size_t mBufferSize;
59
};	
60

  
61
} } } // namespace cinder::audio::linux 	

Also available in: Unified diff