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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 289 - (hide annotations) (download)
Tue Oct 19 14:41:38 2004 UTC (19 years, 6 months ago) by schoenebeck
File size: 8740 byte(s)
* LinuxSampler was badly broken with last commit, fixed that
* using now James Klicman's proposol to fix the reported linker problem
* Mutex.cpp: try to force UNIX98 compatibility (if not already supported)
* Makefile.cvs: generate (and clean) all necessary autotools files

1 schoenebeck 200 /***************************************************************************
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 capela 268 #include <errno.h>
27    
28 schoenebeck 200 #if HAVE_JACK
29    
30     namespace LinuxSampler {
31    
32 schoenebeck 226 // *************** ParameterName ***************
33     // *
34    
35     AudioOutputDeviceJack::AudioChannelJack::ParameterName::ParameterName(AudioChannelJack* pChannel) : AudioChannel::ParameterName(ToString(pChannel->ChannelNr)) {
36     this->pChannel = pChannel;
37     }
38    
39     void AudioOutputDeviceJack::AudioChannelJack::ParameterName::OnSetValue(String s) {
40 schoenebeck 227 if (jack_port_set_name(pChannel->hJackPort, s.c_str())) throw AudioOutputException("Failed to rename JACK port");
41 schoenebeck 226 }
42    
43    
44    
45     // *************** ParameterJackBindings ***************
46     // *
47    
48     AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::ParameterJackBindings(AudioChannelJack* pChannel) : DeviceRuntimeParameterStrings(std::vector<String>()) {
49     this->pChannel = pChannel;
50     }
51    
52     String AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Description() {
53     return "Bindings to other JACK clients";
54     }
55    
56     bool AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Fix() {
57     return false;
58     }
59    
60     std::vector<String> AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::PossibilitiesAsString() {
61 schoenebeck 227 const char** pPortNames = jack_get_ports(pChannel->pDevice->hJackClient, NULL, NULL, JackPortIsInput);
62 schoenebeck 226 if (!pPortNames) return std::vector<String>();
63     std::vector<String> result;
64     for (int i = 0; pPortNames[i]; i++) result.push_back(pPortNames[i]);
65     //free(pPortNames); FIXME: pPortNames should be freed here
66     return result;
67     }
68    
69     void AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::OnSetValue(std::vector<String> vS) {
70 schoenebeck 227 // TODO: we should remove all existing bindings before we connect new ones here
71     String src_name = "LinuxSampler:" + ((DeviceRuntimeParameterString*)pChannel->Parameters["NAME"])->ValueAsString();
72 schoenebeck 226 for (int i = 0; i < vS.size(); i++) {
73     String dst_name = vS[i];
74 schoenebeck 227 int res = jack_connect(pChannel->pDevice->hJackClient, src_name.c_str(), dst_name.c_str());
75     if (res == EEXIST) throw AudioOutputException("Jack: Connection to port '" + dst_name + "' already established");
76     else if (res) throw AudioOutputException("Jack: Cannot connect port '" + src_name + "' to port '" + dst_name + "'");
77 schoenebeck 226 }
78     }
79    
80     String AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Name() {
81     return "JACK_BINDINGS";
82     }
83    
84    
85    
86     // *************** AudioChannelJack ***************
87     // *
88    
89     AudioOutputDeviceJack::AudioChannelJack::AudioChannelJack(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException) : AudioChannel(ChannelNr, CreateJackPort(ChannelNr, pDevice), pDevice->uiMaxSamplesPerCycle) {
90     this->pDevice = pDevice;
91     this->ChannelNr = ChannelNr;
92     Parameters["NAME"] = new ParameterName(this);
93     Parameters["JACK_BINDINGS"] = new ParameterJackBindings(this);
94     }
95    
96     AudioOutputDeviceJack::AudioChannelJack::~AudioChannelJack() {
97     //TODO: delete JACK port
98     }
99    
100     float* AudioOutputDeviceJack::AudioChannelJack::CreateJackPort(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException) {
101 schoenebeck 227 String port_id = ToString(ChannelNr);
102 schoenebeck 226 hJackPort = jack_port_register(pDevice->hJackClient, port_id.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
103     if (!hJackPort) throw AudioOutputException("Jack: Cannot register Jack output port.");
104     return (float*) jack_port_get_buffer(hJackPort, pDevice->uiMaxSamplesPerCycle);
105     }
106    
107    
108    
109     // *************** AudioOutputDeviceJack ***************
110     // *
111    
112 schoenebeck 200 /**
113     * Open and initialize connection to the JACK system.
114     *
115     * @param Parameters - optional parameters
116     * @throws AudioOutputException on error
117     * @see AcquireChannels()
118     */
119 schoenebeck 226 AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) {
120 schoenebeck 200 if ((hJackClient = jack_client_new("LinuxSampler")) == 0)
121     throw AudioOutputException("Seems Jack server not running.");
122    
123     jack_set_process_callback(hJackClient, __libjack_process_callback, this);
124     jack_on_shutdown(hJackClient, __libjack_shutdown_callback, this);
125     if (jack_activate(hJackClient))
126     throw AudioOutputException("Jack: Cannot activate Jack client.");
127    
128     uiMaxSamplesPerCycle = jack_get_buffer_size(hJackClient);
129    
130 schoenebeck 226 // create audio channels
131     AcquireChannels(((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt());
132 schoenebeck 227
133     // finally activate device if desired
134     if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) Play();
135 schoenebeck 200 }
136    
137     AudioOutputDeviceJack::~AudioOutputDeviceJack() {
138     // destroy jack client
139     jack_client_close(hJackClient);
140     }
141    
142     /**
143     * This method should not be called directly! It will be called by
144     * libjack to demand transmission of further sample points.
145     */
146     int AudioOutputDeviceJack::Process(uint Samples) {
147     if (csIsPlaying.Pop()) {
148     // let all connected engines render 'Samples' sample points
149     return RenderAudio(Samples);
150     }
151     else {
152     // playback stop by zeroing output buffer(s) and not calling connected sampler engines to render audio
153     return RenderSilence(Samples);
154     }
155     }
156    
157     void AudioOutputDeviceJack::Play() {
158     csIsPlaying.PushAndUnlock(true);
159     }
160    
161     bool AudioOutputDeviceJack::IsPlaying() {
162     csIsPlaying.GetUnsafe();
163     }
164    
165     void AudioOutputDeviceJack::Stop() {
166     csIsPlaying.PushAndUnlock(false);
167     }
168    
169 schoenebeck 226 AudioChannel* AudioOutputDeviceJack::CreateChannel(uint ChannelNr) {
170     return new AudioChannelJack(ChannelNr, this);
171 schoenebeck 200 }
172    
173     uint AudioOutputDeviceJack::MaxSamplesPerCycle() {
174     return jack_get_buffer_size(hJackClient);
175     }
176    
177     uint AudioOutputDeviceJack::SampleRate() {
178     return jack_get_sample_rate(hJackClient);
179     }
180    
181     String AudioOutputDeviceJack::Name() {
182 schoenebeck 221 return "JACK";
183 schoenebeck 200 }
184    
185     String AudioOutputDeviceJack::Driver() {
186     return Name();
187     }
188    
189     String AudioOutputDeviceJack::Description() {
190     return "JACK Audio Connection Kit";
191     }
192    
193     String AudioOutputDeviceJack::Version() {
194 schoenebeck 289 String s = "$Revision: 1.14 $";
195 schoenebeck 200 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
196     }
197    
198     // libjack callback functions
199    
200     int __libjack_process_callback(jack_nframes_t nframes, void* arg) {
201     AudioOutputDeviceJack* pAudioOutputDeviceJack = (AudioOutputDeviceJack*) arg;
202     return pAudioOutputDeviceJack->Process(nframes);
203     }
204    
205     void __libjack_shutdown_callback(void* arg) {
206     AudioOutputDeviceJack* pAudioOutputDeviceJack = (AudioOutputDeviceJack*) arg;
207     pAudioOutputDeviceJack->Stop();
208     fprintf(stderr, "Jack: Jack server shutdown, exiting.\n");
209     }
210    
211     } // namespace LinuxSampler
212    
213     #endif // HAVE_JACK

  ViewVC Help
Powered by ViewVC