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