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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 221 by schoenebeck, Fri Aug 20 17:25:19 2004 UTC revision 403 by schoenebeck, Tue Feb 22 20:37:59 2005 UTC
# Line 23  Line 23 
23  #include "AudioOutputDeviceJack.h"  #include "AudioOutputDeviceJack.h"
24  #include "AudioOutputDeviceFactory.h"  #include "AudioOutputDeviceFactory.h"
25    
26    #include <errno.h>
27    
28  #if HAVE_JACK  #if HAVE_JACK
29    
30    #ifndef HAVE_JACK_CLIENT_NAME_SIZE
31    #define jack_client_name_size() 33
32    #endif
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
36      REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceJack);      /// number of currently existing JACK audio output devices in LinuxSampler
37        static int existingJackDevices = 0;
38    
39    // *************** AudioChannelJack::ParameterName ***************
40    // *
41    
42        AudioOutputDeviceJack::AudioChannelJack::ParameterName::ParameterName(AudioChannelJack* pChannel) : AudioChannel::ParameterName(ToString(pChannel->ChannelNr)) {
43            this->pChannel = pChannel;
44        }
45    
46        void AudioOutputDeviceJack::AudioChannelJack::ParameterName::OnSetValue(String s) {
47            if (jack_port_set_name(pChannel->hJackPort, s.c_str())) throw AudioOutputException("Failed to rename JACK port");
48        }
49    
50    
51    
52    // *************** AudioChannelJack::ParameterJackBindings ***************
53    // *
54    
55        AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::ParameterJackBindings(AudioChannelJack* pChannel) : DeviceRuntimeParameterStrings(std::vector<String>()) {
56            this->pChannel = pChannel;
57        }
58    
59        String AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Description() {
60            return "Bindings to other JACK clients";
61        }
62    
63        bool AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::Fix() {
64            return false;
65        }
66    
67        std::vector<String> AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::PossibilitiesAsString() {
68            const char** pPortNames = jack_get_ports(pChannel->pDevice->hJackClient, NULL, NULL, JackPortIsInput);
69            if (!pPortNames) return std::vector<String>();
70            std::vector<String> result;
71            for (int i = 0; pPortNames[i]; i++) result.push_back(pPortNames[i]);
72            //free(pPortNames); FIXME: pPortNames should be freed here
73            return result;
74        }
75    
76        void AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::OnSetValue(std::vector<String> vS) {
77            // TODO: we should remove all existing bindings before we connect new ones here
78            String src_name = ((DeviceCreationParameterString*)pChannel->pDevice->Parameters["NAME"])->ValueAsString() + ":" +
79                              ((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::ParameterName ***************
118    // *
119    
120        AudioOutputDeviceJack::ParameterName::ParameterName() : DeviceCreationParameterString() {
121            InitWithDefault(); // use default name
122        }
123    
124        AudioOutputDeviceJack::ParameterName::ParameterName(String s) throw (LinuxSamplerException) : DeviceCreationParameterString(s) {
125        }
126    
127        String AudioOutputDeviceJack::ParameterName::Description() {
128            return "Arbitrary JACK client name";
129        }
130    
131        bool AudioOutputDeviceJack::ParameterName::Fix() {
132            return true;
133        }
134    
135        bool AudioOutputDeviceJack::ParameterName::Mandatory() {
136            return false;
137        }
138    
139        std::map<String,DeviceCreationParameter*> AudioOutputDeviceJack::ParameterName::DependsAsParameters() {
140            return std::map<String,DeviceCreationParameter*>(); // no dependencies
141        }
142    
143        std::vector<String> AudioOutputDeviceJack::ParameterName::PossibilitiesAsString(std::map<String,String> Parameters) {
144            return std::vector<String>();
145        }
146    
147        optional<String> AudioOutputDeviceJack::ParameterName::DefaultAsString(std::map<String,String> Parameters) {
148            return (existingJackDevices) ? "LinuxSampler" + ToString(existingJackDevices) : "LinuxSampler";
149        }
150    
151        void AudioOutputDeviceJack::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {
152            // not possible, as parameter is fix
153        }
154    
155        String AudioOutputDeviceJack::ParameterName::Name() {
156            return "NAME";
157        }
158    
159      /* Common parameters for now they'll have to be registered here. */  
160      REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterActive);  
161      REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterSampleRate);  // *************** AudioOutputDeviceJack ***************
162      REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterChannels);  // *
163    
164      /**      /**
165       * Open and initialize connection to the JACK system.       * Open and initialize connection to the JACK system.
# Line 41  namespace LinuxSampler { Line 168  namespace LinuxSampler {
168       * @throws AudioOutputException  on error       * @throws AudioOutputException  on error
169       * @see AcquireChannels()       * @see AcquireChannels()
170       */       */
171      AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(std::map<String,DeviceCreationParameter*>()) {      AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) {
172          if ((hJackClient = jack_client_new("LinuxSampler")) == 0)          if (((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString().size() >= jack_client_name_size())
173                throw LinuxSamplerException("JACK client name too long");
174    
175            if ((hJackClient = jack_client_new(((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString().c_str())) == 0)
176              throw AudioOutputException("Seems Jack server not running.");              throw AudioOutputException("Seems Jack server not running.");
177    
178            existingJackDevices++;
179    
180          jack_set_process_callback(hJackClient, __libjack_process_callback, this);          jack_set_process_callback(hJackClient, __libjack_process_callback, this);
181          jack_on_shutdown(hJackClient, __libjack_shutdown_callback, this);          jack_on_shutdown(hJackClient, __libjack_shutdown_callback, this);
182          if (jack_activate(hJackClient))          if (jack_activate(hJackClient))
# Line 52  namespace LinuxSampler { Line 184  namespace LinuxSampler {
184    
185          uiMaxSamplesPerCycle = jack_get_buffer_size(hJackClient);          uiMaxSamplesPerCycle = jack_get_buffer_size(hJackClient);
186    
187  #if 0          // create audio channels
188          // create amount of audio channels and jack output ports we need for autoconnect          AcquireChannels(((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt());
189          for (uint p = 0; p < AutoConnectPorts; p++) {  
190              // create jack output port          // finally activate device if desired
191              std::stringstream portid; portid << "LinuxSampler:" << p;          if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) Play();
             jack_port_t* newport;  
             if (newport = jack_port_register(hJackClient, portid.str().c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) {  
                 hJackPorts.push_back(newport);  
             }  
             else throw AudioOutputException("Jack: Cannot register Jack output port.");  
   
             // create LS audio channel  
             std::stringstream chanid; chanid << "Jack:" << p;  
             Channels.push_back(new AudioChannel((float*) jack_port_get_buffer(newport, uiMaxSamplesPerCycle), uiMaxSamplesPerCycle, chanid.str()));  
   
             // autoconnect port  
             if (jack_connect(hJackClient, portid.str().c_str(), AutoConnectPortIDs[p].c_str())) {  
                 std::stringstream err; err << "Jack: Cannot auto connect port " << p;  
                 throw AudioOutputException(err.str());  
             }  
         }  
 #endif  
192      }      }
193    
194      AudioOutputDeviceJack::~AudioOutputDeviceJack() {      AudioOutputDeviceJack::~AudioOutputDeviceJack() {
         // destroy all audio channels  
         for (int c = 0; c < Channels.size(); c++) delete Channels[c];  
195          // destroy jack client          // destroy jack client
196          jack_client_close(hJackClient);          jack_client_close(hJackClient);
197            existingJackDevices--;
198      }      }
199    
200      /**      /**
# Line 110  namespace LinuxSampler { Line 224  namespace LinuxSampler {
224          csIsPlaying.PushAndUnlock(false);          csIsPlaying.PushAndUnlock(false);
225      }      }
226    
227      void AudioOutputDeviceJack::AcquireChannels(uint uiChannels) {      AudioChannel* AudioOutputDeviceJack::CreateChannel(uint ChannelNr) {
228          if (uiChannels > this->Channels.size()) {          return new AudioChannelJack(ChannelNr, this);
             for (int c = this->Channels.size(); c < uiChannels; c++) {  
                 // create new jack output port  
                 std::stringstream portid; portid << "LinuxSampler:" << c;  
                 jack_port_t* newport;  
                 if (newport = jack_port_register(hJackClient, portid.str().c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) {  
                     hJackPorts.push_back(newport);  
                 }  
                 else throw AudioOutputException("Jack: Cannot register Jack output port.");  
   
                 // create LS audio channel  
                 std::stringstream chanid; chanid << "Jack:" << c;  
                 Channels.push_back(new AudioChannel((float*) jack_port_get_buffer(newport, uiMaxSamplesPerCycle), uiMaxSamplesPerCycle, chanid.str()));  
             }  
         }  
229      }      }
230    
231      uint AudioOutputDeviceJack::MaxSamplesPerCycle() {      uint AudioOutputDeviceJack::MaxSamplesPerCycle() {
# Line 149  namespace LinuxSampler { Line 249  namespace LinuxSampler {
249      }      }
250    
251      String AudioOutputDeviceJack::Version() {      String AudioOutputDeviceJack::Version() {
252         String s = "$Revision: 1.10 $";         String s = "$Revision: 1.17 $";
253         return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword         return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
254      }      }
255    

Legend:
Removed from v.221  
changed lines
  Added in v.403

  ViewVC Help
Powered by ViewVC