182 lines
9.9 KiB
C++
182 lines
9.9 KiB
C++
/*
|
|
Copyright (C) 2014 Cédric Schieli
|
|
|
|
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 the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
#ifndef __JackProxyDriver__
|
|
#define __JackProxyDriver__
|
|
|
|
#include "JackTimedDriver.h"
|
|
|
|
#define DEFAULT_UPSTREAM "default" /*!< Default upstream Jack server to connect to */
|
|
#define DEFAULT_CLIENT_NAME "proxy" /*!< Default client name to use when connecting to upstream Jack server */
|
|
|
|
#ifdef __APPLE__
|
|
#define JACK_PROXY_CLIENT_LIB "libjack.0.dylib"
|
|
#elif defined(WIN32)
|
|
#ifdef _WIN64
|
|
#define JACK_PROXY_CLIENT_LIB "libjack64.dll"
|
|
#else
|
|
#define JACK_PROXY_CLIENT_LIB "libjack.dll"
|
|
#endif
|
|
#else
|
|
#define JACK_PROXY_CLIENT_LIB "libjack.so.0"
|
|
#endif
|
|
|
|
#define PROXY_DEF_SYMBOL(ret,name,...) ret (*name) (__VA_ARGS__)
|
|
#define PROXY_LOAD_SYMBOL(ret,name,...) name = (ret (*) (__VA_ARGS__)) GetJackProc(fHandle, #name); assert(name)
|
|
|
|
namespace Jack
|
|
{
|
|
/*! \Brief This class describes the Proxy Backend
|
|
|
|
It uses plain Jack API to connect to an upstream server. The latter is
|
|
either running as the same user, or is running in promiscuous mode.
|
|
|
|
The main use case is the multi-user, multi-session, shared workstation:
|
|
|
|
- a classic server with hw driver is launched system-wide at boot time, in
|
|
promiscuous mode, optionally restricted to the audio group
|
|
- in each user session, a jackdbus server is automatically started with
|
|
JackProxyDriver as master driver, automatically connected to the
|
|
system-wide one
|
|
- optionally, each user run PulseAudio with a pulse-jack bridge
|
|
*/
|
|
|
|
class JackProxyDriver : public JackRestarterDriver
|
|
{
|
|
|
|
private:
|
|
|
|
char fUpstream[JACK_CLIENT_NAME_SIZE+1]; /*<! the upstream server name */
|
|
char fClientName[JACK_CLIENT_NAME_SIZE+1]; /*<! client name to use when connecting */
|
|
const char* fPromiscuous; /*<! if not null, group or gid to use for promiscuous mode */
|
|
|
|
//jack data
|
|
jack_client_t* fClient; /*<! client handle */
|
|
jack_port_t** fUpstreamCapturePorts; /*<! ports registered for capture in the upstream server */
|
|
jack_port_t** fUpstreamPlaybackPorts; /*<! ports registered for playback in the upstream server */
|
|
int* fUpstreamCapturePortConnected; /*<! map of capture ports connected upstream, for optimization purpose */
|
|
int* fUpstreamPlaybackPortConnected; /*<! map of playback ports connected upstream, for optimization purpose */
|
|
|
|
bool fAutoSave; /*<! whether the local connections should be saved/restored when upstream connection is restarted */
|
|
bool fAutoConnect; /*<! whether the upstream ports should be automatically connected to upstream physical ports */
|
|
bool fDetectPlaybackChannels; /*<! whether the number of playback ports registered should match the number of upstream physical playback ports */
|
|
bool fDetectCaptureChannels; /*<! whether the number of capture ports registered should match the number of upstream physical capture ports */
|
|
|
|
bool Initialize(); /*<! establish upstream connection and register the client callbacks */
|
|
|
|
int AllocPorts(); /*<! register local and upstream ports */
|
|
int FreePorts(); /*<! unregister local ports */
|
|
void ConnectPorts(); /*<! connect upstream ports to physical ones */
|
|
|
|
int CountIO(const char*, int); /*<! get the number of upstream ports of a specific type */
|
|
|
|
// client callbacks
|
|
static int process_callback(jack_nframes_t, void*);
|
|
static int bufsize_callback(jack_nframes_t, void*);
|
|
static int srate_callback(jack_nframes_t, void*);
|
|
static void connect_callback(jack_port_id_t, jack_port_id_t, int, void*);
|
|
static void shutdown_callback(void*);
|
|
|
|
// indirect member callbacks
|
|
int bufsize_callback(jack_nframes_t);
|
|
int srate_callback(jack_nframes_t);
|
|
void connect_callback(jack_port_id_t, jack_port_id_t, int);
|
|
|
|
JACK_HANDLE fHandle; /*<! handle to the jack client library */
|
|
|
|
// map needed client library symbols as members to override those from the jackserver library
|
|
PROXY_DEF_SYMBOL(jack_client_t*, jack_client_open, const char*, jack_options_t, jack_status_t*, ...);
|
|
PROXY_DEF_SYMBOL(int, jack_set_process_callback, jack_client_t*, JackProcessCallback, void*);
|
|
PROXY_DEF_SYMBOL(int, jack_set_buffer_size_callback, jack_client_t*, JackBufferSizeCallback, void*);
|
|
PROXY_DEF_SYMBOL(int, jack_set_sample_rate_callback, jack_client_t*, JackSampleRateCallback, void*);
|
|
PROXY_DEF_SYMBOL(int, jack_set_port_connect_callback, jack_client_t*, JackPortConnectCallback, void*);
|
|
PROXY_DEF_SYMBOL(void, jack_on_shutdown, jack_client_t*, JackShutdownCallback, void*);
|
|
PROXY_DEF_SYMBOL(jack_nframes_t, jack_get_buffer_size, jack_client_t*);
|
|
PROXY_DEF_SYMBOL(jack_nframes_t, jack_get_sample_rate, jack_client_t*);
|
|
PROXY_DEF_SYMBOL(int, jack_activate, jack_client_t*);
|
|
PROXY_DEF_SYMBOL(int, jack_deactivate, jack_client_t*);
|
|
PROXY_DEF_SYMBOL(jack_port_t*, jack_port_by_id, jack_client_t*, jack_port_id_t);
|
|
PROXY_DEF_SYMBOL(int, jack_port_is_mine, const jack_client_t*, const jack_port_t*);
|
|
PROXY_DEF_SYMBOL(const char**, jack_get_ports, jack_client_t*, const char*, const char*, unsigned long);
|
|
PROXY_DEF_SYMBOL(void, jack_free, void*);
|
|
PROXY_DEF_SYMBOL(jack_port_t*, jack_port_register, jack_client_t*, const char*, const char*, unsigned long, unsigned long);
|
|
PROXY_DEF_SYMBOL(int, jack_port_unregister, jack_client_t*, jack_port_t*);
|
|
PROXY_DEF_SYMBOL(void*, jack_port_get_buffer, jack_port_t*, jack_nframes_t);
|
|
PROXY_DEF_SYMBOL(int, jack_connect, jack_client_t*, const char*, const char*);
|
|
PROXY_DEF_SYMBOL(const char*, jack_port_name, const jack_port_t*);
|
|
PROXY_DEF_SYMBOL(int, jack_client_close, jack_client_t*);
|
|
|
|
/*! load the needed library symbols */
|
|
void LoadSymbols()
|
|
{
|
|
PROXY_LOAD_SYMBOL(jack_client_t*, jack_client_open, const char*, jack_options_t, jack_status_t*, ...);
|
|
PROXY_LOAD_SYMBOL(int, jack_set_process_callback, jack_client_t*, JackProcessCallback, void*);
|
|
PROXY_LOAD_SYMBOL(int, jack_set_buffer_size_callback, jack_client_t*, JackBufferSizeCallback, void*);
|
|
PROXY_LOAD_SYMBOL(int, jack_set_sample_rate_callback, jack_client_t*, JackSampleRateCallback, void*);
|
|
PROXY_LOAD_SYMBOL(int, jack_set_port_connect_callback, jack_client_t*, JackPortConnectCallback, void*);
|
|
PROXY_LOAD_SYMBOL(void, jack_on_shutdown, jack_client_t*, JackShutdownCallback, void*);
|
|
PROXY_LOAD_SYMBOL(jack_nframes_t, jack_get_buffer_size, jack_client_t*);
|
|
PROXY_LOAD_SYMBOL(jack_nframes_t, jack_get_sample_rate, jack_client_t*);
|
|
PROXY_LOAD_SYMBOL(int, jack_activate, jack_client_t*);
|
|
PROXY_LOAD_SYMBOL(int, jack_deactivate, jack_client_t*);
|
|
PROXY_LOAD_SYMBOL(jack_port_t*, jack_port_by_id, jack_client_t*, jack_port_id_t);
|
|
PROXY_LOAD_SYMBOL(int, jack_port_is_mine, const jack_client_t*, const jack_port_t*);
|
|
PROXY_LOAD_SYMBOL(const char**, jack_get_ports, jack_client_t*, const char*, const char*, unsigned long);
|
|
PROXY_LOAD_SYMBOL(void, jack_free, void*);
|
|
PROXY_LOAD_SYMBOL(jack_port_t*, jack_port_register, jack_client_t*, const char*, const char*, unsigned long, unsigned long);
|
|
PROXY_LOAD_SYMBOL(int, jack_port_unregister, jack_client_t*, jack_port_t*);
|
|
PROXY_LOAD_SYMBOL(void*, jack_port_get_buffer, jack_port_t*, jack_nframes_t);
|
|
PROXY_LOAD_SYMBOL(int, jack_connect, jack_client_t*, const char*, const char*);
|
|
PROXY_LOAD_SYMBOL(const char*, jack_port_name, const jack_port_t*);
|
|
PROXY_LOAD_SYMBOL(int, jack_client_close, jack_client_t*);
|
|
}
|
|
int LoadClientLib(); /*!< load the client library */
|
|
|
|
public:
|
|
|
|
JackProxyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
|
|
const char* upstream, const char* promiscuous, char* client_name, bool auto_connect, bool auto_save);
|
|
virtual ~JackProxyDriver();
|
|
|
|
int Open(jack_nframes_t buffer_size,
|
|
jack_nframes_t samplerate,
|
|
bool capturing,
|
|
bool playing,
|
|
int inchannels,
|
|
int outchannels,
|
|
bool monitor,
|
|
const char* capture_driver_name,
|
|
const char* playback_driver_name,
|
|
jack_nframes_t capture_latency,
|
|
jack_nframes_t playback_latency);
|
|
int Close();
|
|
|
|
int Stop();
|
|
|
|
int Attach();
|
|
int Detach();
|
|
|
|
int Read();
|
|
int Write();
|
|
|
|
};
|
|
}
|
|
|
|
#endif
|