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