/[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 1651 by persson, Sun Jan 27 15:07:11 2008 UTC revision 2412 by schoenebeck, Mon Feb 4 21:52:56 2013 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 - 2008 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2013 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 80  namespace LinuxSampler { Line 80  namespace LinuxSampler {
80          // disconnect all current bindings first          // disconnect all current bindings first
81          for (int i = 0; i < Bindings.size(); i++) {          for (int i = 0; i < Bindings.size(); i++) {
82              String dst_name = Bindings[i];              String dst_name = Bindings[i];
83              int res = jack_disconnect(pChannel->pDevice->hJackClient, src_name.c_str(), dst_name.c_str());              /*int res =*/ jack_disconnect(pChannel->pDevice->hJackClient, src_name.c_str(), dst_name.c_str());
84          }          }
85          // connect new bindings          // connect new bindings
86          for (int i = 0; i < vS.size(); i++) {          for (int i = 0; i < vS.size(); i++) {
# Line 120  namespace LinuxSampler { Line 120  namespace LinuxSampler {
120          if (!hJackPort) throw AudioOutputException("Jack: Cannot register Jack output port.");          if (!hJackPort) throw AudioOutputException("Jack: Cannot register Jack output port.");
121          return (float*) jack_port_get_buffer(hJackPort, pDevice->uiMaxSamplesPerCycle);          return (float*) jack_port_get_buffer(hJackPort, pDevice->uiMaxSamplesPerCycle);
122      }      }
123        
124        void AudioOutputDeviceJack::AudioChannelJack::UpdateJackBuffer(uint size) {
125            SetBuffer(
126               (float*)jack_port_get_buffer(hJackPort, size)
127            );
128        }
129    
130    
131    
# Line 178  namespace LinuxSampler { Line 184  namespace LinuxSampler {
184       * @see AcquireChannels()       * @see AcquireChannels()
185       */       */
186      AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) {      AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) {
187          JackClient* pJackClient = JackClient::CreateAudio(((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString());          pJackClient = JackClient::CreateAudio(((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString());
188          existingJackDevices++;          existingJackDevices++;
189          pJackClient->SetAudioOutputDevice(this);          pJackClient->SetAudioOutputDevice(this);
190          hJackClient = pJackClient->hJackClient;          hJackClient = pJackClient->hJackClient;
# Line 202  namespace LinuxSampler { Line 208  namespace LinuxSampler {
208       * libjack to demand transmission of further sample points.       * libjack to demand transmission of further sample points.
209       */       */
210      int AudioOutputDeviceJack::Process(uint Samples) {      int AudioOutputDeviceJack::Process(uint Samples) {
211            int res;
212            
213            // in recent versions of JACK2 and JACk1, we are forced to
214            // re-retrieve the audio buffer pointers in each process period
215            UpdateJackBuffers(Samples);
216            
217          if (csIsPlaying.Pop()) {          if (csIsPlaying.Pop()) {
218              // let all connected engines render 'Samples' sample points              // let all connected engines render 'Samples' sample points
219              return RenderAudio(Samples);              res = RenderAudio(Samples);
220          }          }
221          else {          else {
222              // playback stop by zeroing output buffer(s) and not calling connected sampler engines to render audio              // playback stop by zeroing output buffer(s) and not calling connected sampler engines to render audio
223              return RenderSilence(Samples);              res = RenderSilence(Samples);
224          }          }
225            csIsPlaying.RttDone();
226            return res;
227        }
228        
229        void AudioOutputDeviceJack::UpdateJackBuffers(uint size) {
230            for (int i = 0; i < Channels.size(); ++i)
231                static_cast<AudioChannelJack*>(Channels[i])->UpdateJackBuffer(size);
232        }
233        
234        float AudioOutputDeviceJack::latency() {
235            if (!hJackClient) return -1;
236            const float size = jack_get_buffer_size(hJackClient);
237            const float rate = jack_get_sample_rate(hJackClient);
238            return size / rate;
239        }
240        
241        jack_client_t* AudioOutputDeviceJack::jackClientHandle() {
242            return hJackClient;
243      }      }
244    
245      void AudioOutputDeviceJack::Play() {      void AudioOutputDeviceJack::Play() {
# Line 235  namespace LinuxSampler { Line 265  namespace LinuxSampler {
265      uint AudioOutputDeviceJack::SampleRate() {      uint AudioOutputDeviceJack::SampleRate() {
266          return jack_get_sample_rate(hJackClient);          return jack_get_sample_rate(hJackClient);
267      }      }
268        
269        void AudioOutputDeviceJack::addListener(JackListener* listener) {
270            pJackClient->addListener(listener);
271        }
272    
273      String AudioOutputDeviceJack::Name() {      String AudioOutputDeviceJack::Name() {
274          return "JACK";          return "JACK";
# Line 249  namespace LinuxSampler { Line 283  namespace LinuxSampler {
283      }      }
284    
285      String AudioOutputDeviceJack::Version() {      String AudioOutputDeviceJack::Version() {
286         String s = "$Revision: 1.22 $";         String s = "$Revision: 1.25 $";
287         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
288      }      }
289    
# Line 264  namespace LinuxSampler { Line 298  namespace LinuxSampler {
298          return static_cast<JackClient*>(arg)->Process(nframes);          return static_cast<JackClient*>(arg)->Process(nframes);
299      }      }
300    
301      void linuxsampler_libjack_shutdown_callback(void* arg) {      void JackClient::libjackShutdownCallback(void* arg) {
302          static_cast<JackClient*>(arg)->Stop();          JackClient* jackClient = static_cast<JackClient*>(arg);
303            jackClient->Stop();
304          fprintf(stderr, "Jack: Jack server shutdown, exiting.\n");          fprintf(stderr, "Jack: Jack server shutdown, exiting.\n");
305            for (int i = 0; i < jackClient->jackListeners.size(); ++i) {
306                JackListener* listener = jackClient->jackListeners[i];
307                listener->onJackShutdown();
308            }
309        }
310        
311        int JackClient::libjackSampleRateCallback(jack_nframes_t nframes, void *arg) {
312            JackClient* client = static_cast<JackClient*>(arg);
313            const config_t& config = client->ConfigReader.Lock();
314            if (config.AudioDevice)
315                config.AudioDevice->ReconnectAll();
316            client->ConfigReader.Unlock();
317            return 0;
318        }
319        
320        int JackClient::libjackBufferSizeCallback(jack_nframes_t nframes, void *arg) {
321            dmsg(1,("libjackBufferSizeCallback(%d)\n",nframes));
322            JackClient* client = static_cast<JackClient*>(arg);
323            const config_t& config = client->ConfigReader.Lock();
324            if (config.AudioDevice) {
325                config.AudioDevice->UpdateJackBuffers(nframes);
326                config.AudioDevice->ReconnectAll();
327            }
328            client->ConfigReader.Unlock();
329            return 0;
330        }
331        
332        void JackClient::addListener(JackListener* listener) {
333            jackListeners.push_back(listener);
334      }      }
335    
336      std::map<String, JackClient*> JackClient::Clients;      std::map<String, JackClient*> JackClient::Clients;
# Line 291  namespace LinuxSampler { Line 355  namespace LinuxSampler {
355          {          {
356              config_t& config = Config.GetConfigForUpdate();              config_t& config = Config.GetConfigForUpdate();
357              config.AudioDevice = 0;              config.AudioDevice = 0;
358    #if HAVE_JACK_MIDI
359              config.MidiDevice = 0;              config.MidiDevice = 0;
360    #endif
361          }          }
362          {          {
363              config_t& config = Config.SwitchConfig();              config_t& config = Config.SwitchConfig();
364              config.AudioDevice = 0;              config.AudioDevice = 0;
365    #if HAVE_JACK_MIDI
366              config.MidiDevice = 0;              config.MidiDevice = 0;
367    #endif
368          }          }
369          audio = midi = false;          audio = midi = false;
370          if (Name.size() >= jack_client_name_size())          if (Name.size() >= jack_client_name_size())
371              throw Exception("JACK client name too long");              throw Exception("JACK client name too long");
372          if ((hJackClient = jack_client_new(Name.c_str())) == 0)  #if HAVE_JACK_CLIENT_OPEN
373            hJackClient = jack_client_open(Name.c_str(), JackNullOption, NULL);
374    #else
375            hJackClient = jack_client_new(Name.c_str());
376    #endif
377            if (!hJackClient)
378              throw Exception("Seems Jack server is not running.");              throw Exception("Seems Jack server is not running.");
379          jack_set_process_callback(hJackClient, linuxsampler_libjack_process_callback, this);          jack_set_process_callback(hJackClient, linuxsampler_libjack_process_callback, this);
380          jack_on_shutdown(hJackClient, linuxsampler_libjack_shutdown_callback, this);          jack_on_shutdown(hJackClient, libjackShutdownCallback, this);
381            jack_set_buffer_size_callback(hJackClient, libjackBufferSizeCallback, this);
382            jack_set_sample_rate_callback(hJackClient, libjackSampleRateCallback, this);
383            
384          if (jack_activate(hJackClient))          if (jack_activate(hJackClient))
385              throw Exception("Jack: Cannot activate Jack client.");              throw Exception("Jack: Cannot activate Jack client.");
386      }      }
# Line 318  namespace LinuxSampler { Line 394  namespace LinuxSampler {
394          Config.SwitchConfig().AudioDevice = device;          Config.SwitchConfig().AudioDevice = device;
395      }      }
396    
397    #if HAVE_JACK_MIDI
398      void JackClient::SetMidiInputDevice(MidiInputDeviceJack* device) {      void JackClient::SetMidiInputDevice(MidiInputDeviceJack* device) {
399          Config.GetConfigForUpdate().MidiDevice = device;          Config.GetConfigForUpdate().MidiDevice = device;
400          Config.SwitchConfig().MidiDevice = device;          Config.SwitchConfig().MidiDevice = device;
401      }      }
402    #endif
403    
404      JackClient* JackClient::CreateAudio(String Name) { // static      JackClient* JackClient::CreateAudio(String Name) { // static
405          JackClient* client;          JackClient* client;
# Line 363  namespace LinuxSampler { Line 441  namespace LinuxSampler {
441    
442      void JackClient::ReleaseMidi(String Name) { // static      void JackClient::ReleaseMidi(String Name) { // static
443          JackClient* client = Clients[Name];          JackClient* client = Clients[Name];
444    #if HAVE_JACK_MIDI
445          client->SetMidiInputDevice(0);          client->SetMidiInputDevice(0);
446    #endif
447          client->midi = false;          client->midi = false;
448          if (!client->audio) {          if (!client->audio) {
449              Clients.erase(Name);              Clients.erase(Name);

Legend:
Removed from v.1651  
changed lines
  Added in v.2412

  ViewVC Help
Powered by ViewVC