CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2004 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 #ifndef __OutPort_hxx__ 00023 #define __OutPort_hxx__ 00024 00025 #include "WritingRegion.hxx" 00026 #include <typeinfo> 00027 #include <list> 00028 #include <string> 00029 #include "InPort.hxx" 00030 #include "InPortPublisher.hxx" 00031 00032 namespace CLAM 00033 { 00034 00035 class Processing; 00036 00037 class OutPortBase 00038 { 00039 public: 00040 typedef std::list<InPortBase*> InPortsList; 00041 OutPortBase( const std::string & name = "unnamed out port", Processing * proc = 0 ); 00042 virtual ~OutPortBase(); 00043 const std::string & GetName(); 00044 Processing * GetProcessing(); 00045 InPortsList::iterator BeginVisuallyConnectedInPorts(); 00046 InPortsList::iterator EndVisuallyConnectedInPorts(); 00047 00048 virtual void ConnectToIn(InPortBase& in) = 0; 00049 virtual void DisconnectFromIn(InPortBase & in) = 0; 00050 virtual void DisconnectFromAll()=0; 00051 virtual bool IsVisuallyConnectedTo(InPortBase & in) = 0; 00052 virtual bool IsConnectableTo(InPortBase & ) = 0; 00053 virtual bool CanProduce()=0; 00054 virtual int GetSize()=0; 00055 virtual void SetSize(int newSize)=0; 00056 virtual int GetHop()=0; 00057 virtual void SetHop(int newHop)=0; 00058 bool HasConnections(){ return mVisuallyConnectedPorts.size()!=0; } 00059 virtual void CenterEvenRegions()=0; 00060 void SetPublisher( OutPortBase& publisher); 00061 void UnsetPublisher(); 00062 virtual void UnpublishOutPort() =0; 00063 virtual const std::type_info & GetTypeId() const = 0; 00064 protected: 00065 InPortsList mVisuallyConnectedPorts; 00066 std::string mName; 00067 Processing * mProcessing; 00068 OutPortBase* mPublisher; 00069 }; 00070 00071 00072 template<typename Token> 00073 class OutPort : public OutPortBase 00074 { 00075 typedef OutPort<Token> ProperOutPort; 00076 typedef InPort<Token> ProperInPort; 00077 typedef WritingRegion<Token> ProperWritingRegion; 00078 public: 00079 OutPort( const std::string & name = "unnamed out port", Processing * proc = 0 ); 00080 virtual ~OutPort(); 00081 00082 void DisconnectFromAll(); 00083 void ConnectToIn( InPortBase& in); 00084 void ConnectToConcreteIn(InPort<Token>& in); 00085 void DisconnectFromIn( InPortBase& in); 00086 void DisconnectFromConcreteIn(InPort<Token>& in); 00087 bool IsConnectableTo(InPortBase & in); 00088 bool IsVisuallyConnectedTo(InPortBase & in); 00089 bool IsPhysicallyConnectedToIn(InPort<Token>& ); 00090 InPortPublisher<Token>* GetPublisherContaining(InPort<Token>&); 00091 00092 Token & GetData(int offset=0); 00093 void SetSize( int newSize ); 00094 int GetSize(); 00095 int GetHop(); 00096 void SetHop( int hop ); 00097 void Produce(); 00098 bool CanProduce(); 00099 void CenterEvenRegions(); 00100 00101 static Token & GetLastWrittenData( OutPortBase &, int offset = 0); 00102 void UnpublishOutPort() {} 00103 virtual const std::type_info & GetTypeId() const 00104 { 00105 return typeid(Token); 00106 }; 00107 00108 protected: 00109 bool TryConnectToPublisher( InPortBase & in ); 00110 bool TryConnectToConcreteIn( InPortBase & in ); 00111 00112 bool TryDisconnectFromPublisher( InPortBase & in ); 00113 bool TryDisconnectFromConcreteIn( InPortBase & in ); 00114 00115 Token & GetLastWrittenData( int offset = 0 ); 00116 ProperWritingRegion mRegion; 00117 00118 }; 00119 00120 template<class Token> 00121 OutPort<Token>::OutPort( const std::string & name, Processing * proc ) 00122 : OutPortBase(name,proc) 00123 { 00124 } 00125 00126 template<class Token> 00127 void OutPort<Token>::DisconnectFromAll() 00128 { 00129 InPortsList::iterator it = mVisuallyConnectedPorts.begin(); 00130 for( it=BeginVisuallyConnectedInPorts(); it!=EndVisuallyConnectedInPorts(); it++ ) 00131 { 00132 (*it)->UnAttachRegion(); 00133 } 00134 mVisuallyConnectedPorts.clear(); 00135 } 00136 00137 template<class Token> 00138 OutPort<Token>::~OutPort() 00139 { 00140 DisconnectFromAll(); 00141 } 00142 00143 template<class Token> 00144 bool OutPort<Token>::TryConnectToConcreteIn( InPortBase & in ) 00145 { 00146 try 00147 { 00148 ConnectToConcreteIn( dynamic_cast<ProperInPort&>(in) ); 00149 } 00150 catch(std::bad_cast & e) 00151 { 00152 return false; 00153 } 00154 return true; 00155 } 00156 00157 template<class Token> 00158 bool OutPort<Token>::TryConnectToPublisher( InPortBase & in ) 00159 { 00160 InPortPublisher<Token> * publisher = dynamic_cast< InPortPublisher<Token> *>(&in); 00161 if (!publisher) 00162 return false; 00163 00164 typename InPortPublisher<Token>::ProperInPortsList::iterator it; 00165 mVisuallyConnectedPorts.push_back( &in ); 00166 for( it=publisher->BeginPublishedInPortsList(); it!=publisher->EndPublishedInPortsList(); it++) 00167 (*it)->AttachRegionToOutPort(this, mRegion ); 00168 00169 in.SetVisuallyConnectedOutPort(this); 00170 00171 return true; 00172 } 00173 00174 template<class Token> 00175 void OutPort<Token>::ConnectToIn( InPortBase& in) 00176 { 00177 bool successfullConnection; 00178 successfullConnection = TryConnectToConcreteIn( in ) || TryConnectToPublisher( in ); 00179 CLAM_ASSERT( successfullConnection, 00180 "OutPort<Token>::connectToIn coudn't connect to inPort " 00181 "because was not templatized by the same Token type as outPort" ); 00182 } 00183 00184 template<class Token> 00185 void OutPort<Token>::ConnectToConcreteIn(InPort<Token>& in) 00186 { 00187 CLAM_ASSERT( !in.GetVisuallyConnectedOutPort(), "OutPort<Token>::ConnectToConcreteIn - Trying to connect an inport " 00188 "already connected to another out port" ); 00189 CLAM_ASSERT( !IsVisuallyConnectedTo(in), "OutPort<Token>::ConnectToConcreteIn - Trying to connect an in port " 00190 "already connected to this out port" ); 00191 mVisuallyConnectedPorts.push_back(&in); 00192 in.AttachRegionToOutPort(this, mRegion ); 00193 } 00194 00195 template<class Token> 00196 void OutPort<Token>::DisconnectFromIn( InPortBase& in) 00197 { 00198 bool successfullDisconnection; 00199 successfullDisconnection = TryDisconnectFromConcreteIn( in ) || TryDisconnectFromPublisher( in ); 00200 CLAM_ASSERT( successfullDisconnection, 00201 "OutPort<Token>::DisconnectFromIn coudn't discconnect from inPort " 00202 "because was not templatized by the same Token type as outPort" ); 00203 } 00204 00205 template<class Token> 00206 bool OutPort<Token>::TryDisconnectFromConcreteIn( InPortBase & in ) 00207 { 00208 ProperInPort * concreteIn = dynamic_cast<ProperInPort*>(&in); 00209 if (!concreteIn) 00210 return false; 00211 00212 DisconnectFromConcreteIn( *concreteIn ); 00213 return true; 00214 } 00215 00216 template<class Token> 00217 bool OutPort<Token>::TryDisconnectFromPublisher( InPortBase & in ) 00218 { 00219 InPortPublisher<Token> *publisher = dynamic_cast<InPortPublisher<Token> *>(&in); 00220 if (!publisher) 00221 return false; 00222 00223 typename InPortPublisher<Token>::ProperInPortsList::iterator it; 00224 mVisuallyConnectedPorts.remove( &in ); 00225 for( it=publisher->BeginPublishedInPortsList(); it!=publisher->EndPublishedInPortsList(); it++) 00226 { 00227 if( (*it)->GetVisuallyConnectedOutPort()) 00228 (*it)->UnAttachRegion(); 00229 } 00230 return true; 00231 } 00232 00233 template<class Token> 00234 void OutPort<Token>::DisconnectFromConcreteIn(InPort<Token>& in) 00235 { 00236 CLAM_ASSERT( IsVisuallyConnectedTo(in) || IsPhysicallyConnectedToIn(in), 00237 "OutPort::DisconnectFromConcreteIn() in port is not directly neither physically connected" ); 00238 if (IsVisuallyConnectedTo(in) ) 00239 { 00240 // is directly connected 00241 mVisuallyConnectedPorts.remove(&in); 00242 } 00243 else // then IsPhysicallyConnected() 00244 { 00245 InPortPublisher<Token> *pub = GetPublisherContaining(in); 00246 CLAM_DEBUG_ASSERT(0!=pub, "in port should be published"); 00247 pub->UnPublishInPort(in); 00248 } 00249 in.UnAttachRegion(); 00250 } 00251 00252 template<class Token> 00253 Token & OutPort<Token>::GetData(int offset ) 00254 { 00255 return mRegion[offset]; 00256 } 00257 00258 template<class Token> 00259 void OutPort<Token>::SetSize( int newSize ) 00260 { 00261 mRegion.Size( newSize ); 00262 } 00263 00264 template<class Token> 00265 int OutPort<Token>::GetSize() 00266 { 00267 return mRegion.Size(); 00268 } 00269 00270 template<class Token> 00271 int OutPort<Token>::GetHop() 00272 { 00273 return mRegion.Hop(); 00274 } 00275 00276 template<class Token> 00277 void OutPort<Token>::SetHop( int hop ) 00278 { 00279 mRegion.Hop(hop); 00280 } 00281 00282 template<class Token> 00283 void OutPort<Token>::Produce() 00284 { 00285 mRegion.Produce(); 00286 } 00287 00288 template<class Token> 00289 bool OutPort<Token>::CanProduce() 00290 { 00291 return mRegion.CanProduce(); 00292 } 00293 00294 template<class Token> 00295 bool OutPort<Token>::IsConnectableTo(InPortBase & in) 00296 { 00297 return ( dynamic_cast< ProperInPort* >(&in) || 00298 dynamic_cast< InPortPublisher<Token> *>(&in)); 00299 } 00300 00301 template<class Token> 00302 bool OutPort<Token>::IsPhysicallyConnectedToIn(InPort<Token>& in) 00303 { 00304 if (IsVisuallyConnectedTo(in)) 00305 return true; 00306 00307 return ( 0!=GetPublisherContaining(in) ); 00308 00309 } 00310 00311 template<class Token> 00312 InPortPublisher<Token>* OutPort<Token>::GetPublisherContaining(InPort<Token>& in) 00313 { 00314 00315 InPortPublisher<Token> *result=0; 00316 InPortsList::iterator it; 00317 for( it=mVisuallyConnectedPorts.begin(); it!=mVisuallyConnectedPorts.end(); it++ ) 00318 if ( (*it)->IsPublisherOf(in) ) 00319 { 00320 result=dynamic_cast<InPortPublisher<Token> *>(*it); 00321 CLAM_DEBUG_ASSERT( result, "OutPort::GetPublisherContaining(in) IsPublisher but dynamic_cast failed"); 00322 return result; 00323 } 00324 00325 return 0; 00326 00327 } 00328 00329 template<class Token> 00330 bool OutPort<Token>::IsVisuallyConnectedTo(InPortBase & in) 00331 { 00332 InPortsList::iterator it; 00333 for( it=mVisuallyConnectedPorts.begin(); it!=mVisuallyConnectedPorts.end(); it++ ) 00334 if(*it == &in) return true; 00335 return false; 00336 } 00337 00338 template<class Token> 00339 void OutPort<Token>::CenterEvenRegions() 00340 { 00341 mRegion.CenterEvenRegions(); 00342 } 00343 00344 template<class Token> 00345 Token & OutPort<Token>::GetLastWrittenData( int offset ) 00346 { 00347 CLAM_DEBUG_ASSERT( 0 <= offset, "OutPort<Token>::GetLastWrittenData - Index under bounds" ); 00348 CLAM_DEBUG_ASSERT( offset <= GetSize(), "OutPort<Token>::GetLastWrittenData - Index over bounds" ); 00349 return mRegion.GetLastWrittenData( offset ); 00350 } 00351 00352 template<class Token> 00353 Token & OutPort<Token>::GetLastWrittenData( OutPortBase & out, int offset ) 00354 { 00355 try 00356 { 00357 OutPort<Token>& concreteOut = dynamic_cast< OutPort<Token>& >(out); 00358 return concreteOut.GetLastWrittenData( offset ); 00359 } 00360 catch(...) 00361 { 00362 CLAM_ASSERT( false, "OutPort<Token>::GetLastWrittenData - Passed an outport of wrong type" ); 00363 } 00364 return *(Token *)NULL; 00365 00366 } 00367 00368 } // namespace CLAM 00369 00370 #endif // __OutPort_hxx__ 00371