CLAM-Development  1.4.0
Network.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2007 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 
23 #include "Network.hxx"
24 #include "NaiveFlowControl.hxx"
25 #include "NetworkPlayer.hxx"
26 #include <algorithm>
30 #include "ProcessingFactory.hxx"
31 #include "XmlStorageErr.hxx"
32 #ifdef USE_LADSPA //TODO alway include it. move conditional code in LFactory.hxx
33 #include "ProcessingFactory.hxx"
34 #endif
35 #include "ControlSink.hxx"
36 #include "ControlSource.hxx"
37 #include "CLAMVersion.hxx"
38 
39 #include <sstream>
40 #include <algorithm>
41 #include <iterator>
42 
43 
44 namespace CLAM
45 {
47  _name("Unnamed Network"),
48  _flowControl(new NaiveFlowControl),
49  _player(0),
50  _setPasteMode(false)
51  {}
52 
54  {
55  //std::cerr <<" *\t\t\t~NETWORK"<<std::endl;
56  Clear();
57  if (_flowControl) delete _flowControl;
58  if (_player) delete _player;
59  }
60 
61  void Network::StoreOn( Storage & storage) const
62  {
63  XMLAdapter<std::string> strAdapter( _name, "id");
64  storage.Store(strAdapter);
65 
66  std::string version = CLAM::GetVersion();
67  XMLAdapter<std::string> versionAdapter( version, "clamVersion");
68  storage.Store(versionAdapter);
69 
70  if (not _description.empty())
71  {
72  XMLAdapter<Text> descriptionAdapter(_description, "description", true);
73  storage.Store(descriptionAdapter);
74  }
75 
76  ProcessingsMap::const_iterator it;
77  for(it=BeginProcessings();it!=EndProcessings();it++)
78  {
79  Processing * proc = it->second;
80  const std::string & name = it->first;
81  if (!HasSelectionAndContains(name))
82  continue;
83  std::string processingPosition;
84  std::string processingSize;
85  // if exists canvas geometries, store them
86  if (!_processingsGeometries.empty())
87  {
88  Geometry & geometry=_processingsGeometries.find(name)->second;
89  processingPosition=IntsToString (geometry.x, geometry.y);
90  processingSize=IntsToString (geometry.width, geometry.height);
91  }
92  ProcessingDefinitionAdapter procDefinition(proc, name, processingPosition, processingSize);
93  XMLComponentAdapter xmlAdapter(procDefinition, "processing", true);
94  storage.Store(xmlAdapter);
95  }
96 
97  // second iteration to store ports.
98  // XR: maybe it should be all in one iteration but this way
99  // the xml file is clearer.
100 
101  for(it=BeginProcessings();it!=EndProcessings();it++)
102  {
103  const std::string & name = it->first;
104  Processing * proc = it->second;
105 
106  if (!HasSelectionAndContains(name))
107  continue;
108 
109  unsigned nOutPorts = proc->GetNOutPorts();
110  for (unsigned i = 0; i<nOutPorts; i++)
111  {
112  OutPortBase & outport = proc->GetOutPort(i);
113  if (!outport.HasConnections())
114  continue;
115 
116  std::string outPortName = name + "." + outport.GetName();
117  NamesList namesInPorts = GetInPortsConnectedTo(outPortName);
118  NamesList::iterator namesIterator;
119  for(namesIterator=namesInPorts.begin();
120  namesIterator!=namesInPorts.end();
121  namesIterator++)
122  {
123  if (!HasSelectionAndContains(GetProcessingIdentifier(*namesIterator)))
124  continue;
125  ConnectionDefinitionAdapter connectionDefinition( outPortName, *namesIterator );
126  XMLComponentAdapter xmlAdapter(connectionDefinition, "port_connection", true);
127  storage.Store(xmlAdapter);
128  }
129  }
130  }
131 
132  for(it=BeginProcessings();it!=EndProcessings();it++)
133  {
134  const std::string & name = it->first;
135  Processing * proc = it->second;
136 
137  if (!HasSelectionAndContains(name))
138  continue;
139 
140  unsigned nOutControls = proc->GetNOutControls();
141  for (unsigned i = 0; i<nOutControls; i++)
142  {
143  OutControlBase & outControl = proc->GetOutControl(i);
144  std::string outControlName = name+ "." + outControl.GetName();
145  NamesList namesInControls = GetInControlsConnectedTo(outControlName);
146  NamesList::iterator namesIterator;
147  for(namesIterator=namesInControls.begin();
148  namesIterator!=namesInControls.end();
149  namesIterator++)
150  {
151  if (!HasSelectionAndContains(GetProcessingIdentifier(*namesIterator)))
152  continue;
153  ConnectionDefinitionAdapter connectionDefinition( outControlName, *namesIterator );
154  XMLComponentAdapter xmlAdapter(connectionDefinition, "control_connection", true);
155  storage.Store(xmlAdapter);
156  }
157  }
158  }
159 
160  InformationTexts::const_iterator ibIt;
161  for(ibIt=BeginInformationTexts();ibIt!=EndInformationTexts();ibIt++)
162  {
163  InformationTextAdapter infoTextDefinition((*ibIt)->x, (*ibIt)->y, (*ibIt)->text);
164  XMLComponentAdapter xmlAdapter(infoTextDefinition, "information", true);
165  storage.Store(xmlAdapter);
166  }
167 
168  _selectedProcessings.clear();
169  _processingsGeometries.clear();
170  }
171 
172  void Network::LoadFrom( Storage & storage)
173  {
174  typedef std::map <std::string, std::string> NamesMap;
175  NamesMap namesMap;
176  if (!_setPasteMode) Clear();
177  XMLAdapter<std::string> strAdapter( _name, "id");
178  storage.Load(strAdapter);
179  _processingsGeometries.clear();
180 
181  XMLAdapter<Text> descriptionAdapter(_description, "description", true);
182  if(not storage.Load(descriptionAdapter)) _description="";
183 
184  while(1)
185  {
186  ProcessingDefinitionAdapter procDefinition;
187  XMLComponentAdapter xmlAdapter(procDefinition, "processing", true);
188  if (not storage.Load(xmlAdapter)) break;
189 
190  const std::string & definitionName = procDefinition.GetName();
191  CLAM::Processing * processing = procDefinition.GetProcessing();
192  std::string finalName = definitionName;
193  if (_setPasteMode)
194  {
195  finalName = GetUnusedName(definitionName, true);
196  namesMap.insert(std::make_pair(definitionName,finalName));
197  }
198  AddProcessing(finalName, processing, procDefinition.GetConfiguration());
199  // if exists canvas geometries, restore them
200  if (procDefinition.GetPosition()!="" && procDefinition.GetSize()!="")
201  {
202  Geometry geometry;
203  StringPairToInts(procDefinition.GetPosition(),geometry.x,geometry.y);
204  StringPairToInts(procDefinition.GetSize(),geometry.width,geometry.height);
205  _processingsGeometries.insert(ProcessingsGeometriesMap::value_type(finalName,geometry));
206  }
207  }
208 
209  while(1)
210  {
211  ConnectionDefinitionAdapter connectionDefinition;
212  XMLComponentAdapter xmlAdapter(connectionDefinition, "port_connection", true);
213  if (not storage.Load(xmlAdapter)) break;
214  std::string fullOut = connectionDefinition.GetOutName();
215  std::string fullIn = connectionDefinition.GetInName();
216 
217  if (_setPasteMode)
218  {
219  fullOut = namesMap.find(GetProcessingIdentifier(fullOut))->second
220  +"."+GetConnectorIdentifier(fullOut);
221  fullIn = namesMap.find(GetProcessingIdentifier(fullIn))->second
222  +"."+GetConnectorIdentifier(fullIn);
223  }
224 
225  if (BrokenConnection(fullOut, fullIn))
226  continue;
227 
228  if (not ConnectPorts( fullOut, fullIn ))
229  {
230  throw XmlStorageErr(std::string("Unable to connect ports '")+fullOut+"->"+fullIn+".");
231  }
232  }
233 
234  while(1)
235  {
236  ConnectionDefinitionAdapter connectionDefinition;
237  XMLComponentAdapter xmlAdapter(connectionDefinition, "control_connection", true);
238  if (!storage.Load(xmlAdapter)) break;
239  std::string fullOut = connectionDefinition.GetOutName();
240  std::string fullIn = connectionDefinition.GetInName();
241  if (_setPasteMode)
242  {
243  fullOut = namesMap.find(GetProcessingIdentifier(fullOut))->second
244  +"."+GetConnectorIdentifier(fullOut);
245  fullIn = namesMap.find(GetProcessingIdentifier(fullIn))->second
246  +"."+GetConnectorIdentifier(fullIn);
247  }
248  if (not ConnectControls( fullOut, fullIn ))
249  throw XmlStorageErr(std::string("Unable to connect controls '")+fullOut+"->"+fullIn+".");
250  }
251 
252  while(1)
253  {
254  InformationTextAdapter infoTextDefinition;
255  XMLComponentAdapter xmlAdapter(infoTextDefinition, "information", true);
256  if (not storage.Load(xmlAdapter)) break;
257 
258  InformationText *myInformationText=new InformationText();
259  myInformationText->x=infoTextDefinition.GetCoordX();
260  myInformationText->y=infoTextDefinition.GetCoordY();
261  myInformationText->text=infoTextDefinition.GetText();
262 
263  _informationTexts.push_back(myInformationText);
264  }
265 
266  _setPasteMode=false;
267 // OrderSinksAndSources(_processingsGeometries);
268  }
269 
270  bool Network::UpdateSelections (const NamesList & processingsNamesList)
271  {
272  if (!_selectedProcessings.empty() || processingsNamesList.empty())
273  {
274  _selectedProcessings.clear();
275  return true;
276  }
277  NamesList::const_iterator namesIterator;
278  for (namesIterator=processingsNamesList.begin();namesIterator!=processingsNamesList.end();namesIterator++)
279  _selectedProcessings.insert(*namesIterator);
280  return false;
281  }
282 
283  bool Network::HasSelectionAndContains(const std::string & name) const
284  {
285  NamesSet::const_iterator itFindSelected = _selectedProcessings.find(name);
286  if (!_selectedProcessings.empty() && itFindSelected==_selectedProcessings.end())
287  return false;
288  return true;
289  }
290 
291 
293  {
294  //TODO: use the map find!!!!
295  for (ProcessingsGeometriesMap::const_iterator it=_processingsGeometries.begin();it!=_processingsGeometries.end();it++)
296  {
297  if ( &GetProcessing(it->first) == processing )
298  return it->second;
299  }
300  Geometry nullGeometry={0,10000,0,0};
301  return nullGeometry;
302  }
303 
304  const Network::Processings Network::getOrderedProcessings(const std::string & type, bool horizontalOrder) const
305  {
306  std::list <ProcessingAndGeometry> processingsAndGeometries;
307  Processings orderedProcessings;
308  for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
309  {
310  Processing * proc = it->second;
311  const std::string className = proc->GetClassName();
312  if (className!=type)
313  continue;
315  item.processing = proc;
316  item.geometry = findProcessingGeometry(proc);
317  processingsAndGeometries.push_back(item);
318  processingsAndGeometries.sort(horizontalOrder?compareGeometriesUpperXThan:compareGeometriesUpperYThan);
319  }
320 
321  for (std::list<ProcessingAndGeometry>::const_iterator it=processingsAndGeometries.begin();
322  it!=processingsAndGeometries.end();it++)
323  {
324  orderedProcessings.push_back( it->processing );
325  }
326 
327  return orderedProcessings;
328  }
329 
330  const Network::Processings Network::getOrderedProcessingsByAttribute(const std::string & attribute, bool horizontalOrder) const
331  {
332  std::list <ProcessingAndGeometry> processingsAndGeometries;
333  Processings orderedProcessings;
334  for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
335  {
336  Processing * proc = it->second;
337  const std::string className = proc->GetClassName();
338  if (!ProcessingFactory::GetInstance().AttributeExists(className,attribute))
339  continue;
341  item.processing = proc;
342  item.geometry = findProcessingGeometry(proc);
343  processingsAndGeometries.push_back(item);
344  processingsAndGeometries.sort(horizontalOrder?compareGeometriesUpperXThan:compareGeometriesUpperYThan);
345  }
346 
347  for (std::list<ProcessingAndGeometry>::const_iterator it=processingsAndGeometries.begin();
348  it!=processingsAndGeometries.end();it++)
349  {
350  orderedProcessings.push_back( it->processing );
351  }
352 
353  return orderedProcessings;
354  }
355 
357  {
358  std::list <ProcessingAndGeometry> controlSinksAndGeometries;
359  ControlSinks orderedControlSinks;
360  for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
361  {
362  Processing * proc = it->second;
363  const std::string className = proc->GetClassName();
364  if (className!="ControlSink")
365  continue;
367  item.processing = proc;
368  item.geometry = findProcessingGeometry(proc);
369  controlSinksAndGeometries.push_back(item);
370  controlSinksAndGeometries.sort(compareGeometriesUpperXThan);
371  }
372 
373  for (std::list<ProcessingAndGeometry>::const_iterator it=controlSinksAndGeometries.begin();
374  it!=controlSinksAndGeometries.end();it++)
375  {
376  ControlSink* controlSink = dynamic_cast<ControlSink*>(it->processing);
377  CLAM_ASSERT(controlSink, "Expected an AudioSink");
378  orderedControlSinks.push_back( controlSink );
379  }
380 
381  return orderedControlSinks;
382  }
383 
385  {
386  std::list <ProcessingAndGeometry> controlSourcesAndGeometries;
387  ControlSources orderedControlSources;
388  for (ProcessingsMap::const_iterator it=_processings.begin(); it!=_processings.end(); it++)
389  {
390  Processing * proc = it->second;
391  const std::string className = proc->GetClassName();
392  if (className!="ControlSource")
393  continue;
395  item.processing = proc;
396  item.geometry = findProcessingGeometry(proc);
397  controlSourcesAndGeometries.push_back(item);
398  controlSourcesAndGeometries.sort(compareGeometriesUpperXThan);
399  }
400 
401  for (std::list<ProcessingAndGeometry>::const_iterator it=controlSourcesAndGeometries.begin();
402  it!=controlSourcesAndGeometries.end();it++)
403  {
404  ControlSource* controlSource = dynamic_cast<ControlSource*>(it->processing);
405  CLAM_ASSERT(controlSource, "Expected an AudioSink");
406  orderedControlSources.push_back( controlSource );
407  }
408 
409  return orderedControlSources;
410  }
411 
412  bool Network::SetProcessingsGeometries (const ProcessingsGeometriesMap & processingsGeometries)
413  {
414  _processingsGeometries.clear();
415  if (processingsGeometries.empty())
416  return true;
417  _processingsGeometries=processingsGeometries;
418  return false;
419  }
420 
422  {
423  const ProcessingsGeometriesMap copyProcessingsGeometry(_processingsGeometries);
424  _processingsGeometries.clear();
425  return copyProcessingsGeometry;
426  }
427 
429  {
430  return arg1.geometry.y < arg2.geometry.y ;
431  }
432 
434  {
435  return arg1.geometry.x < arg2.geometry.x ;
436  }
437 
438 /* // TODO: use individual geometries loadings/storings??:
439  const Network::Geometry Network::GetAndEraseGeometry(std::string name)
440  {
441  const ProcessingsGeometriesMap::iterator itGeometry =_processingsGeometries.find(name);
442  Geometry geometry=itGeometry->second;
443  if (itGeometry == _processingsGeometries.end())
444  {
445  geometry.width=0;
446  geometry.height=0;
447  return geometry;
448  }
449  _processingsGeometries.erase(name); // if exists, erase geometry from map
450  return geometry;
451  }*/
452 
453  void Network::StringPairToInts(const std::string & geometryInString, int & a, int & b)
454  {
455  a=atoi(geometryInString.substr(0,geometryInString.find(",")).c_str());
456  b=atoi(geometryInString.substr(geometryInString.find(",")+1,geometryInString.length()).c_str());
457  }
458 
459  const std::string Network::IntsToString (const int & a, const int & b) const
460  {
461  std::ostringstream stream;
462  stream<<a<<","<<b;
463  return stream.str();
464  }
465 
466  // flow and player related methods
468  {
469  if (_flowControl) delete _flowControl;
470  _flowControl = flowControl;
471  _flowControl->AttachToNetwork((CLAM::Network*)this);
472  }
474  {
475  if (_player) delete _player;
476  _player = player;
477  _player->SetNetworkBackLink(*(CLAM::Network*)this);
478  _player->Init();
479  }
481  {
482  if (!_player) return 512;
483  return _player->BackendBufferSize();
484  }
486  {
487  if (!_player) return 44100;
488  return _player->BackendSampleRate();
489  }
490 
491 
492  Processing& Network::GetProcessing( const std::string & name ) const
493  {
494  CLAM_ASSERT( HasProcessing(name),
495  ("No processing in the network has the name '"+name+"'.").c_str());
496 
497  ProcessingsMap::const_iterator it = _processings.find( name );
498  return *it->second;
499  }
500 
501  void Network::AddProcessing( const std::string & name, Processing* proc, const ProcessingConfig * config)
502  {
503  if (!IsStopped()) Stop();
504 
505  if (!_processings.insert( ProcessingsMap::value_type( name, proc ) ).second )
506  CLAM_ASSERT(false, "Network::AddProcessing() Trying to add a processing with a repeated name (key)" );
507  proc->SetNetworkBackLink((CLAM::Network*)this);
508  proc->Configure(config ? *config : proc->GetConfig());
509  _flowControl->ProcessingAddedToNetwork(*proc);
510  }
511 
512  Processing & Network::AddProcessing( const std::string & name, const std::string & factoryKey )
513  {
514  Processing * proc = ProcessingFactory::GetInstance().CreateSafe( factoryKey );
515  AddProcessing(name, proc);
516  return *proc;
517  }
518 
519  // returns the name that was used so the same one can be used when calling CreateProcessingController (hack)
520  std::string Network::AddProcessing( const std::string & factoryKey )
521  {
522  std::string name = GetUnusedName( factoryKey );
523  AddProcessing(name, factoryKey );
524  return name;
525  }
526 
527  std::string Network::GetUnusedName( const std::string& prefix, const bool cutOnLastSeparator, const std::string separator ) const
528  {
529  std::string name;
530  std::string newPrefix=prefix;
531  if (cutOnLastSeparator==true)
532  {
533  int lastSeparatorPos=prefix.rfind(separator);
534  if (lastSeparatorPos!=-1)
535  newPrefix=prefix.substr(0,lastSeparatorPos);
536  }
537 
538  for ( int i = 0; i<9999999; i++ )
539  {
540  std::stringstream tmp;
541  tmp << i;
542  name = i? newPrefix + separator + tmp.str() : newPrefix;
543  if (!this->HasProcessing( name ) ) return name;
544  }
545  CLAM_ASSERT(false, "All valid id's for given prefix are exhausted");
546  return "";
547  }
548 
549  void Network::RemoveProcessing ( const std::string & name)
550  {
551  CLAM_ASSERT( _flowControl,
552  "Network::RemoveProcessing() - Network should have an attached flow control at this state.");
553 
554  ProcessingsMap::const_iterator i = _processings.find( name );
555  if(i==_processings.end())
556  {
557  std::string msg("Network::RemoveProcessing() Trying to remove a processing that is not included in the network:");
558  msg += name;
559  CLAM_ASSERT(false, msg.c_str() );
560  }
561  if ( !IsStopped() ) Stop();
562  Processing * proc = i->second;
563  _processings.erase( name );
564 
565  _flowControl->ProcessingRemovedFromNetwork(*proc);
566  delete proc;
567  }
568 
569  bool Network::HasProcessing( const std::string& name ) const
570  {
571  ProcessingsMap::const_iterator i = _processings.find( name );
572  return i!=_processings.end();
573  }
574 
575  bool Network::ConfigureProcessing( const std::string & name, const ProcessingConfig & newConfig )
576  {
577  ProcessingsMap::iterator it = _processings.find( name );
578  CLAM_ASSERT(it!=_processings.end(),"Wrong processing name to configure in a network");
579  Processing * proc = it->second;
580  if ( !IsStopped() ) Stop();
581  bool ok = proc->Configure( newConfig );
582  _flowControl->ProcessingConfigured(*proc);
583  return ok;
584  }
585 
587  {
588  ProcessingsMap::iterator it;
589  for( it=_processings.begin(); it!=_processings.end(); it++)
590  {
591  Processing* proc = it->second;
592  proc->Configure( proc->GetConfig() );
593  }
594  }
595 
596  bool Network::ConnectPorts( const std::string & producer, const std::string & consumer )
597  {
598  _flowControl->NetworkTopologyChanged();
599 
600  OutPortBase & outport = GetOutPortByCompleteName(producer);
601  InPortBase & inport = GetInPortByCompleteName(consumer);
602 
603  if ( outport.IsVisuallyConnectedTo(inport) )
604  return false;
605 
606  if ( !outport.IsConnectableTo(inport) ) //they have different type
607  return false;
608 
609  if( inport.GetVisuallyConnectedOutPort())
610  return false;
611 
612  if (!IsStopped()) Stop();
613 
614  outport.ConnectToIn( inport );
615  return true;
616  }
617 
618  bool Network::ConnectControls( const std::string & producer, const std::string & consumer )
619  {
620  OutControlBase & outcontrol = GetOutControlByCompleteName(producer);
621  InControlBase & incontrol = GetInControlByCompleteName(consumer);
622 
623  if ( outcontrol.IsConnectedTo(incontrol) )
624  return false;
625 
626  if ( !outcontrol.IsLinkable(incontrol) ) //they have different type
627  return false;
628 
629  if (!IsStopped()) Stop();
630 
631  outcontrol.AddLink( incontrol );
632  return true;
633  }
634 
635 
636  bool Network::DisconnectPorts( const std::string & producer, const std::string & consumer)
637  {
638  _flowControl->NetworkTopologyChanged();
639 
640  OutPortBase & outport = GetOutPortByCompleteName(producer);
641  InPortBase & inport = GetInPortByCompleteName(consumer);
642 
643  if ( !outport.IsVisuallyConnectedTo(inport))
644  return false;
645 
646  if (!IsStopped()) Stop();
647 
648  outport.DisconnectFromIn( inport );
649  return true;
650  }
651 
652  bool Network::DisconnectControls( const std::string & producer, const std::string & consumer)
653  {
654  OutControlBase & outcontrol = GetOutControlByCompleteName(producer);
655  InControlBase & incontrol = GetInControlByCompleteName(consumer);
656 
657  if ( !outcontrol.IsConnectedTo( incontrol ))
658  return false;
659 
660  if (!IsStopped()) Stop();
661 
662  outcontrol.RemoveLink( incontrol );
663  return true;
664  }
665 
666  std::string Network::GetConnectorIdentifier( const std::string& str ) const
667  {
668  return str.substr( PositionOfLastIdentifier(str)+1 );
669  }
670 
671  std::string Network::GetProcessingIdentifier( const std::string& str ) const
672  {
673  std::size_t length = PositionOfLastIdentifier(str) - PositionOfProcessingIdentifier(str);
674  return str.substr( PositionOfProcessingIdentifier(str), length);
675  }
676 
677  InPortBase & Network::GetInPortByCompleteName( const std::string & name ) const
678  {
680  return proc.GetInPort( GetConnectorIdentifier(name) );
681  }
682 
683  OutPortBase & Network::GetOutPortByCompleteName( const std::string & name ) const
684  {
686  return proc.GetOutPort( GetConnectorIdentifier(name) );
687  }
688 
689  InControlBase & Network::GetInControlByCompleteName( const std::string & name ) const
690  {
692  return proc.GetInControl( GetConnectorIdentifier(name) );
693  }
694 
695  OutControlBase & Network::GetOutControlByCompleteName( const std::string & name ) const
696  {
698  return proc.GetOutControl( GetConnectorIdentifier(name) );
699  }
700 
701  bool Network::IsStopped() const
702  {
703  if (! _player)
704  return true;
705  return _player->IsStopped();
706  }
707 
708  bool Network::IsPlaying() const
709  {
710  if (! _player)
711  return false;
712  return _player->IsPlaying();
713  }
714 
715  bool Network::IsPaused() const
716  {
717  if (! _player)
718  return false;
719  return _player->IsPaused();
720  }
721 
722  bool Network::IsRealTime() const
723  {
724  if (! _player)
725  return false;
726  return _player->IsRealTime();
727  }
728 
730  {
731  ProcessingsMap::iterator it;
732  for (it=BeginProcessings(); it!=EndProcessings(); it++)
733  {
734  if (it->second->IsRunning())
735  {
736  continue;
737  }
738  if (it->second->IsConfigured())
739  {
740  it->second->Start();
741  }
742  else
743  {
744  std::cerr << "Warning: could not start processing for not being Configured: '"
745  << it->first<< "' of class " << it->second->GetClassName() << std::endl;
746  }
747  }
748  if (_player)
749  _player->Start();
750  }
751 
753  {
754  if (_player) _player->Stop();
755  ProcessingsMap::iterator it;
756  for (it=BeginProcessings(); it!=EndProcessings(); it++)
757  if (it->second->IsRunning())
758  it->second->Stop();
759  }
761  {
762  if (_player) _player->Pause();
763  }
764 
765  void Network::Do()
766  {
767  _flowControl->Do();
768  }
769 
771  {
772  if ( !IsStopped() ) Stop();
773 
774  while( !_processings.empty() )
775  {
776  //std::cerr << "REMOVING <"<<_processings.begin()->first<<">"<<std::endl;
777  RemoveProcessing( _processings.begin()->first );
778  }
779  for(unsigned i=0;i<_informationTexts.size();i++)
780  {
781  removeInformationText(_informationTexts[i]);
782  }
783  _informationTexts.clear();
784  }
785 
786  Network::ProcessingsMap::iterator Network::BeginProcessings()
787  {
788  return _processings.begin();
789  }
790 
791  Network::ProcessingsMap::iterator Network::EndProcessings()
792  {
793  return _processings.end();
794  }
795  Network::ProcessingsMap::const_iterator Network::BeginProcessings() const
796  {
797  return _processings.begin();
798  }
799 
800  Network::ProcessingsMap::const_iterator Network::EndProcessings() const
801  {
802  return _processings.end();
803  }
804 
805  // accessors to text boxes
806 
808  {
809  _informationTexts.push_back(informationText);
810  }
811 
813  {
814  InformationTexts::iterator it = find(BeginInformationTexts(), EndInformationTexts(), informationText);
815 
816  if(it!=EndInformationTexts())
817  _informationTexts.erase(it);
818  else
819  std::cerr << "Warning: Information Text Box does not exist.";
820  }
821 
822  Network::InformationTexts::iterator Network::BeginInformationTexts()
823  {
824  return _informationTexts.begin();
825  }
826 
827  Network::InformationTexts::iterator Network::EndInformationTexts()
828  {
829  return _informationTexts.end();
830  }
831 
832  Network::InformationTexts::const_iterator Network::BeginInformationTexts() const
833  {
834  return _informationTexts.begin();
835  }
836 
837  Network::InformationTexts::const_iterator Network::EndInformationTexts() const
838  {
839  return _informationTexts.end();
840  }
841 
842 
843  Network::NamesList Network::GetInPortsConnectedTo( const std::string & producer ) const
844  {
845  OutPortBase & out = GetOutPortByCompleteName( producer );
846  NamesList consumers;
847 
848  if(!out.HasConnections())
849  return consumers;
850 
851  OutPortBase::InPortsList::iterator it;
852  for(it=out.BeginVisuallyConnectedInPorts(); it!=out.EndVisuallyConnectedInPorts(); it++)
853  {
854  std::string completeName(GetNetworkId((*it)->GetProcessing()));
855  completeName += ".";
856  completeName += (*it)->GetName();
857  consumers.push_back(completeName);
858  }
859  return consumers;
860  }
861 
862  Network::NamesList Network::GetInControlsConnectedTo( const std::string & producer ) const
863  {
864  OutControlBase & out = GetOutControlByCompleteName( producer );
865  NamesList consumers;
866 
867  std::list<InControlBase*>::iterator it;
868  for(it=out.BeginInControlsConnected();
869  it!=out.EndInControlsConnected();
870  it++)
871  {
872  std::string completeName(GetNetworkId((*it)->GetProcessing()));
873  completeName += ".";
874  completeName += (*it)->GetName();
875  consumers.push_back(completeName);
876  }
877  return consumers;
878  }
879 
881  {
882  InPortsList consumers;
883  OutPortBase::InPortsList::iterator it;
884  for(it=producer.BeginVisuallyConnectedInPorts(); it!=producer.EndVisuallyConnectedInPorts(); it++)
885  consumers.push_back(*it);
886  return consumers;
887  }
888 
889  const std::string & Network::GetNetworkId(const Processing * proc) const
890  {
891  ProcessingsMap::const_iterator it;
892  for(it=BeginProcessings(); it!=EndProcessings(); it++)
893  if(it->second == proc )
894  return it->first;
895 
896  CLAM_ASSERT(false, "Trying to get a network id from a processing not present in it");
897  throw 0; // To avoid warning message
898  }
899 
900  bool Network::RenameProcessing( const std::string & oldName, const std::string & newName )
901  {
902  if (oldName==newName) return true;
903  if( _processings.find( newName ) != _processings.end() ) // newName is being used
904  return false;
905  ProcessingsMap::iterator it = _processings.find( oldName );
906  Processing * proc = it->second;
907  _processings.erase( it );
908  _processings.insert( ProcessingsMap::value_type( newName, proc ) );
909  return true;
910  }
911 
912  bool Network::IsReady() const
913  {
914  if (IsEmpty()) return false;
915  if (HasMisconfiguredProcessings()) return false;
916  if (HasUnconnectedInPorts()) return false;
917  return true;
918  }
919 
920  bool Network::IsEmpty() const
921  {
922  return _processings.empty();
923  }
924 
926  {
927  ProcessingsMap::const_iterator it;
928  for(it=BeginProcessings(); it!=EndProcessings(); it++)
929  if(!it->second->IsConfigured())
930  return true;
931  return false;
932  }
933 
935  {
936  for (ProcessingsMap::const_iterator it=BeginProcessings(); it!=EndProcessings(); it++)
937  {
938  Processing * proc = it->second;
939  unsigned nInPorts = proc->GetNInPorts();
940  for (unsigned i = 0; i<nInPorts; i++)
941  {
942  InPortBase & inPort = proc->GetInPort(i);
943  if (not inPort.GetVisuallyConnectedOutPort())
944  return true;
945  }
946  }
947  return false;
948  }
949  std::string Network::GetUnconnectedInPorts() const
950  {
951  std::string result;
952  for (ProcessingsMap::const_iterator it=BeginProcessings(); it!=EndProcessings(); it++)
953  {
954  Processing * proc = it->second;
955  unsigned nInPorts = proc->GetNInPorts();
956  for (unsigned i = 0; i<nInPorts; i++)
957  {
958  InPortBase & inPort = proc->GetInPort(i);
959  if (not inPort.GetVisuallyConnectedOutPort())
960  result+= it->first + "." + inPort.GetName() + "\n";
961  }
962  }
963  return result;
964  }
965 
967  {
968  ProcessingsMap::const_iterator it;
969  for(it=BeginProcessings(); it!=EndProcessings(); it++)
970  if(it->second->IsSyncSource())
971  return true;
972  return false;
973  }
974 
976  {
977  ProcessingsMap::const_iterator it;
978  for(it=BeginProcessings(); it!=EndProcessings(); it++)
979  if(!it->second->SupportsVariableAudioSize())
980  return false;
981  return true;
982  }
983 
984  // TODO: Test GetConfigurationErrors
986  {
987  std::ostringstream errorMessage;
988  ProcessingsMap::const_iterator it;
989  for(it=BeginProcessings(); it!=EndProcessings(); it++)
990  {
991  if(it->second->IsConfigured()) continue;
992  errorMessage << "* Processing '" << it->first << "' is misconfigured:\n";
993  errorMessage << it->second->GetConfigErrorMessage() << std::endl;
994  }
995 
996  return errorMessage.str();
997  }
998 
999  bool Network::BrokenConnection( const std::string & producer, const std::string & consumer )
1000  {
1001  bool brokenConnection = false;
1002 
1003  Processing& prod = GetProcessing( GetProcessingIdentifier(producer) );
1004  Processing& cons = GetProcessing( GetProcessingIdentifier(consumer) );
1005 
1006  if (!prod.HasOutPort(GetConnectorIdentifier(producer)))
1007  brokenConnection = true;
1008 
1009  if (!cons.HasInPort(GetConnectorIdentifier(consumer)))
1010  brokenConnection = true;
1011 
1012  if (brokenConnection)
1013  _brokenConnections.push_back(producer + " -> " + consumer);
1014 
1015  return brokenConnection;
1016  }
1017 
1019  {
1020  std::ostringstream os;
1021  std::copy(_brokenConnections.begin(), _brokenConnections.end(),
1022  std::ostream_iterator<std::string> (os, "<br/> "));
1023 
1024  return std::make_pair(_brokenConnections.size() != 0, os.str());
1025  }
1026 
1028  {
1029  _brokenConnections.clear();
1030  }
1031 }
1032