CLAM-Development  1.3
OutPort.hxx
Go to the documentation of this file.
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 =  &in;
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