Network.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2007 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 
00023 #include "Network.hxx"
00024 #include "NaiveFlowControl.hxx"
00025 #include "NetworkPlayer.hxx"
00026 #include <algorithm>
00027 #include "ProcessingDefinitionAdapter.hxx"
00028 #include "ConnectionDefinitionAdapter.hxx"
00029 #include "InformationTextAdapter.hxx"
00030 #include "ProcessingFactory.hxx"
00031 #include "XmlStorageErr.hxx"
00032 #ifdef USE_LADSPA //TODO alway include it. move conditional code in LFactory.hxx
00033 #include "ProcessingFactory.hxx"
00034 #endif
00035 #include "ControlSink.hxx"
00036 #include "ControlSource.hxx"
00037 #include "CLAMVersion.hxx"
00038 
00039 #include <sstream>
00040 #include <algorithm>
00041 #include <iterator>
00042 
00043 
00044 namespace CLAM
00045 {       
00046         typedef std::pair<double, Processing *> ProcessingAndGeometry;
00047 
00048         Network::Network() :
00049                 _name("Unnamed Network"),
00050                 _flowControl(new NaiveFlowControl),
00051                 _player(0),
00052                 _inPasteMode(false)
00053         {}
00054         
00055         Network::~Network()
00056         {
00057                 //std::cerr <<" *\t\t\t~NETWORK"<<std::endl;
00058                 Clear();
00059                 if (_flowControl) delete _flowControl;
00060                 if (_player) delete _player;
00061         }
00062 
00063         void Network::StoreOn( Storage & storage) const
00064         {
00065                 XMLAdapter<std::string> strAdapter( _name, "id");
00066                 storage.Store(strAdapter);
00067 
00068                 std::string version = CLAM::GetVersion();
00069                 XMLAdapter<std::string> versionAdapter( version, "clamVersion");
00070                 storage.Store(versionAdapter);
00071                 
00072                 if (not _description.empty())
00073                 {
00074                         XMLAdapter<Text> descriptionAdapter(_description, "description", true);
00075                         storage.Store(descriptionAdapter);
00076                 }
00077                 
00078                 ProcessingsMap::const_iterator it;
00079                 for(it=BeginProcessings();it!=EndProcessings();it++)
00080                 {
00081                         Processing * proc = it->second;
00082                         const std::string & name = it->first;
00083                         if (SelectionAndDoesNotContain(name))
00084                                 continue;
00085                         std::string processingPosition;
00086                         std::string processingSize;
00087                         // if exists canvas geometries, store them
00088                         if (!_processingsGeometries.empty())
00089                         {
00090                                 Geometry & geometry=_processingsGeometries.find(name)->second;
00091                                 processingPosition=IntsToString (geometry.x, geometry.y);
00092                                 processingSize=IntsToString (geometry.width, geometry.height);
00093                         }
00094                         ProcessingDefinitionAdapter procDefinition(proc, name, processingPosition, processingSize);
00095                         XMLComponentAdapter xmlAdapter(procDefinition, "processing", true);
00096                         storage.Store(xmlAdapter);
00097                 }
00098 
00099                 // second iteration to store ports. 
00100                 // XR: maybe it should be all in one iteration but this way
00101                 // the xml file is clearer.
00102 
00103                 for(it=BeginProcessings();it!=EndProcessings();it++)
00104                 {
00105                         const std::string & name = it->first;
00106                         Processing * proc = it->second;
00107 
00108                         if (SelectionAndDoesNotContain(name))
00109                                 continue;
00110 
00111                         unsigned nOutPorts = proc->GetNOutPorts();
00112                         for (unsigned i = 0; i<nOutPorts; i++)
00113                         {
00114                                 OutPortBase & outport = proc->GetOutPort(i);
00115                                 if (!outport.HasConnections())
00116                                         continue;
00117         
00118                                 std::string outPortName = name + "." + outport.GetName();
00119                                 NamesList namesInPorts = GetInPortsConnectedTo(outPortName);
00120                                 NamesList::iterator namesIterator;
00121                                 for(namesIterator=namesInPorts.begin();
00122                                     namesIterator!=namesInPorts.end();
00123                                     namesIterator++)
00124                                 {
00125                                         if (SelectionAndDoesNotContain(GetProcessingIdentifier(*namesIterator)))
00126                                                 continue;
00127                                         ConnectionDefinitionAdapter connectionDefinition( outPortName, *namesIterator );
00128                                         XMLComponentAdapter xmlAdapter(connectionDefinition, "port_connection", true);
00129                                         storage.Store(xmlAdapter);
00130                                 }
00131                         }
00132                 }
00133 
00134                 for(it=BeginProcessings();it!=EndProcessings();it++)
00135                 {
00136                         const std::string & name = it->first;
00137                         Processing * proc = it->second;
00138 
00139                         if (SelectionAndDoesNotContain(name))
00140                                 continue;
00141 
00142                         unsigned nOutControls = proc->GetNOutControls();
00143                         for (unsigned i = 0; i<nOutControls; i++)
00144                         {
00145                                 OutControlBase & outControl = proc->GetOutControl(i);
00146                                 std::string outControlName = name+ "." + outControl.GetName();
00147                                 NamesList namesInControls = GetInControlsConnectedTo(outControlName);
00148                                 NamesList::iterator namesIterator;
00149                                 for(namesIterator=namesInControls.begin();
00150                                     namesIterator!=namesInControls.end();
00151                                     namesIterator++)
00152                                 {
00153                                         if (SelectionAndDoesNotContain(GetProcessingIdentifier(*namesIterator)))
00154                                                 continue;
00155                                         ConnectionDefinitionAdapter connectionDefinition( outControlName, *namesIterator );
00156                                         XMLComponentAdapter xmlAdapter(connectionDefinition, "control_connection", true);
00157                                         storage.Store(xmlAdapter);
00158                                 }
00159                         }
00160                 }
00161 
00162                 InformationTexts::const_iterator ibIt;
00163                 for(ibIt=BeginInformationTexts();ibIt!=EndInformationTexts();ibIt++)
00164                 {
00165                         InformationTextAdapter infoTextDefinition((*ibIt)->x, (*ibIt)->y, (*ibIt)->text);
00166                         XMLComponentAdapter xmlAdapter(infoTextDefinition, "information", true);
00167                         storage.Store(xmlAdapter);
00168                 }
00169 
00170                 _selectedProcessings.clear();
00171                 _processingsGeometries.clear();
00172         }
00173 
00174         void Network::LoadFrom( Storage & storage)
00175         {
00176                 typedef std::map <std::string, std::string> NamesMap;
00177                 NamesMap namesMap;
00178                 if (!_inPasteMode) Clear();
00179                 XMLAdapter<std::string> strAdapter( _name, "id");
00180                 storage.Load(strAdapter);
00181                 _processingsGeometries.clear();
00182 
00183                 XMLAdapter<Text> descriptionAdapter(_description, "description", true);
00184                 if(not storage.Load(descriptionAdapter)) _description="";
00185         
00186                 while(1)
00187                 {
00188                         ProcessingDefinitionAdapter procDefinition;
00189                         XMLComponentAdapter xmlAdapter(procDefinition, "processing", true);
00190                         if (not storage.Load(xmlAdapter)) break;
00191 
00192                         const std::string & definitionName = procDefinition.GetName();
00193                         CLAM::Processing * processing = procDefinition.GetProcessing();
00194                         std::string finalName = definitionName;
00195                         if (_inPasteMode)
00196                         {
00197                                 finalName = GetUnusedName(definitionName, true);
00198                                 namesMap.insert(std::make_pair(definitionName,finalName));
00199                         }
00200                         AddProcessing(finalName, processing, procDefinition.GetConfiguration());
00201                         // if exists canvas geometries, restore them
00202                         if (procDefinition.GetPosition()!="" && procDefinition.GetSize()!="")
00203                         {
00204                                 Geometry geometry;
00205                                 StringPairToInts(procDefinition.GetPosition(),geometry.x,geometry.y);
00206                                 StringPairToInts(procDefinition.GetSize(),geometry.width,geometry.height);
00207                                 _processingsGeometries.insert(ProcessingsGeometriesMap::value_type(finalName,geometry));
00208                         }
00209                 }
00210 
00211                 while(1)
00212                 {
00213                         ConnectionDefinitionAdapter connectionDefinition;
00214                         XMLComponentAdapter xmlAdapter(connectionDefinition, "port_connection", true);
00215                         if (not storage.Load(xmlAdapter)) break;
00216                         std::string fullOut = connectionDefinition.GetOutName();
00217                         std::string fullIn = connectionDefinition.GetInName();
00218 
00219                         if (_inPasteMode)
00220                         {
00221                                 fullOut = namesMap.find(GetProcessingIdentifier(fullOut))->second
00222                                         +"."+GetConnectorIdentifier(fullOut);
00223                                 fullIn = namesMap.find(GetProcessingIdentifier(fullIn))->second
00224                                         +"."+GetConnectorIdentifier(fullIn);
00225                         }
00226 
00227                         if (BrokenConnection(fullOut, fullIn))
00228                                 continue;
00229 
00230                         if (not ConnectPorts( fullOut, fullIn ))
00231                         {
00232                                 throw XmlStorageErr(std::string("Unable to connect ports '")+fullOut+"->"+fullIn+".");
00233                         }
00234                 }
00235 
00236                 while(1)
00237                 {
00238                         ConnectionDefinitionAdapter connectionDefinition;
00239                         XMLComponentAdapter xmlAdapter(connectionDefinition, "control_connection", true);
00240                         if (!storage.Load(xmlAdapter)) break;
00241                         std::string fullOut = connectionDefinition.GetOutName();
00242                         std::string fullIn = connectionDefinition.GetInName();
00243                         if (_inPasteMode)
00244                         {
00245                                 fullOut = namesMap.find(GetProcessingIdentifier(fullOut))->second
00246                                         +"."+GetConnectorIdentifier(fullOut);
00247                                 fullIn = namesMap.find(GetProcessingIdentifier(fullIn))->second
00248                                         +"."+GetConnectorIdentifier(fullIn);
00249                         }
00250                         if (not ConnectControls( fullOut, fullIn ))
00251                                 throw XmlStorageErr(std::string("Unable to connect controls '")+fullOut+"->"+fullIn+".");
00252                 }
00253 
00254                 while(1)
00255                 {
00256                         InformationTextAdapter infoTextDefinition;
00257                         XMLComponentAdapter xmlAdapter(infoTextDefinition, "information", true);
00258                         if (not storage.Load(xmlAdapter)) break;
00259                         
00260                         InformationText *myInformationText=new InformationText();
00261                         myInformationText->x=infoTextDefinition.GetCoordX();
00262                         myInformationText->y=infoTextDefinition.GetCoordY();
00263                         myInformationText->text=infoTextDefinition.GetText();                   
00264 
00265                         _informationTexts.push_back(myInformationText);
00266                 }
00267 
00268                 _inPasteMode=false;
00269         }
00270 
00271         bool Network::UpdateSelections (const NamesList & processingsNamesList)
00272         {
00273                 if (!_selectedProcessings.empty() || processingsNamesList.empty())
00274                 {
00275                         _selectedProcessings.clear();
00276                         return true;
00277                 }
00278                 NamesList::const_iterator namesIterator;
00279                 for (namesIterator=processingsNamesList.begin();namesIterator!=processingsNamesList.end();namesIterator++)
00280                         _selectedProcessings.insert(*namesIterator);
00281                 return false;
00282         }
00283 
00284         bool Network::SelectionAndDoesNotContain(const std::string & name) const
00285         {
00286                 if (_selectedProcessings.empty()) return false;
00287                 return _selectedProcessings.count(name)==0;
00288         }
00289 
00290 
00291         const Network::Geometry & Network::getProcessingGeometry(const std::string & processingName) const
00292         {
00293                 ProcessingsGeometriesMap::const_iterator it =
00294                         _processingsGeometries.find(processingName);
00295                 if (it!=_processingsGeometries.end())
00296                         return it->second;
00297                 static Geometry nullGeometry={0,10000,0,0};
00298                 return nullGeometry;
00299         }
00300 
00301         const Network::Processings Network::getOrderedProcessings(const std::string & type, bool horizontalOrder) const
00302         {
00303                 std::list <ProcessingAndGeometry> processingsAndGeometries;
00304                 for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
00305                 {
00306                         Processing * proc = it->second;
00307                         const std::string className = proc->GetClassName();
00308                         if (className!=type) continue;
00309                         const Geometry & geometry = getProcessingGeometry(it->first);
00310                         int position = horizontalOrder ? geometry.x : geometry.y;
00311                         processingsAndGeometries.push_back(std::make_pair(position, proc));
00312                 }
00313                 processingsAndGeometries.sort();
00314 
00315                 Processings orderedProcessings;
00316                 for (std::list<ProcessingAndGeometry>::const_iterator it=processingsAndGeometries.begin();
00317                         it!=processingsAndGeometries.end();it++)
00318                 {
00319                         orderedProcessings.push_back( it->second );
00320                 }
00321 
00322                 return orderedProcessings;
00323         }
00324 
00325         const Network::Processings Network::getOrderedProcessingsByAttribute(const std::string & attribute, bool horizontalOrder) const
00326         {
00327                 ProcessingFactory & factory = ProcessingFactory::GetInstance();
00328                 std::list <ProcessingAndGeometry> processingsAndGeometries;
00329                 for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
00330                 {
00331                         Processing * proc = it->second;
00332                         const std::string className = proc->GetClassName();
00333                         if (!factory.AttributeExists(className,attribute)) continue;
00334                         const Geometry & geometry = getProcessingGeometry(it->first);
00335                         int position = horizontalOrder? geometry.x : geometry.y;
00336                         processingsAndGeometries.push_back(std::make_pair(position, proc));
00337                 }
00338                 processingsAndGeometries.sort();
00339 
00340                 Processings orderedProcessings;
00341                 for (std::list<ProcessingAndGeometry>::const_iterator it=processingsAndGeometries.begin();
00342                         it!=processingsAndGeometries.end();it++)
00343                 {
00344                         orderedProcessings.push_back( it->second );
00345                 }
00346                 return orderedProcessings;
00347         }
00348 
00349         const Network::ControlSinks Network::getOrderedControlSinks() const
00350         {
00351                 std::list <ProcessingAndGeometry> processingsAndGeometries;
00352                 for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
00353                 {
00354                         Processing * proc = it->second;
00355                         const std::string className = proc->GetClassName();
00356                         if (className!="ControlSink") continue;
00357                         const Geometry & geometry = getProcessingGeometry(it->first);
00358                         int position = geometry.x;
00359                         processingsAndGeometries.push_back(std::make_pair(position, proc));
00360                 }
00361                 processingsAndGeometries.sort();
00362 
00363                 ControlSinks orderedControlSinks;
00364                 for (std::list<ProcessingAndGeometry>::const_iterator it=processingsAndGeometries.begin();
00365                         it!=processingsAndGeometries.end();it++)
00366                 {
00367                         ControlSink* controlSink = dynamic_cast<ControlSink*>(it->second);
00368                         CLAM_ASSERT(controlSink, "Expected an AudioSink");
00369                         orderedControlSinks.push_back( controlSink );
00370                 }
00371                 return orderedControlSinks;
00372         }
00373         
00374         const Network::ControlSources Network::getOrderedControlSources() const
00375         {
00376                 std::list <ProcessingAndGeometry> processingsAndGeometries;
00377                 for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
00378                 {
00379                         Processing * proc = it->second;
00380                         const std::string className = proc->GetClassName();
00381                         if (className!="ControlSource") continue;
00382                         const Geometry & geometry = getProcessingGeometry(it->first);
00383                         int position = geometry.x;
00384                         processingsAndGeometries.push_back(std::make_pair(position, proc));
00385                 }
00386                 processingsAndGeometries.sort();
00387 
00388                 ControlSources orderedControlSources;
00389                 for (std::list<ProcessingAndGeometry>::const_iterator it=processingsAndGeometries.begin();
00390                         it!=processingsAndGeometries.end();it++)
00391                 {
00392                         ControlSource* controlSource = dynamic_cast<ControlSource*>(it->second);
00393                         CLAM_ASSERT(controlSource, "Expected an AudioSink");
00394                         orderedControlSources.push_back( controlSource );
00395                 }
00396                 return orderedControlSources;
00397         }
00398 
00399         bool Network::SetProcessingsGeometries (const ProcessingsGeometriesMap & processingsGeometries)
00400         {
00401                 _processingsGeometries.clear(); 
00402                 if (processingsGeometries.empty())
00403                         return true;
00404                 _processingsGeometries=processingsGeometries;
00405                 return false;
00406         }
00407 
00408         const Network::ProcessingsGeometriesMap Network::GetAndClearGeometries()
00409         {
00410                 const ProcessingsGeometriesMap copyProcessingsGeometry(_processingsGeometries);
00411                 _processingsGeometries.clear();
00412                 return copyProcessingsGeometry;
00413         }
00414 
00415         void Network::StringPairToInts(const std::string & geometryInString, int & a, int & b)
00416         {
00417                 a=atoi(geometryInString.substr(0,geometryInString.find(",")).c_str());
00418                 b=atoi(geometryInString.substr(geometryInString.find(",")+1,geometryInString.length()).c_str());
00419         }
00420 
00421         const std::string Network::IntsToString (const int & a, const int & b) const
00422         {
00423                 std::ostringstream stream;
00424                 stream<<a<<","<<b;
00425                 return stream.str();
00426         }
00427 
00428         // flow and player related methods
00429         void Network::AddFlowControl(FlowControl* flowControl)
00430         {
00431                 if (_flowControl) delete _flowControl;
00432                 _flowControl = flowControl;
00433                 _flowControl->AttachToNetwork((CLAM::Network*)this);
00434         }
00435         void Network::SetPlayer(NetworkPlayer* player)
00436         {
00437                 if (_player) delete _player;
00438                 _player = player;
00439                 _player->SetNetworkBackLink(*(CLAM::Network*)this);
00440                 _player->Init();
00441         }
00442         unsigned Network::BackendBufferSize()
00443         {
00444                 if (!_player) return 512;
00445                 return _player->BackendBufferSize();
00446         }
00447         unsigned Network::BackendSampleRate()
00448         {
00449                 if (!_player) return 44100;
00450                 return _player->BackendSampleRate();
00451         }
00452 
00453 
00454         Processing& Network::GetProcessing( const std::string & name ) const
00455         {
00456                 CLAM_ASSERT( HasProcessing(name), 
00457                         ("No processing in the network has the name '"+name+"'.").c_str());
00458 
00459                 ProcessingsMap::const_iterator it = _processings.find( name );
00460                 return *it->second;
00461         }
00462 
00463         void Network::AddProcessing( const std::string & name, Processing* proc, const ProcessingConfig * config)
00464         {
00465                 if (!IsStopped()) Stop();
00466 
00467                 if (!_processings.insert( ProcessingsMap::value_type( name, proc ) ).second )
00468                         CLAM_ASSERT(false, "Network::AddProcessing() Trying to add a processing with a repeated name (key)" );
00469                 proc->SetNetworkBackLink((CLAM::Network*)this);
00470                 proc->Configure(config ? *config : proc->GetConfig());
00471                 _flowControl->ProcessingAddedToNetwork(*proc);
00472         }
00473 
00474         Processing & Network::AddProcessing( const std::string & name, const std::string & factoryKey )
00475         {
00476                 Processing * proc = ProcessingFactory::GetInstance().CreateSafe( factoryKey  );
00477                 AddProcessing(name, proc);
00478                 return *proc;
00479         }
00480 
00481         std::string Network::AddProcessing( const std::string & factoryKey )
00482         {
00483                 std::string name = GetUnusedName( factoryKey  ); 
00484                 AddProcessing(name, factoryKey );
00485                 return name;
00486         }
00487 
00488         std::string Network::GetUnusedName( const std::string& prefix, const bool cutOnLastSeparator, const std::string separator ) const
00489         {
00490                 std::string name;
00491                 std::string newPrefix=prefix;
00492                 if (cutOnLastSeparator==true)
00493                 {
00494                         int lastSeparatorPos=prefix.rfind(separator);
00495                         if (lastSeparatorPos!=-1)
00496                                 newPrefix=prefix.substr(0,lastSeparatorPos);
00497                 }
00498 
00499                 for ( int i = 0; i<9999999; i++ ) 
00500                 {
00501                         std::stringstream tmp; 
00502                         tmp << i;
00503                         name = i? newPrefix + separator + tmp.str() : newPrefix; 
00504                         if (!this->HasProcessing( name ) ) return name;
00505                 }
00506                 CLAM_ASSERT(false, "All valid id's for given prefix are exhausted");
00507                 return "";
00508         }
00509 
00510         void Network::RemoveProcessing ( const std::string & name)
00511         {
00512                 CLAM_ASSERT( _flowControl, 
00513                              "Network::RemoveProcessing() - Network should have an attached flow control at this state.");
00514 
00515                 ProcessingsMap::const_iterator i = _processings.find( name );
00516                 if(i==_processings.end())
00517                 {
00518                         std::string msg("Network::RemoveProcessing() Trying to remove a processing that is not included in the network:");
00519                         msg += name;
00520                         CLAM_ASSERT(false, msg.c_str() );
00521                 }
00522                 if ( !IsStopped() ) Stop(); 
00523                 Processing * proc = i->second;
00524                 _processings.erase( name );
00525 
00526                 _flowControl->ProcessingRemovedFromNetwork(*proc);
00527                 delete proc;            
00528         }
00529 
00530         bool Network::HasProcessing( const std::string& name ) const
00531         {
00532                 ProcessingsMap::const_iterator i = _processings.find( name );
00533                 return i!=_processings.end();
00534         }
00535         
00536         bool Network::ConfigureProcessing( const std::string & name, const ProcessingConfig & newConfig )       
00537         {
00538                 ProcessingsMap::iterator it = _processings.find( name );
00539                 CLAM_ASSERT(it!=_processings.end(),"Wrong processing name to configure in a network");
00540                 Processing * proc = it->second;
00541                 if ( !IsStopped() ) Stop();
00542                 bool ok = proc->Configure( newConfig );
00543                 _flowControl->ProcessingConfigured(*proc);
00544                 return ok;
00545         }
00546 
00547         void Network::ReconfigureAllProcessings()
00548         {
00549                 ProcessingsMap::iterator it;
00550                 for( it=_processings.begin(); it!=_processings.end(); it++)
00551                 {
00552                         Processing* proc = it->second;
00553                         proc->Configure( proc->GetConfig() );
00554                 }
00555         }
00556 
00557         bool Network::ConnectPorts( const std::string & producer, const std::string & consumer )
00558         {
00559                 _flowControl->NetworkTopologyChanged();
00560 
00561                 OutPortBase & outport = GetOutPortByCompleteName(producer);
00562                 InPortBase & inport = GetInPortByCompleteName(consumer);
00563 
00564                 if ( outport.IsVisuallyConnectedTo(inport) ) 
00565                         return false;
00566                         
00567                 if ( !outport.IsConnectableTo(inport) ) //they have different type
00568                         return false;
00569 
00570                 if( inport.GetVisuallyConnectedOutPort())
00571                         return false;
00572 
00573                 if (!IsStopped()) Stop();
00574 
00575                 outport.ConnectToIn( inport );
00576                 return true;
00577         }
00578 
00579         bool Network::ConnectControls( const std::string & producer, const std::string & consumer )
00580         {
00581                 OutControlBase & outcontrol = GetOutControlByCompleteName(producer);
00582                 InControlBase & incontrol = GetInControlByCompleteName(consumer);
00583 
00584                 if ( outcontrol.IsConnectedTo(incontrol) ) 
00585                         return false;
00586 
00587                 if ( !outcontrol.IsLinkable(incontrol) ) //they have different type
00588                         return false;
00589 
00590                 if (!IsStopped()) Stop();
00591 
00592                 outcontrol.AddLink( incontrol );
00593                 return true;
00594         }
00595 
00596 
00597         bool Network::DisconnectPorts( const std::string & producer, const std::string & consumer)
00598         {
00599                 _flowControl->NetworkTopologyChanged();
00600 
00601                 OutPortBase & outport = GetOutPortByCompleteName(producer);
00602                 InPortBase & inport = GetInPortByCompleteName(consumer);
00603 
00604                 if ( !outport.IsVisuallyConnectedTo(inport))
00605                         return false;
00606 
00607                 if (!IsStopped()) Stop();
00608 
00609                 outport.DisconnectFromIn( inport );
00610                 return true;
00611         }
00612 
00613         bool Network::DisconnectControls( const std::string & producer, const std::string & consumer)
00614         {
00615                 OutControlBase & outcontrol = GetOutControlByCompleteName(producer);
00616                 InControlBase & incontrol = GetInControlByCompleteName(consumer);
00617 
00618                 if ( !outcontrol.IsConnectedTo( incontrol )) 
00619                         return false;
00620 
00621                 if (!IsStopped()) Stop();
00622 
00623                 outcontrol.RemoveLink( incontrol );
00624                 return true;
00625         }
00626 
00627         std::string Network::GetConnectorIdentifier( const std::string& str ) const
00628         {
00629                 return str.substr( PositionOfLastIdentifier(str)+1 );
00630         }
00631 
00632         std::string Network::GetProcessingIdentifier( const std::string& str ) const
00633         {
00634                 std::size_t length = PositionOfLastIdentifier(str)  - PositionOfProcessingIdentifier(str);
00635                 return str.substr( PositionOfProcessingIdentifier(str), length);
00636         }
00637 
00638         InPortBase & Network::GetInPortByCompleteName( const std::string & name ) const
00639         {
00640                 Processing& proc = GetProcessing( GetProcessingIdentifier(name) );
00641                 return proc.GetInPort( GetConnectorIdentifier(name) );
00642         }
00643 
00644         OutPortBase & Network::GetOutPortByCompleteName( const std::string & name ) const
00645         {
00646                 Processing& proc = GetProcessing( GetProcessingIdentifier(name) );
00647                 return proc.GetOutPort( GetConnectorIdentifier(name) );
00648         }
00649 
00650         InControlBase & Network::GetInControlByCompleteName( const std::string & name ) const
00651         {
00652                 Processing& proc = GetProcessing( GetProcessingIdentifier(name) );
00653                 return proc.GetInControl( GetConnectorIdentifier(name) );
00654         }
00655 
00656         OutControlBase & Network::GetOutControlByCompleteName( const std::string & name ) const
00657         {
00658                 Processing& proc = GetProcessing( GetProcessingIdentifier(name) );
00659                 return proc.GetOutControl( GetConnectorIdentifier(name) );
00660         }
00661 
00662         bool Network::IsStopped() const
00663         {
00664                 if (! _player) 
00665                         return true;
00666                 return _player->IsStopped();
00667         }
00668 
00669         bool Network::IsPlaying() const
00670         {
00671                 if (! _player) 
00672                         return false;
00673                 return _player->IsPlaying();
00674         }
00675 
00676         bool Network::IsPaused() const
00677         {
00678                 if (! _player) 
00679                         return false;
00680                 return _player->IsPaused();
00681         }
00682 
00683         bool Network::IsRealTime() const
00684         {
00685                 if (! _player)
00686                         return false;
00687                 return _player->IsRealTime();
00688         }
00689 
00690         void Network::Start()
00691         {
00692                 ProcessingsMap::iterator it;
00693                 for (it=BeginProcessings(); it!=EndProcessings(); it++)
00694                 {
00695                         if (it->second->IsRunning()) 
00696                         {
00697                                 continue;
00698                         }
00699                         if (it->second->IsConfigured())
00700                         {
00701                                 it->second->Start();
00702                         }
00703                         else
00704                         {       
00705                                 std::cerr << "Warning: could not start processing for not being Configured: '" 
00706                                                 << it->first<< "' of class " << it->second->GetClassName() << std::endl;
00707                         }
00708                 }
00709                 if (_player) 
00710                         _player->Start();
00711         }
00712         
00713         void Network::Stop()
00714         {
00715                 if (_player) _player->Stop();
00716                 ProcessingsMap::iterator it;
00717                 for (it=BeginProcessings(); it!=EndProcessings(); it++)
00718                         if (it->second->IsRunning())
00719                                 it->second->Stop();
00720         }
00721         void Network::Pause()
00722         {
00723                 if (_player) _player->Pause();
00724         }
00725         
00726         void Network::Do()
00727         {
00728                 _flowControl->Do();
00729         }
00730 
00731         void Network::Clear()
00732         {
00733                 if ( !IsStopped() ) Stop(); 
00734                 
00735                 while( !_processings.empty() )
00736                 {
00737                         //std::cerr << "REMOVING <"<<_processings.begin()->first<<">"<<std::endl;
00738                         RemoveProcessing( _processings.begin()->first );
00739                 }
00740                 for(unsigned i=0;i<_informationTexts.size();i++)
00741                 {
00742                         removeInformationText(_informationTexts[i]);
00743                 }
00744                 _informationTexts.clear();
00745         }
00746 
00747         Network::ProcessingsMap::iterator Network::BeginProcessings()
00748         {
00749                 return _processings.begin();
00750         }
00751 
00752         Network::ProcessingsMap::iterator Network::EndProcessings()
00753         {
00754                 return _processings.end();
00755         }
00756         Network::ProcessingsMap::const_iterator Network::BeginProcessings() const
00757         {
00758                 return _processings.begin();
00759         }
00760 
00761         Network::ProcessingsMap::const_iterator Network::EndProcessings() const
00762         {
00763                 return _processings.end();
00764         }
00765 
00766         // accessors to text boxes
00767 
00768         void Network::addInformationText(InformationText * informationText)
00769         {
00770                 _informationTexts.push_back(informationText);
00771         }
00772 
00773         void Network::removeInformationText(InformationText * informationText)
00774         {
00775                 InformationTexts::iterator it = find(BeginInformationTexts(), EndInformationTexts(), informationText);
00776         
00777                 if(it!=EndInformationTexts())
00778                         _informationTexts.erase(it);
00779                 else
00780                         std::cerr << "Warning: Information Text Box does not exist.";
00781         }
00782 
00783         Network::InformationTexts::iterator Network::BeginInformationTexts()
00784         {
00785                 return _informationTexts.begin();
00786         }
00787         
00788         Network::InformationTexts::iterator Network::EndInformationTexts()
00789         {
00790                 return _informationTexts.end();
00791         }
00792         
00793         Network::InformationTexts::const_iterator Network::BeginInformationTexts() const
00794         {
00795                 return _informationTexts.begin();
00796         }
00797         
00798         Network::InformationTexts::const_iterator Network::EndInformationTexts() const
00799         {
00800                 return _informationTexts.end();
00801         }
00802 
00803 
00804         Network::NamesList  Network::GetInPortsConnectedTo( const std::string & producer ) const
00805         {               
00806                 OutPortBase & out = GetOutPortByCompleteName( producer );
00807                 NamesList consumers;
00808 
00809                 if(!out.HasConnections())
00810                         return consumers;
00811 
00812                 OutPortBase::InPortsList::iterator it;
00813                 for(it=out.BeginVisuallyConnectedInPorts(); it!=out.EndVisuallyConnectedInPorts(); it++)
00814                 {
00815                         std::string completeName(GetNetworkId((*it)->GetProcessing()));
00816                         completeName += ".";
00817                         completeName += (*it)->GetName();
00818                         consumers.push_back(completeName);
00819                 }
00820                 return consumers;
00821         }
00822 
00823         Network::NamesList  Network::GetInControlsConnectedTo( const std::string & producer ) const
00824         {               
00825                 OutControlBase & out = GetOutControlByCompleteName( producer );
00826                 NamesList consumers;
00827 
00828                 std::list<InControlBase*>::iterator it;
00829                 for(it=out.BeginInControlsConnected();
00830                     it!=out.EndInControlsConnected();
00831                     it++)
00832                 {
00833                         std::string completeName(GetNetworkId((*it)->GetProcessing()));
00834                         completeName += ".";
00835                         completeName += (*it)->GetName();
00836                         consumers.push_back(completeName);
00837                 }
00838                 return consumers;
00839         }
00840 
00841         Network::InPortsList Network::GetInPortsConnectedTo( OutPortBase & producer ) const
00842         {               
00843                 InPortsList consumers;
00844                 OutPortBase::InPortsList::iterator it;
00845                 for(it=producer.BeginVisuallyConnectedInPorts(); it!=producer.EndVisuallyConnectedInPorts(); it++)
00846                         consumers.push_back(*it);
00847                 return consumers;
00848         }
00849 
00850         const std::string &  Network::GetNetworkId(const Processing * proc) const
00851         {
00852                 ProcessingsMap::const_iterator it;
00853                 for(it=BeginProcessings(); it!=EndProcessings(); it++)
00854                         if(it->second == proc )
00855                                 return it->first;
00856 
00857                 CLAM_ASSERT(false, "Trying to get a network id from a processing not present in it");
00858                 throw 0; // To avoid warning message
00859         }
00860 
00861         bool Network::RenameProcessing( const std::string & oldName, const std::string & newName )
00862         {
00863                 if (oldName==newName) return true;
00864                 if( _processings.find( newName ) != _processings.end() ) // newName is being used
00865                         return false;
00866                 ProcessingsMap::iterator it = _processings.find( oldName );
00867                 Processing * proc = it->second;
00868                 _processings.erase( it );
00869                 _processings.insert( ProcessingsMap::value_type( newName, proc ) );
00870                 return true;
00871         }
00872 
00873         bool Network::IsReady() const
00874         {
00875                 if (IsEmpty()) return false;
00876                 if (HasMisconfiguredProcessings()) return false;
00877                 if (HasUnconnectedInPorts()) return false;
00878                 return true;
00879         }
00880 
00881         bool Network::IsEmpty() const
00882         {
00883                 return _processings.empty();
00884         }
00885 
00886         bool Network::HasMisconfiguredProcessings() const
00887         {
00888                 ProcessingsMap::const_iterator it;
00889                 for(it=BeginProcessings(); it!=EndProcessings(); it++)
00890                         if(!it->second->IsConfigured())
00891                                 return true;
00892                 return false;
00893         }
00894 
00895         bool Network::HasUnconnectedInPorts() const
00896         {
00897                 for (ProcessingsMap::const_iterator it=BeginProcessings(); it!=EndProcessings(); it++)
00898                 {
00899                         Processing * proc = it->second;
00900                         unsigned nInPorts = proc->GetNInPorts();
00901                         for (unsigned i = 0; i<nInPorts; i++)
00902                         {
00903                                 InPortBase & inPort = proc->GetInPort(i);
00904                                 if (not inPort.GetVisuallyConnectedOutPort())
00905                                         return true;
00906                         }
00907                 }
00908                 return false;
00909         }
00910         std::string Network::GetUnconnectedInPorts() const
00911         {
00912                 std::string result;
00913                 for (ProcessingsMap::const_iterator it=BeginProcessings(); it!=EndProcessings(); it++)
00914                 {
00915                         Processing * proc = it->second;
00916                         unsigned nInPorts = proc->GetNInPorts();
00917                         for (unsigned i = 0; i<nInPorts; i++)
00918                         {
00919                                 InPortBase & inPort = proc->GetInPort(i);
00920                                 if (not inPort.GetVisuallyConnectedOutPort())
00921                                         result+= it->first + "." + inPort.GetName() + "\n";
00922                         }
00923                 }
00924                 return result;
00925         }
00926 
00927         bool Network::HasSyncSource() const
00928         {
00929                 ProcessingsMap::const_iterator it;
00930                 for(it=BeginProcessings(); it!=EndProcessings(); it++)
00931                         if(it->second->IsSyncSource())
00932                                 return true;
00933                 return false;
00934         }
00935 
00936         bool Network::SupportsVariableAudioSize() const
00937         {
00938             ProcessingsMap::const_iterator it;
00939                 for(it=BeginProcessings(); it!=EndProcessings(); it++)
00940                         if(!it->second->SupportsVariableAudioSize())
00941                                 return false;
00942                 return true;
00943     }
00944 
00945         // TODO: Test GetConfigurationErrors
00946         std::string Network::GetConfigurationErrors() const
00947         {
00948                 std::ostringstream errorMessage;
00949                 ProcessingsMap::const_iterator it;
00950                 for(it=BeginProcessings(); it!=EndProcessings(); it++)
00951                 {
00952                         if(it->second->IsConfigured()) continue;
00953                         errorMessage << "* Processing '" <<  it->first  << "' is misconfigured:\n";
00954                         errorMessage << it->second->GetConfigErrorMessage() << std::endl;
00955                 }
00956 
00957                 return errorMessage.str();
00958         }
00959 
00960         bool Network::BrokenConnection( const std::string & producer, const std::string & consumer )
00961         {
00962                 bool brokenConnection = false;
00963 
00964                 Processing& prod = GetProcessing( GetProcessingIdentifier(producer) );
00965                 Processing& cons = GetProcessing( GetProcessingIdentifier(consumer) );
00966 
00967                 if (!prod.HasOutPort(GetConnectorIdentifier(producer)))
00968                          brokenConnection = true;
00969 
00970                 if (!cons.HasInPort(GetConnectorIdentifier(consumer)))
00971                          brokenConnection = true;
00972 
00973                 if (brokenConnection)
00974                         _brokenConnections.push_back(producer + " -> " + consumer);
00975 
00976                 return brokenConnection;
00977         } 
00978 
00979         Network::ConnectionState Network::GetConnectionReport() const
00980         {
00981                 std::ostringstream os;
00982                 std::copy(_brokenConnections.begin(), _brokenConnections.end(), 
00983                                   std::ostream_iterator<std::string> (os, "<br/> "));
00984 
00985                 return std::make_pair(_brokenConnections.size() != 0, os.str());
00986         }
00987 
00988         void Network::ResetConnectionReport()
00989         {
00990                 _brokenConnections.clear();
00991         }
00992 }
00993 
Generated by  doxygen 1.6.3