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

Contents of /linuxsampler/trunk/src/audiodriver/AudioOutputDeviceJack.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 143 - (show annotations) (download)
Wed Jun 23 18:54:08 2004 UTC (19 years, 10 months ago) by capela
File size: 7372 byte(s)
* SET CHANNEL AUDIO_OUTPUT_TYPE <chan> <driver> command is back!
  creates an audio output device instance of the given driver type
  ('Jack' or 'Alsa') with default parameters if none exists,
  otherwise it just picks the first available device and assign
  it to the intended sampler channel.

* The AudioOutputDevice class get's a new pure virtual method,
  Driver(), which is implemented on both of the existing inherited
  classes, AudioOutputDeviceAlsa and AudioOutputDeviceJack, with
  the sole purpose to return the driver type name as a String
  ('Alsa' and 'Jack', respectively).

* The quoting on the filename argument for the LOAD INSTRUMENT
  command has been made optional; you can have both ways, with
  single quotes or none, keeping compability with older LSCP
  specification.

* An additional sanity check is made on LOAD INSTRUMENT, whether
  the sampler channel has an audio output device assigned, thus
  preventing the server from crashing on instrument file load.

* The GET AUDIO_OUTPUT_DEVICE INFO now includes the missing
  'driver' item, as predicted by the draft protocol document.

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 #if HAVE_JACK
27
28 namespace LinuxSampler {
29
30 REGISTER_AUDIO_OUTPUT_DRIVER("Jack",AudioOutputDeviceJack);
31
32 /**
33 * Open and initialize connection to the JACK system.
34 *
35 * @param Parameters - optional parameters
36 * @throws AudioOutputException on error
37 * @see AcquireChannels()
38 */
39 AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,String> Parameters) : AudioOutputDevice(std::map<String,DeviceCreationParameter*>()) {
40 if ((hJackClient = jack_client_new("LinuxSampler")) == 0)
41 throw AudioOutputException("Seems Jack server not running.");
42
43 jack_set_process_callback(hJackClient, __libjack_process_callback, this);
44 jack_on_shutdown(hJackClient, __libjack_shutdown_callback, this);
45 if (jack_activate(hJackClient))
46 throw AudioOutputException("Jack: Cannot activate Jack client.");
47
48 uiMaxSamplesPerCycle = jack_get_buffer_size(hJackClient);
49
50 #if 0
51 // create amount of audio channels and jack output ports we need for autoconnect
52 for (uint p = 0; p < AutoConnectPorts; p++) {
53 // create jack output port
54 std::stringstream portid; portid << "LinuxSampler:" << p;
55 jack_port_t* newport;
56 if (newport = jack_port_register(hJackClient, portid.str().c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) {
57 hJackPorts.push_back(newport);
58 }
59 else throw AudioOutputException("Jack: Cannot register Jack output port.");
60
61 // create LS audio channel
62 std::stringstream chanid; chanid << "Jack:" << p;
63 Channels.push_back(new AudioChannel((float*) jack_port_get_buffer(newport, uiMaxSamplesPerCycle), uiMaxSamplesPerCycle, chanid.str()));
64
65 // autoconnect port
66 if (jack_connect(hJackClient, portid.str().c_str(), AutoConnectPortIDs[p].c_str())) {
67 std::stringstream err; err << "Jack: Cannot auto connect port " << p;
68 throw AudioOutputException(err.str());
69 }
70 }
71 #endif
72 }
73
74 AudioOutputDeviceJack::~AudioOutputDeviceJack() {
75 // destroy all audio channels
76 for (int c = 0; c < Channels.size(); c++) delete Channels[c];
77 // destroy jack client
78 jack_client_close(hJackClient);
79 }
80
81 /**
82 * This method should not be called directly! It will be called by
83 * libjack to demand transmission of further sample points.
84 */
85 int AudioOutputDeviceJack::Process(uint Samples) {
86 if (csIsPlaying.Pop()) {
87 // let all connected engines render 'Samples' sample points
88 return RenderAudio(Samples);
89 }
90 else {
91 // playback stop by zeroing output buffer(s) and not calling connected sampler engines to render audio
92 return RenderSilence(Samples);
93 }
94 }
95
96 void AudioOutputDeviceJack::Play() {
97 csIsPlaying.PushAndUnlock(true);
98 }
99
100 bool AudioOutputDeviceJack::IsPlaying() {
101 csIsPlaying.GetUnsafe();
102 }
103
104 void AudioOutputDeviceJack::Stop() {
105 csIsPlaying.PushAndUnlock(false);
106 }
107
108 void AudioOutputDeviceJack::AcquireChannels(uint uiChannels) {
109 if (uiChannels > this->Channels.size()) {
110 for (int c = this->Channels.size(); c < uiChannels; c++) {
111 // create new jack output port
112 std::stringstream portid; portid << "LinuxSampler:" << c;
113 jack_port_t* newport;
114 if (newport = jack_port_register(hJackClient, portid.str().c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) {
115 hJackPorts.push_back(newport);
116 }
117 else throw AudioOutputException("Jack: Cannot register Jack output port.");
118
119 // create LS audio channel
120 std::stringstream chanid; chanid << "Jack:" << c;
121 Channels.push_back(new AudioChannel((float*) jack_port_get_buffer(newport, uiMaxSamplesPerCycle), uiMaxSamplesPerCycle, chanid.str()));
122 }
123 }
124 }
125
126 uint AudioOutputDeviceJack::MaxSamplesPerCycle() {
127 return jack_get_buffer_size(hJackClient);
128 }
129
130 uint AudioOutputDeviceJack::SampleRate() {
131 return jack_get_sample_rate(hJackClient);
132 }
133
134 String AudioOutputDeviceJack::Driver() {
135 return "Jack";
136 }
137
138 String AudioOutputDeviceJack::Description() {
139 return "JACK Audio Connection Kit";
140 }
141
142 String AudioOutputDeviceJack::Version() {
143 String s = "$Revision: 1.7 $";
144 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
145 }
146
147 std::map<String,DeviceCreationParameter*> AudioOutputDeviceJack::AvailableParameters() {
148 // FIXME: not a good solution to get the commot parameters (ACTIVE,SAMPERATE,CHANNELS which have to be offered by all audio output drivers)
149 std::map<String,DeviceCreationParameter*> available_parameters = AudioOutputDevice::AvailableParameters();
150 return available_parameters; // this driver currently does not have additional, individual device parameters
151 }
152
153
154 // libjack callback functions
155
156 int __libjack_process_callback(jack_nframes_t nframes, void* arg) {
157 AudioOutputDeviceJack* pAudioOutputDeviceJack = (AudioOutputDeviceJack*) arg;
158 return pAudioOutputDeviceJack->Process(nframes);
159 }
160
161 void __libjack_shutdown_callback(void* arg) {
162 AudioOutputDeviceJack* pAudioOutputDeviceJack = (AudioOutputDeviceJack*) arg;
163 pAudioOutputDeviceJack->Stop();
164 fprintf(stderr, "Jack: Jack server shutdown, exiting.\n");
165 }
166
167 } // namespace LinuxSampler
168
169 #endif // HAVE_JACK

  ViewVC Help
Powered by ViewVC