--- linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceJack.h 2004/07/13 22:04:16 200 +++ linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceJack.h 2013/10/19 07:52:33 2478 @@ -3,6 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * + * Copyright (C) 2005 - 2013 Christian Schoenebeck * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -23,7 +24,7 @@ #ifndef __LS_AUDIOOUTPUTDEVICEJACK_H__ #define __LS_AUDIOOUTPUTDEVICEJACK_H__ -#include "../../common/global.h" +#include "../../common/global_private.h" #if HAVE_JACK @@ -34,7 +35,14 @@ #include "AudioOutputDevice.h" #include "../../common/ConditionServer.h" +#if HAVE_JACK_MIDI +#include "../midi/MidiInputDeviceJack.h" +#endif + namespace LinuxSampler { + + class JackClient; + class JackListener; /** JACK audio output driver * @@ -43,49 +51,167 @@ class AudioOutputDeviceJack : public AudioOutputDevice { public: AudioOutputDeviceJack(std::map Parameters); - ~AudioOutputDeviceJack(); + virtual ~AudioOutputDeviceJack(); - // Audio channel parameter to connect to other Jack clients - class ParameterJackBindings : public DeviceRuntimeParameterStrings { + /** + * Audio channel implementation for the JACK audio driver. + */ + class AudioChannelJack : public AudioChannel { public: - ParameterJackBindings(AudioChannel* pChannel, std::vector InitialBindings) : DeviceRuntimeParameterStrings(InitialBindings) { this->pChannel = pChannel; } - virtual String Description() { return "Bindings to other JACK clients"; } - virtual bool Fix() { return false; } - virtual std::vector PossibilitiesAsString() { return std::vector(); /* TODO: to be implemented */ } - virtual void OnSetValue(std::vector vS) { /* TODO: code to connect to other jack clients */ } + /** Audio Channel Parameter 'NAME' + * + * Used to assign an arbitrary name to an audio channel. + */ + class ParameterName : public AudioChannel::ParameterName { + public: + ParameterName(AudioChannelJack* pChannel); + virtual void OnSetValue(String s) OVERRIDE; + protected: + AudioChannelJack* pChannel; + }; + + /** Audio Channel Parameter 'JACK_BINDINGS' + * + * Used to connect to other JACK clients. + */ + class ParameterJackBindings : public DeviceRuntimeParameterStrings { + public: + ParameterJackBindings(AudioChannelJack* pChannel); + virtual String Description() OVERRIDE; + virtual bool Fix() OVERRIDE; + virtual std::vector PossibilitiesAsString() OVERRIDE; + virtual void OnSetValue(std::vector vS) OVERRIDE; + static String Name(); + protected: + AudioChannelJack* pChannel; + std::vector Bindings; + }; protected: - AudioChannel* pChannel; - }; + AudioChannelJack(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException); + ~AudioChannelJack(); + void UpdateJackBuffer(uint size); + friend class AudioOutputDeviceJack; + private: + AudioOutputDeviceJack* pDevice; + jack_port_t* hJackPort; + uint ChannelNr; - // derived abstract methods from class 'AudioOutputDevice' - virtual void Play(); - virtual bool IsPlaying(); - virtual void Stop(); - virtual void AcquireChannels(uint uiChannels); - virtual uint MaxSamplesPerCycle(); - virtual uint SampleRate(); + float* CreateJackPort(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException); + }; - static String Name(); + /** Audio Device Parameter 'NAME' + * + * Used to assign an arbitrary name to the JACK client of this + * audio device. + */ + class ParameterName : public DeviceCreationParameterString { + public: + ParameterName(); + ParameterName(String s) throw (Exception); + virtual String Description() OVERRIDE; + virtual bool Fix() OVERRIDE; + virtual bool Mandatory() OVERRIDE; + virtual std::map DependsAsParameters() OVERRIDE; + virtual std::vector PossibilitiesAsString(std::map Parameters) OVERRIDE; + virtual optional DefaultAsString(std::map Parameters) OVERRIDE; + virtual void OnSetValue(String s) throw (Exception) OVERRIDE; + static String Name(); + }; - virtual String Driver(); + // derived abstract methods from class 'AudioOutputDevice' + virtual void Play() OVERRIDE; + virtual bool IsPlaying() OVERRIDE; + virtual void Stop() OVERRIDE; + virtual uint MaxSamplesPerCycle() OVERRIDE; + virtual uint SampleRate() OVERRIDE; + virtual AudioChannel* CreateChannel(uint ChannelNr) OVERRIDE; + virtual String Driver() OVERRIDE; + virtual float latency() OVERRIDE; + + static String Name(); static String Description(); static String Version(); - static std::map AvailableParameters(); int Process(uint Samples); // FIXME: should be private + void UpdateJackBuffers(uint size); + void addListener(JackListener* listener); + jack_client_t* jackClientHandle(); protected: AudioOutputDeviceJack(String* AutoConnectPortIDs = NULL, uint AutoConnectPorts = 0); private: - ConditionServer csIsPlaying; - uint uiMaxSamplesPerCycle; - jack_client_t* hJackClient; - std::vector hJackPorts; + ConditionServer csIsPlaying; + uint uiMaxSamplesPerCycle; + jack_client_t* hJackClient; + JackClient* pJackClient; }; // Callback functions for the libjack API - int __libjack_process_callback(jack_nframes_t nframes, void* arg); - void __libjack_shutdown_callback(void* arg); + int linuxsampler_libjack_process_callback(jack_nframes_t nframes, void* arg); + + /** JACK client + * + * Represents a jack client. This class is shared by + * AudioOutputDeviceJack and MidiInputDeviceJack. The jack server + * calls JackClient::Process, which in turn calls + * AudioOutputDeviceJack::Process and/or + * MidiInputDeviceJack::Process. + */ + class JackClient { + public: + static JackClient* CreateAudio(String Name); + static JackClient* CreateMidi(String Name); + static void ReleaseAudio(String Name); + static void ReleaseMidi(String Name); + int Process(uint Samples); + void Stop(); + void SetAudioOutputDevice(AudioOutputDeviceJack* device); + #if HAVE_JACK_MIDI + void SetMidiInputDevice(MidiInputDeviceJack* device); + #endif + void addListener(JackListener* listener); + + jack_client_t* hJackClient; + + private: + std::vector jackListeners; + static std::map Clients; + struct config_t { + AudioOutputDeviceJack* AudioDevice; + #if HAVE_JACK_MIDI + MidiInputDeviceJack* MidiDevice; + #endif + }; + SynchronizedConfig Config; + SynchronizedConfig::Reader ConfigReader; + bool audio; + bool midi; + + JackClient(String Name); + ~JackClient(); + + // Callback functions for the libjack API +#if HAVE_JACK_ON_INFO_SHUTDOWN + static void libjackShutdownCallback(jack_status_t code, const char* reason, void *arg); +#else + static void libjackShutdownCallback(void *arg); +#endif + static int libjackSampleRateCallback(jack_nframes_t nframes, void *arg); + static int libjackBufferSizeCallback(jack_nframes_t nframes, void *arg); + }; + + /** + * Currently not derived / instantiated by the sampler itself, however this + * class can be subclassed and used i.e. by a GUI build on top of the sampler, + * to react on JACK events. Because registering JACK callback functions through + * the general JACK API is not possible after the JACK client has been activated, + * and the latter is already the case as soon as an AudioOutputDeviceJack object + * has been instantiated. + */ + class JackListener { + public: + virtual void onJackShutdown(jack_status_t code, const char* reason) = 0; + }; } #endif // HAVE_JACK