/[svn]/linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceJack.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceJack.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 268 - (show annotations) (download)
Thu Oct 7 22:20:20 2004 UTC (19 years, 6 months ago) by capela
File size: 9043 byte(s)
* gcc-c++ 3.4.1 compability fixes.

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "AudioOutputDeviceJack.h"
24 #include "AudioOutputDeviceFactory.h"
25
26 #include <errno.h>
27
28 #if HAVE_JACK
29
30 namespace LinuxSampler {
31
32 REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceJack);
33
34 /* Common parameters for now they'll have to be registered here. */
35 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterActive);
36 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterChannels);
37
38
39
40 // *************** ParameterName ***************
41 // *
42
43 AudioOutputDeviceJack::AudioChannelJack::ParameterName::ParameterName(AudioChannelJack* pChannel) : AudioChannel::ParameterName(ToString(pChannel->ChannelNr)) {
44 this->pChannel = pChannel;
45 }
46
47 void AudioOutputDeviceJack::AudioChannelJack::ParameterName::OnSetValue(String s) {
48 if (jack_port_set_name(pChannel->hJackPort, s.c_str())) throw AudioOutputException("Failed to rename JACK port");
49 }
50
51
52
53 // *************** ParameterJackBindings ***************
54 // *
55
56 AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::ParameterJackBindings(AudioChannelJack* pChannel) : DeviceRuntimeParameterStrings(std::vector<String>()) {
57 this->pChannel = pChannel;
58 }
59
60 String AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Description() {
61 return "Bindings to other JACK clients";
62 }
63
64 bool AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Fix() {
65 return false;
66 }
67
68 std::vector<String> AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::PossibilitiesAsString() {
69 const char** pPortNames = jack_get_ports(pChannel->pDevice->hJackClient, NULL, NULL, JackPortIsInput);
70 if (!pPortNames) return std::vector<String>();
71 std::vector<String> result;
72 for (int i = 0; pPortNames[i]; i++) result.push_back(pPortNames[i]);
73 //free(pPortNames); FIXME: pPortNames should be freed here
74 return result;
75 }
76
77 void AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::OnSetValue(std::vector<String> vS) {
78 // TODO: we should remove all existing bindings before we connect new ones here
79 String src_name = "LinuxSampler:" + ((DeviceRuntimeParameterString*)pChannel->Parameters["NAME"])->ValueAsString();
80 for (int i = 0; i < vS.size(); i++) {
81 String dst_name = vS[i];
82 int res = jack_connect(pChannel->pDevice->hJackClient, src_name.c_str(), dst_name.c_str());
83 if (res == EEXIST) throw AudioOutputException("Jack: Connection to port '" + dst_name + "' already established");
84 else if (res) throw AudioOutputException("Jack: Cannot connect port '" + src_name + "' to port '" + dst_name + "'");
85 }
86 }
87
88 String AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Name() {
89 return "JACK_BINDINGS";
90 }
91
92
93
94 // *************** AudioChannelJack ***************
95 // *
96
97 AudioOutputDeviceJack::AudioChannelJack::AudioChannelJack(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException) : AudioChannel(ChannelNr, CreateJackPort(ChannelNr, pDevice), pDevice->uiMaxSamplesPerCycle) {
98 this->pDevice = pDevice;
99 this->ChannelNr = ChannelNr;
100 Parameters["NAME"] = new ParameterName(this);
101 Parameters["JACK_BINDINGS"] = new ParameterJackBindings(this);
102 }
103
104 AudioOutputDeviceJack::AudioChannelJack::~AudioChannelJack() {
105 //TODO: delete JACK port
106 }
107
108 float* AudioOutputDeviceJack::AudioChannelJack::CreateJackPort(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException) {
109 String port_id = ToString(ChannelNr);
110 hJackPort = jack_port_register(pDevice->hJackClient, port_id.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
111 if (!hJackPort) throw AudioOutputException("Jack: Cannot register Jack output port.");
112 return (float*) jack_port_get_buffer(hJackPort, pDevice->uiMaxSamplesPerCycle);
113 }
114
115
116
117 // *************** AudioOutputDeviceJack ***************
118 // *
119
120 /**
121 * Open and initialize connection to the JACK system.
122 *
123 * @param Parameters - optional parameters
124 * @throws AudioOutputException on error
125 * @see AcquireChannels()
126 */
127 AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) {
128 if ((hJackClient = jack_client_new("LinuxSampler")) == 0)
129 throw AudioOutputException("Seems Jack server not running.");
130
131 jack_set_process_callback(hJackClient, __libjack_process_callback, this);
132 jack_on_shutdown(hJackClient, __libjack_shutdown_callback, this);
133 if (jack_activate(hJackClient))
134 throw AudioOutputException("Jack: Cannot activate Jack client.");
135
136 uiMaxSamplesPerCycle = jack_get_buffer_size(hJackClient);
137
138 // create audio channels
139 AcquireChannels(((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt());
140
141 // finally activate device if desired
142 if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) Play();
143 }
144
145 AudioOutputDeviceJack::~AudioOutputDeviceJack() {
146 // destroy jack client
147 jack_client_close(hJackClient);
148 }
149
150 /**
151 * This method should not be called directly! It will be called by
152 * libjack to demand transmission of further sample points.
153 */
154 int AudioOutputDeviceJack::Process(uint Samples) {
155 if (csIsPlaying.Pop()) {
156 // let all connected engines render 'Samples' sample points
157 return RenderAudio(Samples);
158 }
159 else {
160 // playback stop by zeroing output buffer(s) and not calling connected sampler engines to render audio
161 return RenderSilence(Samples);
162 }
163 }
164
165 void AudioOutputDeviceJack::Play() {
166 csIsPlaying.PushAndUnlock(true);
167 }
168
169 bool AudioOutputDeviceJack::IsPlaying() {
170 csIsPlaying.GetUnsafe();
171 }
172
173 void AudioOutputDeviceJack::Stop() {
174 csIsPlaying.PushAndUnlock(false);
175 }
176
177 AudioChannel* AudioOutputDeviceJack::CreateChannel(uint ChannelNr) {
178 return new AudioChannelJack(ChannelNr, this);
179 }
180
181 uint AudioOutputDeviceJack::MaxSamplesPerCycle() {
182 return jack_get_buffer_size(hJackClient);
183 }
184
185 uint AudioOutputDeviceJack::SampleRate() {
186 return jack_get_sample_rate(hJackClient);
187 }
188
189 String AudioOutputDeviceJack::Name() {
190 return "JACK";
191 }
192
193 String AudioOutputDeviceJack::Driver() {
194 return Name();
195 }
196
197 String AudioOutputDeviceJack::Description() {
198 return "JACK Audio Connection Kit";
199 }
200
201 String AudioOutputDeviceJack::Version() {
202 String s = "$Revision: 1.13 $";
203 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
204 }
205
206 // libjack callback functions
207
208 int __libjack_process_callback(jack_nframes_t nframes, void* arg) {
209 AudioOutputDeviceJack* pAudioOutputDeviceJack = (AudioOutputDeviceJack*) arg;
210 return pAudioOutputDeviceJack->Process(nframes);
211 }
212
213 void __libjack_shutdown_callback(void* arg) {
214 AudioOutputDeviceJack* pAudioOutputDeviceJack = (AudioOutputDeviceJack*) arg;
215 pAudioOutputDeviceJack->Stop();
216 fprintf(stderr, "Jack: Jack server shutdown, exiting.\n");
217 }
218
219 } // namespace LinuxSampler
220
221 #endif // HAVE_JACK

  ViewVC Help
Powered by ViewVC