Jack2  1.9.10
JackNetManager.cpp
00001 /*
00002 Copyright(C) 2008-2011 Romain Moret at Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #include "JackNetManager.h"
00020 #include "JackArgParser.h"
00021 #include "JackServerGlobals.h"
00022 #include "JackLockedEngine.h"
00023 #include "thread.h"
00024 
00025 using namespace std;
00026 
00027 namespace Jack
00028 {
00029 //JackNetMaster******************************************************************************************************
00030 
00031     JackNetMaster::JackNetMaster(JackNetSocket& socket, session_params_t& params, const char* multicast_ip)
00032             : JackNetMasterInterface(params, socket, multicast_ip)
00033     {
00034         jack_log("JackNetMaster::JackNetMaster");
00035 
00036         //settings
00037         fName = const_cast<char*>(fParams.fName);
00038         fClient = NULL;
00039         fSendTransportData.fState = -1;
00040         fReturnTransportData.fState = -1;
00041         fLastTransportState = -1;
00042         int port_index;
00043 
00044         //jack audio ports
00045         fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
00046         for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) {
00047             fAudioCapturePorts[port_index] = NULL;
00048         }
00049 
00050         fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
00051         for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) {
00052             fAudioPlaybackPorts[port_index] = NULL;
00053         }
00054 
00055         //jack midi ports
00056         fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
00057         for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) {
00058             fMidiCapturePorts[port_index] = NULL;
00059         }
00060 
00061         fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
00062         for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) {
00063             fMidiPlaybackPorts[port_index] = NULL;
00064         }
00065     
00066         //monitor
00067 #ifdef JACK_MONITOR
00068         fPeriodUsecs = (int)(1000000.f * ((float) fParams.fPeriodSize / (float) fParams.fSampleRate));
00069         string plot_name;
00070         plot_name = string(fParams.fName);
00071         plot_name += string("_master");
00072         plot_name += string((fParams.fSlaveSyncMode) ? "_sync" : "_async");
00073         plot_name += string("_latency");
00074         fNetTimeMon = new JackGnuPlotMonitor<float>(128, 4, plot_name);
00075         string net_time_mon_fields[] =
00076         {
00077             string("sync send"),
00078             string("end of send"),
00079             string("sync recv"),
00080             string("end of cycle")
00081         };
00082         string net_time_mon_options[] =
00083         {
00084             string("set xlabel \"audio cycles\""),
00085             string("set ylabel \"% of audio cycle\"")
00086         };
00087         fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 4);
00088 #endif
00089     }
00090 
00091     JackNetMaster::~JackNetMaster()
00092     {
00093         jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID);
00094 
00095         if (fClient) {
00096             jack_deactivate(fClient);
00097             FreePorts();
00098             jack_client_close(fClient);
00099         }
00100         delete[] fAudioCapturePorts;
00101         delete[] fAudioPlaybackPorts;
00102         delete[] fMidiCapturePorts;
00103         delete[] fMidiPlaybackPorts;
00104 #ifdef JACK_MONITOR
00105         fNetTimeMon->Save();
00106         delete fNetTimeMon;
00107 #endif
00108     }
00109 //init--------------------------------------------------------------------------------
00110     bool JackNetMaster::Init(bool auto_connect)
00111     {
00112         //network init
00113         if (!JackNetMasterInterface::Init()) {
00114             jack_error("JackNetMasterInterface::Init() error...");
00115             return false;
00116         }
00117 
00118         //set global parameters
00119         if (!SetParams()) {
00120             jack_error("SetParams error...");
00121             return false;
00122         }
00123 
00124         //jack client and process
00125         jack_status_t status;
00126         if ((fClient = jack_client_open(fName, JackNullOption, &status, NULL)) == NULL) {
00127             jack_error("Can't open a new JACK client");
00128             return false;
00129         }
00130         
00131         if (jack_set_process_callback(fClient, SetProcess, this) < 0) {
00132             goto fail;
00133         }
00134 
00135         if (jack_set_buffer_size_callback(fClient, SetBufferSize, this) < 0) {
00136             goto fail;
00137         }
00138         
00139         if (jack_set_sample_rate_callback(fClient, SetSampleRate, this) < 0) {
00140             goto fail;
00141         }
00142         
00143         if (jack_set_latency_callback(fClient, LatencyCallback, this) < 0) {
00144             goto fail;
00145         }
00146         
00147         /*
00148         if (jack_set_port_connect_callback(fClient, SetConnectCallback, this) < 0) {
00149             goto fail;
00150         }
00151         */
00152      
00153         if (AllocPorts() != 0) {
00154             jack_error("Can't allocate JACK ports");
00155             goto fail;
00156         }
00157 
00158         //process can now run
00159         fRunning = true;
00160 
00161         //finally activate jack client
00162         if (jack_activate(fClient) != 0) {
00163             jack_error("Can't activate JACK client");
00164             goto fail;
00165         }
00166 
00167         if (auto_connect) {
00168             ConnectPorts();
00169         }
00170         jack_info("New NetMaster started");
00171         return true;
00172 
00173     fail:
00174         FreePorts();
00175         jack_client_close(fClient);
00176         fClient = NULL;
00177         return false;
00178     }
00179 
00180 //jack ports--------------------------------------------------------------------------
00181     int JackNetMaster::AllocPorts()
00182     {
00183         int i;
00184         char name[32];
00185         jack_log("JackNetMaster::AllocPorts");
00186 
00187         //audio
00188         for (i = 0; i < fParams.fSendAudioChannels; i++) {
00189             snprintf(name, sizeof(name), "to_slave_%d", i+1);
00190             if ((fAudioCapturePorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) {
00191                 return -1;
00192             }
00193         }
00194 
00195         for (i = 0; i < fParams.fReturnAudioChannels; i++) {
00196             snprintf(name, sizeof(name), "from_slave_%d", i+1);
00197             if ((fAudioPlaybackPorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) {
00198                 return -1;
00199             }
00200         }
00201 
00202         //midi
00203         for (i = 0; i < fParams.fSendMidiChannels; i++) {
00204             snprintf(name, sizeof(name), "midi_to_slave_%d", i+1);
00205             if ((fMidiCapturePorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) {
00206                 return -1;
00207             }
00208         }
00209 
00210         for (i = 0; i < fParams.fReturnMidiChannels; i++) {
00211             snprintf(name, sizeof(name), "midi_from_slave_%d", i+1);
00212             if ((fMidiPlaybackPorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE,  JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) {
00213                 return -1;
00214             }
00215         }
00216         return 0;
00217     }
00218 
00219     void JackNetMaster::ConnectPorts()
00220     {
00221         const char** ports = jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
00222         if (ports != NULL) {
00223             for (int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
00224                 jack_connect(fClient, ports[i], jack_port_name(fAudioCapturePorts[i]));
00225             }
00226             jack_free(ports);
00227         }
00228 
00229         ports = jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
00230         if (ports != NULL) {
00231             for (int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
00232                 jack_connect(fClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]);
00233             }
00234             jack_free(ports);
00235         }
00236     }
00237 
00238     void JackNetMaster::FreePorts()
00239     {
00240         jack_log("JackNetMaster::FreePorts ID = %u", fParams.fID);
00241 
00242         int port_index;
00243         for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) {
00244             if (fAudioCapturePorts[port_index]) {
00245                 jack_port_unregister(fClient, fAudioCapturePorts[port_index]);
00246             }
00247         }
00248         for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) {
00249             if (fAudioPlaybackPorts[port_index]) {
00250                 jack_port_unregister(fClient, fAudioPlaybackPorts[port_index]);
00251             }
00252         }
00253         for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) {
00254             if (fMidiCapturePorts[port_index]) {
00255                 jack_port_unregister(fClient, fMidiCapturePorts[port_index]);
00256             }
00257         }
00258         for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) {
00259             if (fMidiPlaybackPorts[port_index]) {
00260                 jack_port_unregister(fClient, fMidiPlaybackPorts[port_index]);
00261             }
00262         }
00263     }
00264 
00265 //transport---------------------------------------------------------------------------
00266     void JackNetMaster::EncodeTransportData()
00267     {
00268         //is there a new timebase master ?
00269         //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
00270         fSendTransportData.fTimebaseMaster = NO_CHANGE;
00271 
00272         //update state and position
00273         fSendTransportData.fState = static_cast<uint>(jack_transport_query(fClient, &fSendTransportData.fPosition));
00274 
00275         //is it a new state ?
00276         fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState));
00277         if (fSendTransportData.fNewState) {
00278             jack_info("Sending '%s' to '%s' frame = %ld", GetTransportState(fSendTransportData.fState), fParams.fName, fSendTransportData.fPosition.frame);
00279         }
00280         fLastTransportState = fSendTransportData.fState;
00281    }
00282 
00283     void JackNetMaster::DecodeTransportData()
00284     {
00285         //is there timebase master change ?
00286         if (fReturnTransportData.fTimebaseMaster != NO_CHANGE) {
00287 
00288             int timebase = 0;
00289             switch (fReturnTransportData.fTimebaseMaster)
00290             {
00291                 case RELEASE_TIMEBASEMASTER :
00292                     timebase = jack_release_timebase(fClient);
00293                     if (timebase < 0) {
00294                         jack_error("Can't release timebase master");
00295                     } else {
00296                         jack_info("'%s' isn't the timebase master anymore", fParams.fName);
00297                     }
00298                     break;
00299 
00300                 case TIMEBASEMASTER :
00301                     timebase = jack_set_timebase_callback(fClient, 0, SetTimebaseCallback, this);
00302                     if (timebase < 0) {
00303                         jack_error("Can't set a new timebase master");
00304                     } else {
00305                         jack_info("'%s' is the new timebase master", fParams.fName);
00306                     }
00307                     break;
00308 
00309                 case CONDITIONAL_TIMEBASEMASTER :
00310                     timebase = jack_set_timebase_callback(fClient, 1, SetTimebaseCallback, this);
00311                     if (timebase != EBUSY) {
00312                         if (timebase < 0)
00313                             jack_error("Can't set a new timebase master");
00314                         else
00315                             jack_info("'%s' is the new timebase master", fParams.fName);
00316                     }
00317                     break;
00318             }
00319         }
00320 
00321         //is the slave in a new transport state and is this state different from master's ?
00322         if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fClient, NULL))) {
00323 
00324             switch (fReturnTransportData.fState)
00325             {
00326                 case JackTransportStopped :
00327                     jack_transport_stop(fClient);
00328                     jack_info("'%s' stops transport", fParams.fName);
00329                     break;
00330 
00331                 case JackTransportStarting :
00332                     if (jack_transport_reposition(fClient, &fReturnTransportData.fPosition) == EINVAL)
00333                         jack_error("Can't set new position");
00334                     jack_transport_start(fClient);
00335                     jack_info("'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
00336                     break;
00337 
00338                 case JackTransportNetStarting :
00339                     jack_info("'%s' is ready to roll...", fParams.fName);
00340                     break;
00341 
00342                 case JackTransportRolling :
00343                     jack_info("'%s' is rolling", fParams.fName);
00344                     break;
00345             }
00346         }
00347     }
00348 
00349     void JackNetMaster::SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg)
00350     {
00351         static_cast<JackNetMaster*>(arg)->TimebaseCallback(pos);
00352     }
00353 
00354     void JackNetMaster::TimebaseCallback(jack_position_t* pos)
00355     {
00356         pos->bar = fReturnTransportData.fPosition.bar;
00357         pos->beat = fReturnTransportData.fPosition.beat;
00358         pos->tick = fReturnTransportData.fPosition.tick;
00359         pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
00360         pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
00361         pos->beat_type = fReturnTransportData.fPosition.beat_type;
00362         pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
00363         pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
00364     }
00365 
00366 //sync--------------------------------------------------------------------------------
00367 
00368     bool JackNetMaster::IsSlaveReadyToRoll()
00369     {
00370         return (fReturnTransportData.fState == JackTransportNetStarting);
00371     }
00372 
00373     int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg)
00374     {
00375         JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
00376         if (nframes != obj->fParams.fPeriodSize) {
00377             jack_error("Cannot currently handle buffer size change, so JackNetMaster proxy will be removed...");
00378             obj->Exit();
00379         }
00380         return 0;
00381     }
00382     
00383     int JackNetMaster::SetSampleRate(jack_nframes_t nframes, void* arg)
00384     {
00385         JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
00386         if (nframes != obj->fParams.fSampleRate) {
00387             jack_error("Cannot currently handle sample rate change, so JackNetMaster proxy will be removed...");
00388             obj->Exit();
00389         }
00390         return 0;
00391     }
00392     
00393     void JackNetMaster::LatencyCallback(jack_latency_callback_mode_t mode, void* arg)
00394     {
00395         JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
00396         jack_nframes_t port_latency = jack_get_buffer_size(obj->fClient);
00397         jack_latency_range_t range;
00398         
00399         //audio
00400         for (int i = 0; i < obj->fParams.fSendAudioChannels; i++) {
00401             //port latency
00402             range.min = range.max = float(obj->fParams.fNetworkLatency * port_latency) / 2.f;
00403             jack_port_set_latency_range(obj->fAudioCapturePorts[i], JackCaptureLatency, &range);
00404         }
00405         
00406         //audio
00407         for (int i = 0; i < obj->fParams.fReturnAudioChannels; i++) {
00408             //port latency
00409             range.min = range.max = float(obj->fParams.fNetworkLatency * port_latency) / 2.f + ((obj->fParams.fSlaveSyncMode) ? 0 : port_latency);
00410             jack_port_set_latency_range(obj->fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
00411         }
00412         
00413         //midi
00414         for (int i = 0; i < obj->fParams.fSendMidiChannels; i++) {
00415             //port latency
00416             range.min = range.max = float(obj->fParams.fNetworkLatency * port_latency) / 2.f;
00417             jack_port_set_latency_range(obj->fMidiCapturePorts[i], JackCaptureLatency, &range);
00418         }
00419     
00420         //midi
00421         for (int i = 0; i < obj->fParams.fReturnMidiChannels; i++) {
00422             //port latency
00423             range.min = range.max = obj->fParams.fNetworkLatency * port_latency + ((obj->fParams.fSlaveSyncMode) ? 0 : port_latency);
00424             jack_port_set_latency_range(obj->fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
00425         }
00426     }
00427 
00428 //process-----------------------------------------------------------------------------
00429     int JackNetMaster::SetProcess(jack_nframes_t nframes, void* arg)
00430     {
00431         try {
00432             return static_cast<JackNetMaster*>(arg)->Process();
00433         } catch (JackNetException& e) {
00434             return 0;
00435         }
00436     }
00437     
00438     void JackNetMaster::SetConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg)
00439     {
00440         static_cast<JackNetMaster*>(arg)->ConnectCallback(a, b, connect);
00441     }
00442     
00443     void JackNetMaster::ConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect)
00444     {
00445         jack_info("JackNetMaster::ConnectCallback a = %d b = %d connect = %d", a, b, connect);
00446         if (connect) {
00447             jack_connect(fClient, jack_port_name(jack_port_by_id(fClient, a)), "system:playback_1");
00448         }
00449     }
00450 
00451     int JackNetMaster::Process()
00452     {
00453         if (!fRunning) {
00454             return 0;
00455         }
00456 
00457 #ifdef JACK_MONITOR
00458         jack_time_t begin_time = GetMicroSeconds();
00459         fNetTimeMon->New();
00460 #endif
00461 
00462         //buffers
00463         for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
00464             fNetMidiCaptureBuffer->SetBuffer(midi_port_index,
00465                                             static_cast<JackMidiBuffer*>(jack_port_get_buffer(fMidiCapturePorts[midi_port_index],
00466                                             fParams.fPeriodSize)));
00467         }
00468         for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
00469 
00470         #ifdef OPTIMIZED_PROTOCOL
00471             if (fNetAudioCaptureBuffer->GetConnected(audio_port_index)) {
00472                 // Port is connected on other side...
00473                 fNetAudioCaptureBuffer->SetBuffer(audio_port_index,
00474                                                 ((jack_port_connected(fAudioCapturePorts[audio_port_index]) > 0)
00475                                                 ? static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index], fParams.fPeriodSize))
00476                                                 : NULL));
00477             } else {
00478                 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL);
00479             }
00480         #else
00481             fNetAudioCaptureBuffer->SetBuffer(audio_port_index,
00482                                             static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index],
00483                                             fParams.fPeriodSize)));
00484         #endif
00485             // TODO
00486         }
00487 
00488         for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
00489             fNetMidiPlaybackBuffer->SetBuffer(midi_port_index,
00490                                                 static_cast<JackMidiBuffer*>(jack_port_get_buffer(fMidiPlaybackPorts[midi_port_index],
00491                                                 fParams.fPeriodSize)));
00492         }
00493         for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
00494 
00495         #ifdef OPTIMIZED_PROTOCOL
00496             sample_t* out = (jack_port_connected(fAudioPlaybackPorts[audio_port_index]) > 0)
00497                 ? static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize))
00498                 : NULL;
00499             if (out) {
00500                 memset(out, 0, sizeof(float) * fParams.fPeriodSize);
00501             }
00502             fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out);
00503         #else
00504             sample_t* out = static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize));
00505             if (out) {
00506                 memset(out, 0, sizeof(float) * fParams.fPeriodSize);
00507             }
00508             fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out)));
00509         #endif
00510         }
00511 
00512         // encode the first packet
00513         EncodeSyncPacket();
00514 
00515         if (SyncSend() == SOCKET_ERROR) {
00516             return SOCKET_ERROR;
00517         }
00518 
00519 #ifdef JACK_MONITOR
00520         fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
00521 #endif
00522 
00523         // send data
00524         if (DataSend() == SOCKET_ERROR) {
00525             return SOCKET_ERROR;
00526         }
00527 
00528 #ifdef JACK_MONITOR
00529         fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
00530 #endif
00531 
00532         // receive sync
00533         int res = SyncRecv();
00534         switch (res) {
00535         
00536             case NET_SYNCHING:
00537             case SOCKET_ERROR:
00538                 return res;
00539                 
00540             case SYNC_PACKET_ERROR:
00541                  // Since sync packet is incorrect, don't decode it and continue with data
00542                  break;
00543                 
00544             default:
00545                 // Decode sync
00546                 int unused_frames;
00547                 DecodeSyncPacket(unused_frames);
00548                 break;
00549         }
00550 
00551 #ifdef JACK_MONITOR
00552         fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
00553 #endif
00554       
00555         // receive data
00556         res = DataRecv();
00557         switch (res) {
00558         
00559             case 0:
00560             case SOCKET_ERROR:
00561                 return res;
00562                 
00563             case DATA_PACKET_ERROR:
00564                 // Well not a real XRun...
00565                 JackServerGlobals::fInstance->GetEngine()->NotifyClientXRun(ALL_CLIENTS);
00566                 break;
00567         }
00568 
00569 #ifdef JACK_MONITOR
00570         fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
00571 #endif
00572         return 0;
00573     }
00574     
00575     void JackNetMaster::SaveConnections(connections_list_t& connections)
00576     {
00577         // Audio
00578         for (int i = 0; i < fParams.fSendAudioChannels; i++) {
00579             const char** connected_port = jack_port_get_all_connections(fClient, fAudioCapturePorts[i]);
00580             if (connected_port != NULL) {
00581                 for (int port = 0; connected_port[port]; port++) {
00582                     connections.push_back(make_pair(connected_port[port], jack_port_name(fAudioCapturePorts[i])));
00583                     jack_log("INPUT %s ==> %s", connected_port[port], jack_port_name(fAudioCapturePorts[i]));
00584                 }
00585                 jack_free(connected_port);
00586             }
00587         }
00588    
00589         for (int i = 0; i < fParams.fReturnAudioChannels; i++) {
00590             const char** connected_port = jack_port_get_all_connections(fClient, fAudioPlaybackPorts[i]);
00591             if (connected_port != NULL) {
00592                 for (int port = 0; connected_port[port]; port++) {
00593                     connections.push_back(make_pair(jack_port_name(fAudioPlaybackPorts[i]), connected_port[port]));
00594                     jack_log("OUTPUT %s ==> %s", jack_port_name(fAudioPlaybackPorts[i]), connected_port[port]);
00595                 }
00596                 jack_free(connected_port);
00597             }
00598         }
00599         
00600         // MIDI
00601         for (int i = 0; i < fParams.fSendMidiChannels; i++) {
00602             const char** connected_port = jack_port_get_all_connections(fClient, fMidiCapturePorts[i]);
00603             if (connected_port != NULL) {
00604                 for (int port = 0; connected_port[port]; port++) {
00605                     connections.push_back(make_pair(connected_port[port], jack_port_name(fMidiCapturePorts[i])));
00606                     jack_log("INPUT %s ==> %s", connected_port[port], jack_port_name(fMidiCapturePorts[i]));
00607                 }
00608                 jack_free(connected_port);
00609             }
00610         }
00611    
00612         for (int i = 0; i < fParams.fReturnMidiChannels; i++) {
00613             const char** connected_port = jack_port_get_all_connections(fClient, fMidiPlaybackPorts[i]);
00614             if (connected_port != NULL) {
00615                 for (int port = 0; connected_port[port]; port++) {
00616                     connections.push_back(make_pair(jack_port_name(fMidiPlaybackPorts[i]), connected_port[port]));
00617                     jack_log("OUTPUT %s ==> %s", jack_port_name(fMidiPlaybackPorts[i]), connected_port[port]);
00618                 }
00619                 jack_free(connected_port);
00620             }
00621         }
00622     }
00623     
00624     void JackNetMaster::LoadConnections(const connections_list_t& connections)
00625     {
00626         list<pair<string, string> >::const_iterator it;
00627         for (it = connections.begin(); it != connections.end(); it++) {
00628             pair<string, string> connection = *it;
00629             jack_connect(fClient, connection.first.c_str(), connection.second.c_str());
00630         }
00631     }
00632 
00633 
00634 //JackNetMasterManager***********************************************************************************************
00635 
00636     JackNetMasterManager::JackNetMasterManager(jack_client_t* client, const JSList* params) : fSocket()
00637     {
00638         jack_log("JackNetMasterManager::JackNetMasterManager");
00639 
00640         fClient = client;
00641         fName = jack_get_client_name(fClient);
00642         fGlobalID = 0;
00643         fRunning = true;
00644         fAutoConnect = false;
00645         fAutoSave = false;
00646 
00647         const JSList* node;
00648         const jack_driver_param_t* param;
00649      
00650         jack_on_shutdown(fClient, SetShutDown, this);
00651     
00652         // Possibly use env variable
00653         const char* default_udp_port = getenv("JACK_NETJACK_PORT");
00654         fSocket.SetPort((default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT);
00655 
00656         const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
00657         if (default_multicast_ip) {
00658             strcpy(fMulticastIP, default_multicast_ip);
00659         } else {
00660             strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
00661         }
00662 
00663         for (node = params; node; node = jack_slist_next(node)) {
00664 
00665             param = (const jack_driver_param_t*) node->data;
00666             switch (param->character) {
00667                 case 'a' :
00668                     if (strlen(param->value.str) < 32) {
00669                         strcpy(fMulticastIP, param->value.str);
00670                     } else {
00671                         jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
00672                     }
00673                     break;
00674 
00675                 case 'p':
00676                     fSocket.SetPort(param->value.ui);
00677                     break;
00678 
00679                 case 'c':
00680                     fAutoConnect = true;
00681                     break;
00682                     
00683                 case 's':
00684                     fAutoSave = true;
00685                     break;
00686             }
00687         }
00688 
00689         //set sync callback
00690         jack_set_sync_callback(fClient, SetSyncCallback, this);
00691 
00692         //activate the client (for sync callback)
00693         if (jack_activate(fClient) != 0) {
00694             jack_error("Can't activate the NetManager client, transport disabled");
00695         }
00696 
00697         //launch the manager thread
00698         if (jack_client_create_thread(fClient, &fThread, 0, 0, NetManagerThread, this)) {
00699             jack_error("Can't create the NetManager control thread");
00700         }
00701     }
00702 
00703     JackNetMasterManager::~JackNetMasterManager()
00704     {
00705         jack_log("JackNetMasterManager::~JackNetMasterManager");
00706         ShutDown();
00707     }
00708 
00709     int JackNetMasterManager::CountIO(const char* type, int flags)
00710     {
00711         int count = 0;
00712         const char** ports = jack_get_ports(fClient, NULL, type, flags);
00713         if (ports != NULL) {
00714             while (ports[count]) { count++; }
00715             jack_free(ports);
00716         }
00717         return count;
00718     }
00719     
00720     void JackNetMasterManager::SetShutDown(void* arg)
00721     {
00722         static_cast<JackNetMasterManager*>(arg)->ShutDown();
00723     }
00724     
00725     void JackNetMasterManager::ShutDown()
00726     {
00727         jack_log("JackNetMasterManager::ShutDown");
00728         if (fRunning) {
00729             jack_client_kill_thread(fClient, fThread);
00730             fRunning = false;
00731         }
00732         master_list_t::iterator it;
00733         for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
00734             delete (*it);
00735         }
00736         fMasterList.clear();
00737         fSocket.Close();
00738         SocketAPIEnd();
00739     }
00740 
00741     int JackNetMasterManager::SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg)
00742     {
00743         return static_cast<JackNetMasterManager*>(arg)->SyncCallback(state, pos);
00744     }
00745 
00746     int JackNetMasterManager::SyncCallback(jack_transport_state_t state, jack_position_t* pos)
00747     {
00748         //check if each slave is ready to roll
00749         int res = 1;
00750         master_list_it_t it;
00751         for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
00752             if (!(*it)->IsSlaveReadyToRoll()) {
00753                 res = 0;
00754             }
00755         }
00756         jack_log("JackNetMasterManager::SyncCallback returns '%s'", (res) ? "true" : "false");
00757         return res;
00758     }
00759 
00760     void* JackNetMasterManager::NetManagerThread(void* arg)
00761     {
00762         JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*>(arg);
00763         jack_info("Starting Jack NetManager");
00764         jack_info("Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort());
00765         master_manager->Run();
00766         return NULL;
00767     }
00768 
00769     void JackNetMasterManager::Run()
00770     {
00771         jack_log("JackNetMasterManager::Run");
00772         //utility variables
00773         int attempt = 0;
00774 
00775         //data
00776         session_params_t host_params;
00777         int rx_bytes = 0;
00778         JackNetMaster* net_master;
00779 
00780         //init socket API (win32)
00781         if (SocketAPIInit() < 0) {
00782             jack_error("Can't init Socket API, exiting...");
00783             return;
00784         }
00785 
00786         //socket
00787         if (fSocket.NewSocket() == SOCKET_ERROR) {
00788             jack_error("Can't create NetManager input socket : %s", StrError(NET_ERROR_CODE));
00789             return;
00790         }
00791 
00792         //bind the socket to the local port
00793         if (fSocket.Bind() == SOCKET_ERROR) {
00794             jack_error("Can't bind NetManager socket : %s", StrError(NET_ERROR_CODE));
00795             fSocket.Close();
00796             return;
00797         }
00798 
00799         //join multicast group
00800         if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
00801             jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
00802         }
00803 
00804         //local loop
00805         if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
00806             jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
00807         }
00808 
00809         //set a timeout on the multicast receive (the thread can now be cancelled)
00810         if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
00811             jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
00812         }
00813 
00814         //main loop, wait for data, deal with it and wait again
00815         do
00816         {
00817             session_params_t net_params;
00818             rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
00819             SessionParamsNToH(&net_params, &host_params);
00820             
00821             if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
00822                 jack_error("Error in receive : %s", StrError(NET_ERROR_CODE));
00823                 if (++attempt == 10) {
00824                     jack_error("Can't receive on the socket, exiting net manager");
00825                     return;
00826                 }
00827             }
00828 
00829             if (rx_bytes == sizeof(session_params_t)) {
00830                 switch (GetPacketType(&host_params))
00831                 {
00832                     case SLAVE_AVAILABLE:
00833                         if ((net_master = InitMaster(host_params))) {
00834                             SessionParamsDisplay(&net_master->fParams);
00835                         } else {
00836                             jack_error("Can't init new NetMaster...");
00837                         }
00838                         jack_info("Waiting for a slave...");
00839                         break;
00840                     case KILL_MASTER:
00841                         if (KillMaster(&host_params)) {
00842                             jack_info("Waiting for a slave...");
00843                         }
00844                         break;
00845                     default:
00846                         break;
00847                 }
00848             }
00849         }
00850         while (fRunning);
00851     }
00852 
00853     JackNetMaster* JackNetMasterManager::InitMaster(session_params_t& params)
00854     {
00855         jack_log("JackNetMasterManager::InitMaster slave : %s", params.fName);
00856 
00857         //check MASTER <<==> SLAVE network protocol coherency
00858         if (params.fProtocolVersion != NETWORK_PROTOCOL) {
00859             jack_error("Error : slave '%s' is running with a different protocol %d != %d", params.fName, params.fProtocolVersion, NETWORK_PROTOCOL);
00860             return NULL;
00861         }
00862 
00863         //settings
00864         fSocket.GetName(params.fMasterNetName);
00865         params.fID = ++fGlobalID;
00866         params.fSampleRate = jack_get_sample_rate(fClient);
00867         params.fPeriodSize = jack_get_buffer_size(fClient);
00868 
00869         if (params.fSendAudioChannels == -1) {
00870             params.fSendAudioChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
00871             jack_info("Takes physical %d audio input(s) for slave", params.fSendAudioChannels);
00872         }
00873 
00874         if (params.fReturnAudioChannels == -1) {
00875             params.fReturnAudioChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
00876             jack_info("Takes physical %d audio output(s) for slave", params.fReturnAudioChannels);
00877         }
00878         
00879         if (params.fSendMidiChannels == -1) {
00880             params.fSendMidiChannels = CountIO(JACK_DEFAULT_MIDI_TYPE, JackPortIsPhysical | JackPortIsOutput);
00881             jack_info("Takes physical %d MIDI input(s) for slave", params.fSendMidiChannels);
00882         }
00883 
00884         if (params.fReturnMidiChannels == -1) {
00885             params.fReturnMidiChannels = CountIO(JACK_DEFAULT_MIDI_TYPE, JackPortIsPhysical | JackPortIsInput);
00886             jack_info("Takes physical %d MIDI output(s) for slave", params.fReturnMidiChannels);
00887         }
00888 
00889         //create a new master and add it to the list
00890         JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP);
00891         if (master->Init(fAutoConnect)) {
00892             fMasterList.push_back(master);
00893             if (fAutoSave && fMasterConnectionList.find(params.fName) != fMasterConnectionList.end()) {
00894                 master->LoadConnections(fMasterConnectionList[params.fName]);
00895             }
00896             return master;
00897         } else {
00898             delete master;
00899             return NULL;
00900         }
00901     }
00902 
00903     master_list_it_t JackNetMasterManager::FindMaster(uint32_t id)
00904     {
00905         jack_log("JackNetMasterManager::FindMaster ID = %u", id);
00906 
00907         master_list_it_t it;
00908         for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
00909             if ((*it)->fParams.fID == id) {
00910                 return it;
00911             }
00912         }
00913         return it;
00914     }
00915 
00916     int JackNetMasterManager::KillMaster(session_params_t* params)
00917     {
00918         jack_log("JackNetMasterManager::KillMaster ID = %u", params->fID);
00919 
00920         master_list_it_t master_it = FindMaster(params->fID);
00921         if (master_it != fMasterList.end()) {
00922             if (fAutoSave) {
00923                 fMasterConnectionList[params->fName].clear();
00924                 (*master_it)->SaveConnections(fMasterConnectionList[params->fName]);
00925             }
00926             fMasterList.erase(master_it);
00927             delete (*master_it);
00928             return 1;
00929         }
00930         return 0;
00931     }
00932 }//namespace
00933 
00934 static Jack::JackNetMasterManager* master_manager = NULL;
00935 
00936 #ifdef __cplusplus
00937 extern "C"
00938 {
00939 #endif
00940 
00941     SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00942     {
00943         jack_driver_desc_t * desc;
00944         jack_driver_desc_filler_t filler;
00945         jack_driver_param_value_t value;
00946 
00947         desc = jack_driver_descriptor_construct("netmanager", JackDriverNone, "netjack multi-cast master component", &filler);
00948 
00949         strcpy(value.str, DEFAULT_MULTICAST_IP);
00950         jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address", NULL);
00951 
00952         value.i = DEFAULT_PORT;
00953         jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
00954 
00955         value.i = false;
00956         jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", NULL);
00957 
00958         value.i = false;
00959         jack_driver_descriptor_add_parameter(desc, &filler, "auto-save", 's', JackDriverParamBool, &value, NULL, "Save/restore netmaster connection state when restarted", NULL);
00960 
00961         return desc;
00962     }
00963 
00964     SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params)
00965     {
00966         if (master_manager) {
00967             jack_error("Master Manager already loaded");
00968             return 1;
00969         } else {
00970             jack_log("Loading Master Manager");
00971             master_manager = new Jack::JackNetMasterManager(jack_client, params);
00972             return (master_manager) ? 0 : 1;
00973         }
00974     }
00975 
00976     SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
00977     {
00978         JSList* params = NULL;
00979         bool parse_params = true;
00980         int res = 1;
00981         jack_driver_desc_t* desc = jack_get_descriptor();
00982 
00983         Jack::JackArgParser parser(load_init);
00984         if (parser.GetArgc() > 0) {
00985             parse_params = parser.ParseParams(desc, &params);
00986         }
00987 
00988         if (parse_params) {
00989             res = jack_internal_initialize(jack_client, params);
00990             parser.FreeParams(params);
00991         }
00992         return res;
00993     }
00994 
00995     SERVER_EXPORT void jack_finish(void* arg)
00996     {
00997         if (master_manager) {
00998             jack_log("Unloading Master Manager");
00999             delete master_manager;
01000             master_manager = NULL;
01001         }
01002     }
01003 
01004 #ifdef __cplusplus
01005 }
01006 #endif