19 #include "JackNetAdapter.h"    20 #include "JackException.h"    21 #include "JackServerGlobals.h"    22 #include "JackEngineControl.h"    23 #include "JackArgParser.h"    28     JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, 
const JSList* params)
    31         jack_log(
"JackNetAdapter::JackNetAdapter");
    38         char multicast_ip[32];
    40         GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
    41         fSocket.GetName(fParams.fSlaveNetName);
    42         fParams.fMtu = DEFAULT_MTU;
    44         fParams.fTransportSync = 0;
    46         int return_audio = -1;
    47         fParams.fSendMidiChannels = 0;
    48         fParams.fReturnMidiChannels = 0;
    49         fParams.fSampleRate = sample_rate;
    50         fParams.fPeriodSize = buffer_size;
    51         fParams.fSlaveSyncMode = 1;
    52         fParams.fNetworkLatency = NETWORK_DEFAULT_LATENCY;
    53         fParams.fSampleEncoder = JackFloatEncoder;
    54         fClient = jack_client;
    57         const char* default_udp_port = getenv(
"JACK_NETJACK_PORT");
    58         udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
    60         const char* default_multicast_ip = getenv(
"JACK_NETJACK_MULTICAST");
    61         if (default_multicast_ip) {
    62             strcpy(multicast_ip, default_multicast_ip);
    64             strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
    70         for (node = params; node; node = jack_slist_next(node))
    74             switch (param->character) {
    76                     assert(strlen(param->value.str) < 32);
    77                     strcpy(multicast_ip, param->value.str);
    80                     udp_port = param->value.ui;
    83                     fParams.fMtu = param->value.i;
    86                     send_audio = param->value.i;
    89                     return_audio = param->value.i;
    92                     strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE);
    95                     fParams.fTransportSync = param->value.ui;
    99                     if (param->value.i > 0) {
   100                         fParams.fSampleEncoder = JackCeltEncoder;
   101                         fParams.fKBps = param->value.i;
   107                     if (param->value.i > 0) {
   108                         fParams.fSampleEncoder = JackOpusEncoder;
   109                         fParams.fKBps = param->value.i;
   114                     fParams.fNetworkLatency = param->value.i;
   115                     if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
   116                         jack_error(
"Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
   117                         throw std::bad_alloc();
   121                     fQuality = param->value.ui;
   124                     fRingbufferCurSize = param->value.ui;
   130         strcpy(fMulticastIP, multicast_ip);
   133         fSocket.SetPort(udp_port);
   134         fSocket.SetAddress(fMulticastIP, udp_port);
   137         fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
   140         fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
   143         SetInputs(fParams.fSendAudioChannels);
   144         SetOutputs(fParams.fReturnAudioChannels);
   147         fSoftCaptureBuffer = NULL;
   148         fSoftPlaybackBuffer = NULL;
   151     JackNetAdapter::~JackNetAdapter()
   153         jack_log(
"JackNetAdapter::~JackNetAdapter");
   155         if (fSoftCaptureBuffer) {
   156             for (
int port_index = 0; port_index < fCaptureChannels; port_index++) {
   157                 delete[] fSoftCaptureBuffer[port_index];
   159             delete[] fSoftCaptureBuffer;
   161         if (fSoftPlaybackBuffer) {
   162             for (
int port_index = 0; port_index < fPlaybackChannels; port_index++) {
   163                 delete[] fSoftPlaybackBuffer[port_index];
   165             delete[] fSoftPlaybackBuffer;
   170     int JackNetAdapter::Open()
   172         jack_info(
"NetAdapter started in %s mode %s Master's transport sync.",
   173                     (fParams.fSlaveSyncMode) ? 
"sync" : 
"async", (fParams.fTransportSync) ? 
"with" : 
"without");
   175         if (fThread.StartSync() < 0) {
   183     int JackNetAdapter::Close()
   189         fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
   192         if (fThread.Kill() < 0) {
   201     int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
   203         JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
   215         if (!JackNetSlaveInterface::Init()) {
   216             jack_error(
"JackNetSlaveInterface::Init() error...");
   227         if (fCaptureChannels > 0) {
   228             fSoftCaptureBuffer = 
new sample_t*[fCaptureChannels];
   229             for (
int port_index = 0; port_index < fCaptureChannels; port_index++) {
   230                 fSoftCaptureBuffer[port_index] = 
new sample_t[fParams.fPeriodSize];
   231                 fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
   235         if (fPlaybackChannels > 0) {
   236             fSoftPlaybackBuffer = 
new sample_t*[fPlaybackChannels];
   237             for (
int port_index = 0; port_index < fPlaybackChannels; port_index++) {
   238                 fSoftPlaybackBuffer[port_index] = 
new sample_t[fParams.fPeriodSize];
   239                 fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
   244         SetAdaptedBufferSize(fParams.fPeriodSize);
   245         SetAdaptedSampleRate(fParams.fSampleRate);
   248         fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
   250         if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
   253             set_threaded_log_function();
   257         SessionParamsDisplay(&fParams);
   261     bool JackNetAdapter::Execute()
   265             while (fThread.GetStatus() == JackThread::kRunning) {
   266                 if (Process() == SOCKET_ERROR) {
   276             fThread.DropSelfRealTime();
   277             fThread.SetStatus(JackThread::kIniting);
   279                 fThread.SetStatus(JackThread::kRunning);
   288     void JackNetAdapter::DecodeTransportData()
   293         if (fSendTransportData.fNewState &&(fSendTransportData.fState != 
jack_transport_query(fClient, NULL))) {
   294             switch (fSendTransportData.fState)
   296                 case JackTransportStopped :
   298                     jack_info(
"NetMaster : transport stops");
   301                 case JackTransportStarting :
   304                     jack_info(
"NetMaster : transport starts");
   307                 case JackTransportRolling :
   311                     jack_info(
"NetMaster : transport rolls");
   317     void JackNetAdapter::EncodeTransportData()
   321         bool conditional = 0;
   323         if (refnum != fLastTimebaseMaster) {
   326                 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
   327                 jack_info(
"Sending a timebase master release request.");
   330                 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
   331                 jack_info(
"Sending a %s timebase master request.", (conditional) ? 
"conditional" : 
"non-conditional");
   333             fLastTimebaseMaster = refnum;
   335             fReturnTransportData.fTimebaseMaster = NO_CHANGE;
   342         fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
   343                                            (fReturnTransportData.fState != fSendTransportData.fState));
   344         if (fReturnTransportData.fNewState) {
   345             jack_info(
"Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
   347         fLastTransportState = fReturnTransportData.fState;
   351     int JackNetAdapter::Read()
   353         switch (SyncRecv()) {
   358             case SYNC_PACKET_ERROR:
   365                 DecodeSyncPacket(unused_frames);
   372     int JackNetAdapter::Write()
   376         if (SyncSend() == SOCKET_ERROR) {
   384     int JackNetAdapter::Process()
   388         if (Read() == SOCKET_ERROR) {
   392         PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
   396         if (Write() == SOCKET_ERROR) {
   411 #include "driver_interface.h"   412 #include "JackAudioAdapter.h"   414     using namespace Jack;
   422         desc = jack_driver_descriptor_construct(
"netadapter", JackDriverNone, 
"netjack net <==> audio backend adapter", &filler);
   424         strcpy(value.str, DEFAULT_MULTICAST_IP);
   425         jack_driver_descriptor_add_parameter(desc, &filler, 
"multicast-ip", 
'a', JackDriverParamString, &value, NULL, 
"Multicast address, or explicit IP of the master", NULL);
   427         value.i = DEFAULT_PORT;
   428         jack_driver_descriptor_add_parameter(desc, &filler, 
"udp-net-port", 
'p', JackDriverParamInt, &value, NULL, 
"UDP port", NULL);
   430         value.i = DEFAULT_MTU;
   431         jack_driver_descriptor_add_parameter(desc, &filler, 
"mtu", 
'M', JackDriverParamInt, &value, NULL, 
"MTU to the master", NULL);
   434         jack_driver_descriptor_add_parameter(desc, &filler, 
"input-ports", 
'C', JackDriverParamInt, &value, NULL, 
"Number of audio input ports", NULL);
   435         jack_driver_descriptor_add_parameter(desc, &filler, 
"output-ports", 
'P', JackDriverParamInt, &value, NULL, 
"Number of audio output ports", NULL);
   439         jack_driver_descriptor_add_parameter(desc, &filler, 
"celt", 
'c', JackDriverParamInt, &value, NULL, 
"Set CELT encoding and number of kBits per channel", NULL);
   444         jack_driver_descriptor_add_parameter(desc, &filler, 
"opus", 
'O', JackDriverParamInt, &value, NULL, 
"Set Opus encoding and number of kBits per channel", NULL);
   447         strcpy(value.str, 
"'hostname'");
   448         jack_driver_descriptor_add_parameter(desc, &filler, 
"client-name", 
'n', JackDriverParamString, &value, NULL, 
"Name of the jack client", NULL);
   451         jack_driver_descriptor_add_parameter(desc, &filler, 
"transport-sync", 
't', JackDriverParamUInt, &value, NULL, 
"Sync transport with master's", NULL);
   454         jack_driver_descriptor_add_parameter(desc, &filler, 
"latency", 
'l', JackDriverParamUInt, &value, NULL, 
"Network latency", NULL);
   457         jack_driver_descriptor_add_parameter(desc, &filler, 
"quality", 
'q', JackDriverParamInt, &value, NULL, 
"Resample algorithm quality (0 - 4)", NULL);
   460         jack_driver_descriptor_add_parameter(desc, &filler, 
"ring-buffer", 
'g', JackDriverParamInt, &value, NULL, 
"Fixed ringbuffer size", 
"Fixed ringbuffer size (if not set => automatic adaptative)");
   463         jack_driver_descriptor_add_parameter(desc, &filler, 
"auto-connect", 
'c', JackDriverParamBool, &value, NULL, 
"Auto connect netadapter to system ports", NULL);
   468     SERVER_EXPORT 
int jack_internal_initialize(jack_client_t* client, 
const JSList* params)
   481             if (adapter->Open() == 0) {
   489             jack_info(
"netadapter allocation error");
   494     SERVER_EXPORT 
int jack_initialize(jack_client_t* jack_client, 
const char* load_init)
   497         bool parse_params = 
true;
   502         if (parser.GetArgc() > 0) {
   503             parse_params = parser.ParseParams(desc, ¶ms);
   507             res = jack_internal_initialize(jack_client, params);
   508             parser.FreeParams(params);
   513     SERVER_EXPORT 
void jack_finish(
void* arg)
 
LIB_EXPORT jack_transport_state_t jack_transport_query(const jack_client_t *client, jack_position_t *pos)
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
Base class for audio adapters.
LIB_EXPORT void jack_transport_start(jack_client_t *client)
Audio adapter : Jack client side.
LIB_EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *)
LIB_EXPORT void jack_transport_stop(jack_client_t *client)
LIB_EXPORT int jack_transport_reposition(jack_client_t *client, const jack_position_t *pos)
LIB_EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *)
Exception possibly thrown by Net slaves.
SERVER_EXPORT void jack_log(const char *fmt,...)