20 #include "JackCompilerDeps.h"    21 #include "driver_interface.h"    22 #include "JackEngineControl.h"    23 #include "JackLockedEngine.h"    24 #include "JackWaitCallbackDriver.h"    25 #include "JackProxyDriver.h"    31     JackProxyDriver::JackProxyDriver(
const char* name, 
const char* alias, JackLockedEngine* engine, JackSynchro* table,
    32                                 const char* upstream, 
const char* promiscuous,
    33                                 char* client_name, 
bool auto_connect, 
bool auto_save)
    34             : JackRestarterDriver(name, alias, engine, table)
    36         jack_log(
"JackProxyDriver::JackProxyDriver upstream %s", upstream);
    38         assert(strlen(upstream) < JACK_CLIENT_NAME_SIZE);
    39         strcpy(fUpstream, upstream);
    41         assert(strlen(client_name) < JACK_CLIENT_NAME_SIZE);
    42         strcpy(fClientName, client_name);
    45             fPromiscuous = strdup(promiscuous);
    48         fAutoConnect = auto_connect;
    49         fAutoSave = auto_save;
    52     JackProxyDriver::~JackProxyDriver()
    55             UnloadJackModule(fHandle);
    59     int JackProxyDriver::LoadClientLib()
    65         fHandle = LoadJackModule(JACK_PROXY_CLIENT_LIB);
    75     int JackProxyDriver::Open(jack_nframes_t buffer_size,
    76                          jack_nframes_t samplerate,
    82                          const char* capture_driver_name,
    83                          const char* playback_driver_name,
    84                          jack_nframes_t capture_latency,
    85                          jack_nframes_t playback_latency)
    87         fDetectPlaybackChannels = (outchannels == -1);
    88         fDetectCaptureChannels = (inchannels == -1);
    90         if (LoadClientLib() != 0) {
    91             jack_error(
"Cannot dynamically load client library !");
    95         return JackWaiterDriver::Open(buffer_size, samplerate,
    97                                     inchannels, outchannels,
    99                                     capture_driver_name, playback_driver_name,
   100                                     capture_latency, playback_latency);
   103     int JackProxyDriver::Close()
   106         return JackWaiterDriver::Close();
   110     int JackProxyDriver::Attach()
   115     int JackProxyDriver::Detach()
   126     bool JackProxyDriver::Initialize()
   128         jack_log(
"JackProxyDriver::Initialize");
   137             jack_info(
"JackProxyDriver restarting...");
   143         jack_info(
"JackProxyDriver started in %s mode.",
   144                     (fEngineControl->fSyncMode) ? 
"sync" : 
"async");
   147             jack_status_t status;
   152                 const char* tmp = getenv(
"JACK_PROMISCUOUS_SERVER");
   157                 if (setenv(
"JACK_PROMISCUOUS_SERVER", fPromiscuous, 1) < 0) {
   164             jack_info(
"JackProxyDriver connecting to %s", fUpstream);
   165             fClient = 
jack_client_open(fClientName, static_cast<jack_options_t>(JackNoStartServer|JackServerName), &status, fUpstream);
   170                     if (setenv(
"JACK_PROMISCUOUS_SERVER", old, 1) < 0) {
   177                     unsetenv(
"JACK_PROMISCUOUS_SERVER");
   187         jack_info(
"JackProxyDriver connected to %s", fUpstream);
   199             jack_error(
"Cannot set buffer size callback.");
   204             jack_error(
"Cannot set sample rate callback.");
   209             jack_error(
"Cannot set port connect callback.");
   214         if (fDetectPlaybackChannels) {
   215             fPlaybackChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
   219         if (fDetectCaptureChannels) {
   220             fCaptureChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
   223         if (AllocPorts() != 0) {
   250     int JackProxyDriver::Stop()
   261     int JackProxyDriver::process_callback(jack_nframes_t nframes, 
void* arg)
   263         assert(static_cast<JackProxyDriver*>(arg));
   264         return static_cast<JackProxyDriver*>(arg)->Process();
   267     int JackProxyDriver::bufsize_callback(jack_nframes_t nframes, 
void* arg)
   269         assert(static_cast<JackProxyDriver*>(arg));
   270         return static_cast<JackProxyDriver*>(arg)->bufsize_callback(nframes);
   272     int JackProxyDriver::bufsize_callback(jack_nframes_t nframes)
   274         if (JackTimedDriver::SetBufferSize(nframes) == 0) {
   277         JackDriver::NotifyBufferSize(nframes);
   281     int JackProxyDriver::srate_callback(jack_nframes_t nframes, 
void* arg)
   283         assert(static_cast<JackProxyDriver*>(arg));
   284         return static_cast<JackProxyDriver*>(arg)->srate_callback(nframes);
   286     int JackProxyDriver::srate_callback(jack_nframes_t nframes)
   288         if (JackTimedDriver::SetSampleRate(nframes) == 0) {
   291         JackDriver::NotifySampleRate(nframes);
   295     void JackProxyDriver::connect_callback(jack_port_id_t a, jack_port_id_t b, 
int connect, 
void* arg)
   297         assert(static_cast<JackProxyDriver*>(arg));
   298         static_cast<JackProxyDriver*>(arg)->connect_callback(a, b, connect);
   300     void JackProxyDriver::connect_callback(jack_port_id_t a, jack_port_id_t b, 
int connect)
   314         for (i = 0; i < fCaptureChannels; i++) {
   315             if (fUpstreamPlaybackPorts[i] == port) {
   316                 fUpstreamPlaybackPortConnected[i] = connect;
   320         for (i = 0; i < fPlaybackChannels; i++) {
   321             if (fUpstreamCapturePorts[i] == port) {
   322                 fUpstreamCapturePortConnected[i] = connect;
   327     void JackProxyDriver::shutdown_callback(
void* arg)
   329         assert(static_cast<JackProxyDriver*>(arg));
   330         static_cast<JackProxyDriver*>(arg)->RestartWait();
   335     int JackProxyDriver::CountIO(
const char* type, 
int flags)
   340             while (ports[count]) { count++; }
   346     int JackProxyDriver::AllocPorts()
   348         jack_log(
"JackProxyDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
   350         char proxy[REAL_JACK_PORT_NAME_SIZE];
   353         fUpstreamPlaybackPorts = 
new jack_port_t* [fCaptureChannels];
   354         fUpstreamPlaybackPortConnected = 
new int [fCaptureChannels];
   355         for (i = 0; i < fCaptureChannels; i++) {
   356             snprintf(proxy, 
sizeof(proxy), 
"%s:to_client_%d", fClientName, i + 1);
   357             fUpstreamPlaybackPorts[i] = 
jack_port_register(fClient, proxy, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
   358             if (fUpstreamPlaybackPorts[i] == NULL) {
   359                 jack_error(
"driver: cannot register upstream port %s", proxy);
   362             fUpstreamPlaybackPortConnected[i] = 0;
   365         fUpstreamCapturePorts = 
new jack_port_t* [fPlaybackChannels];
   366         fUpstreamCapturePortConnected = 
new int [fPlaybackChannels];
   367         for (i = 0; i < fPlaybackChannels; i++) {
   368             snprintf(proxy, 
sizeof(proxy), 
"%s:from_client_%d", fClientName, i + 1);
   369             fUpstreamCapturePorts[i] = 
jack_port_register(fClient, proxy, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
   370             if (fUpstreamCapturePorts[i] == NULL) {
   371                 jack_error(
"driver: cannot register upstream port %s", proxy);
   374             fUpstreamCapturePortConnected[i] = 0;
   378         return JackAudioDriver::Attach();
   381     int JackProxyDriver::FreePorts()
   383         jack_log(
"JackProxyDriver::FreePorts");
   387         for (i = 0; i < fCaptureChannels; i++) {
   388             if (fCapturePortList[i] > 0) {
   389                 fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[i]);
   390                 fCapturePortList[i] = 0;
   392             if (fUpstreamPlaybackPorts && fUpstreamPlaybackPorts[i]) {
   393                 fUpstreamPlaybackPorts[i] = NULL;
   397         for (i = 0; i < fPlaybackChannels; i++) {
   398             if (fPlaybackPortList[i] > 0) {
   399                 fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[i]);
   400                 fPlaybackPortList[i] = 0;
   402             if (fUpstreamCapturePorts && fUpstreamCapturePorts[i]) {
   403                 fUpstreamCapturePorts[i] = NULL;
   407         delete[] fUpstreamPlaybackPorts;
   408         delete[] fUpstreamPlaybackPortConnected;
   409         delete[] fUpstreamCapturePorts;
   410         delete[] fUpstreamCapturePortConnected;
   412         fUpstreamPlaybackPorts = NULL;
   413         fUpstreamPlaybackPortConnected = NULL;
   414         fUpstreamCapturePorts = NULL;
   415         fUpstreamCapturePortConnected = NULL;
   420     void JackProxyDriver::ConnectPorts()
   422         jack_log(
"JackProxyDriver::ConnectPorts");
   423         const char** ports = 
jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
   425             for (
int i = 0; i < fCaptureChannels && ports[i]; i++) {
   431         ports = 
jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
   433             for (
int i = 0; i < fPlaybackChannels && ports[i]; i++) {
   442     int JackProxyDriver::Read()
   445         JackDriver::CycleTakeBeginTime();
   449         size_t buflen = 
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
   451         for (i = 0; i < fCaptureChannels; i++) {
   452             if (fUpstreamPlaybackPortConnected[i]) {
   454                 to = GetInputBuffer(i);
   455                 memcpy(to, from, buflen);
   462     int JackProxyDriver::Write()
   466         size_t buflen = 
sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
   468         for (i = 0; i < fPlaybackChannels; i++) {
   469             if (fUpstreamCapturePortConnected[i]) {
   471                 from = GetOutputBuffer(i);
   472                 memcpy(to, from, buflen);
   492             desc = jack_driver_descriptor_construct(
"proxy", JackDriverMaster, 
"proxy backend", &filler);
   494             strcpy(value.str, DEFAULT_UPSTREAM);
   495             jack_driver_descriptor_add_parameter(desc, &filler, 
"upstream", 
'u', JackDriverParamString, &value, NULL, 
"Name of the upstream jack server", NULL);
   497             strcpy(value.str, 
"");
   498             jack_driver_descriptor_add_parameter(desc, &filler, 
"promiscuous", 
'p', JackDriverParamString, &value, NULL, 
"Promiscuous group", NULL);
   501             jack_driver_descriptor_add_parameter(desc, &filler, 
"input-ports", 
'C', JackDriverParamInt, &value, NULL, 
"Number of audio input ports", 
"Number of audio input ports. If -1, audio physical input from the master");
   502             jack_driver_descriptor_add_parameter(desc, &filler, 
"output-ports", 
'P', JackDriverParamInt, &value, NULL, 
"Number of audio output ports", 
"Number of audio output ports. If -1, audio physical output from the master");
   504             strcpy(value.str, 
"proxy");
   505             jack_driver_descriptor_add_parameter(desc, &filler, 
"client-name", 
'n', JackDriverParamString, &value, NULL, 
"Name of the jack client", NULL);
   508             jack_driver_descriptor_add_parameter(desc, &filler, 
"use-username", 
'U', JackDriverParamBool, &value, NULL, 
"Use current username as client name", NULL);
   511             jack_driver_descriptor_add_parameter(desc, &filler, 
"auto-connect", 
'c', JackDriverParamBool, &value, NULL, 
"Auto connect proxy to upstream system ports", NULL);
   514             jack_driver_descriptor_add_parameter(desc, &filler, 
"auto-save", 
's', JackDriverParamBool, &value, NULL, 
"Save/restore connection state when restarting", NULL);
   521             char upstream[JACK_CLIENT_NAME_SIZE + 1];
   522             char promiscuous[JACK_CLIENT_NAME_SIZE + 1] = {0};
   523             char client_name[JACK_CLIENT_NAME_SIZE + 1];
   524             jack_nframes_t period_size = 1024;  
   525             jack_nframes_t sample_rate = 48000; 
   526             int capture_ports = -1;
   527             int playback_ports = -1;
   530             bool auto_connect = 
false;
   531             bool auto_save = 
false;
   532             bool use_promiscuous = 
false;
   535             const char* default_upstream = getenv(
"JACK_PROXY_UPSTREAM");
   536             strcpy(upstream, (default_upstream) ? default_upstream : DEFAULT_UPSTREAM);
   539             const char* default_promiscuous = getenv(
"JACK_PROXY_PROMISCUOUS");
   540             strcpy(promiscuous, (default_promiscuous) ? default_promiscuous : 
"");
   543             const char* default_client_name = getenv(
"JACK_PROXY_CLIENT_NAME");
   544             strcpy(client_name, (default_client_name) ? default_client_name : DEFAULT_CLIENT_NAME);
   547             const char* username = getenv(
"USERNAME");
   549             const char* username = getenv(
"LOGNAME");
   552             for (node = params; node; node = jack_slist_next(node)) {
   554                 switch (param->character)
   557                         assert(strlen(param->value.str) < JACK_CLIENT_NAME_SIZE);
   558                         strcpy(upstream, param->value.str);
   561                         assert(strlen(param->value.str) < JACK_CLIENT_NAME_SIZE);
   562                         use_promiscuous = 
true;
   563                         strcpy(promiscuous, param->value.str);
   566                         capture_ports = param->value.i;
   569                         playback_ports = param->value.i;
   572                         assert(strlen(param->value.str) < JACK_CLIENT_NAME_SIZE);
   573                         strncpy(client_name, param->value.str, JACK_CLIENT_NAME_SIZE);
   576                         if (username && *username) {
   577                             assert(strlen(username) < JACK_CLIENT_NAME_SIZE);
   578                             strncpy(client_name, username, JACK_CLIENT_NAME_SIZE);
   592                         new Jack::JackProxyDriver(
"system", 
"proxy_pcm", engine, table, upstream, use_promiscuous ? promiscuous : NULL, client_name, auto_connect, auto_save));
   593                 if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports, 
false, 
"capture_", 
"playback_", 0, 0) == 0) {
 Locked Engine, access to methods is serialized using a mutex.
LIB_EXPORT jack_port_t * jack_port_by_id(jack_client_t *client, jack_port_id_t port_id)
Inter process synchronization using POSIX semaphore.
LIB_EXPORT int jack_set_process_callback(jack_client_t *client, JackProcessCallback process_callback, void *arg)
LIB_EXPORT int jack_activate(jack_client_t *client)
SERVER_EXPORT void jack_error(const char *fmt,...)
LIB_EXPORT int jack_connect(jack_client_t *, const char *source_port, const char *destination_port)
LIB_EXPORT jack_port_t * jack_port_register(jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size)
SERVER_EXPORT void jack_info(const char *fmt,...)
LIB_EXPORT void jack_on_shutdown(jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg)
LIB_EXPORT int jack_set_port_connect_callback(jack_client_t *, JackPortConnectCallback connect_callback, void *arg)
LIB_EXPORT jack_client_t * jack_client_open(const char *client_name, jack_options_t options, jack_status_t *status,...)
Wrapper for a restartable non-threaded driver (e.g. JackProxyDriver).
LIB_EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *)
LIB_EXPORT int jack_set_sample_rate_callback(jack_client_t *client, JackSampleRateCallback srate_callback, void *arg)
LIB_EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t)
LIB_EXPORT int jack_port_is_mine(const jack_client_t *, const jack_port_t *port)
LIB_EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *)
LIB_EXPORT int jack_set_buffer_size_callback(jack_client_t *client, JackBufferSizeCallback bufsize_callback, void *arg)
The base interface for drivers clients.
LIB_EXPORT const char * jack_port_name(const jack_port_t *port)
LIB_EXPORT const char ** jack_get_ports(jack_client_t *, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags)
LIB_EXPORT int jack_deactivate(jack_client_t *client)
SERVER_EXPORT void jack_log(const char *fmt,...)
LIB_EXPORT int jack_client_close(jack_client_t *client)