Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

Connector.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 
00003    Copyright (c) 2000 Tyrell Corporation. All rights reserved.
00004 
00005    Tyrell DarkIce
00006 
00007    File     : Connector.cpp
00008    Version  : $Revision: 1.11 $
00009    Author   : $Author: darkeye $
00010    Location : $Source: /cvsroot/darkice/darkice/src/Connector.cpp,v $
00011    
00012    Copyright notice:
00013 
00014     This program is free software; you can redistribute it and/or
00015     modify it under the terms of the GNU General Public License  
00016     as published by the Free Software Foundation; either version 2
00017     of the License, or (at your option) any later version.
00018    
00019     This program is distributed in the hope that it will be useful,
00020     but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
00022     GNU General Public License for more details.
00023    
00024     You should have received a copy of the GNU General Public License
00025     along with this program; if not, write to the Free Software
00026     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00027 
00028 ------------------------------------------------------------------------------*/
00029 
00030 /* ============================================================ include files */
00031 
00032 #include "Exception.h"
00033 #include "Connector.h"
00034 
00035 
00036 /* ===================================================  local data structures */
00037 
00038 
00039 /* ================================================  local constants & macros */
00040 
00041 /*------------------------------------------------------------------------------
00042  *  File identity
00043  *----------------------------------------------------------------------------*/
00044 static const char fileid[] = "$Id: Connector.cpp,v 1.11 2002/10/20 20:42:56 darkeye Exp $";
00045 
00046 
00047 /* ===============================================  local function prototypes */
00048 
00049 
00050 /* =============================================================  module code */
00051 
00052 /*------------------------------------------------------------------------------
00053  *  Initialize the object
00054  *----------------------------------------------------------------------------*/
00055 void
00056 Connector :: init ( Source          * source )        throw ( Exception )
00057 {
00058     this->source   = source;
00059     this->sinks    = 0;
00060     this->numSinks = 0;
00061 }
00062 
00063 
00064 /*------------------------------------------------------------------------------
00065  *  De-initialize the object
00066  *----------------------------------------------------------------------------*/
00067 void
00068 Connector :: strip ( void )                             throw ( Exception )
00069 {
00070     source = 0;
00071 
00072     if ( sinks ) {
00073         unsigned int    u;
00074 
00075         for ( u = 0; u < numSinks; ++u ) {
00076             sinks[u] = 0;
00077         }
00078 
00079         delete[] sinks;
00080     }
00081 }
00082 
00083 
00084 /*------------------------------------------------------------------------------
00085  *  Constructor
00086  *----------------------------------------------------------------------------*/
00087 Connector :: Connector (    const Connector &   connector ) throw ( Exception )
00088 {
00089     unsigned int    u;
00090 
00091     init( connector.source.get());
00092 
00093     for ( u = 0; u < connector.numSinks; ++u ) {
00094         attach( connector.sinks[u].get() );
00095     }
00096 }
00097 
00098 
00099 /*------------------------------------------------------------------------------
00100  *  Assignment operator
00101  *----------------------------------------------------------------------------*/
00102 Connector &
00103 Connector :: operator= (    const Connector &   connector ) throw ( Exception )
00104 {
00105     if ( this != &connector ) {
00106         unsigned int    u;
00107 
00108         // first free everything
00109         strip();
00110 
00111         // then fill in
00112         init( connector.source.get() );
00113 
00114         for ( u = 0; u < connector.numSinks; ++u ) {
00115             attach( connector.sinks[u].get() );
00116         }
00117     }
00118 
00119     return *this;
00120 }
00121 
00122 
00123 /*------------------------------------------------------------------------------
00124  *  Attach a sink to the connector
00125  *----------------------------------------------------------------------------*/
00126 void
00127 Connector :: attach (   Sink              * sink )          throw ( Exception )
00128 {
00129     if ( !sinks ) {
00130         
00131         numSinks = 1;
00132         sinks    = new Ref<Sink>[1];
00133         sinks[0] = sink;
00134 
00135     } else {
00136 
00137         unsigned int    u;
00138         Ref<Sink>     * s = new Ref<Sink>[numSinks + 1];
00139         
00140         for ( u = 0; u < numSinks; ++u ) {
00141             s[u] = sinks[u].get();
00142         }
00143 
00144         s[numSinks] = sink;
00145         delete[] sinks;
00146         sinks = s;
00147         ++numSinks;
00148     }
00149 }
00150 
00151 
00152 /*------------------------------------------------------------------------------
00153  *  Detach a sink to the connector
00154  *----------------------------------------------------------------------------*/
00155 bool
00156 Connector :: detach (   Sink              * sink )          throw ( Exception )
00157 {
00158     if ( numSinks == 0 ) {
00159         
00160         return false;
00161 
00162     } else if ( numSinks == 1 ) {
00163 
00164         if ( sinks[0].get() != sink ) {
00165             return false;
00166         }
00167 
00168         sinks[0] = 0;
00169         delete[] sinks;
00170         sinks    = 0;
00171         --numSinks;
00172 
00173         return true;
00174 
00175     } else {
00176     
00177         unsigned int    u;
00178         unsigned int    v;
00179         unsigned int    ix;
00180         Ref<Sink>     * s;
00181 
00182         ix = numSinks;
00183         for ( u = 0; u < numSinks; ++u ) {
00184 
00185             if ( sinks[u].get() == sink ) {
00186                 ix = u;
00187                 break;
00188             }
00189         }
00190 
00191         if ( ix == numSinks ) {
00192             return false;
00193         }
00194 
00195         s = new Ref<Sink>[numSinks - 1];
00196         for ( u = 0, v = 0; u < numSinks; ++u ) {
00197 
00198             if ( u != ix ) {
00199                 s[v++] = sinks[u];
00200             }
00201         }
00202 
00203         sinks[ix] = 0;
00204         delete[] sinks;
00205         sinks = s;
00206         --numSinks;
00207 
00208         return true;
00209     }
00210 }
00211 
00212 
00213 /*------------------------------------------------------------------------------
00214  *  Open the source and all the sinks if needed
00215  *----------------------------------------------------------------------------*/
00216 bool
00217 Connector :: open ( void )                          throw ( Exception )
00218 {
00219     unsigned int        u;
00220 
00221     if ( !source->isOpen() ) {
00222         if ( !source->open() ) {
00223             return false;
00224         }
00225     }
00226 
00227     for ( u = 0; u < numSinks; ++u ) {
00228         if ( !sinks[u]->isOpen() ) {
00229             if ( !sinks[u]->open() ) {
00230                 break;
00231             }
00232         }
00233     }
00234 
00235     // if not all could be opened, close those that were
00236     if ( u < numSinks ) {
00237         unsigned int        v;
00238 
00239         for ( v = 0; v < u; ++v ) {
00240             sinks[v]->close();
00241         }
00242 
00243         source->close();
00244 
00245         return false;
00246     }
00247 
00248     return true;
00249 }
00250 
00251 
00252 /*------------------------------------------------------------------------------
00253  *  Transfer some data from the source to the sink
00254  *----------------------------------------------------------------------------*/
00255 unsigned int
00256 Connector :: transfer ( unsigned long       bytes,
00257                         unsigned int        bufSize,
00258                         unsigned int        sec,
00259                         unsigned int        usec )      throw ( Exception )
00260 {
00261     unsigned int    u;
00262     unsigned long   b;
00263 
00264     if ( numSinks == 0 ) {
00265         return 0;
00266     }
00267 
00268     if ( bufSize == 0 ) {
00269         return 0;
00270     }
00271 
00272     unsigned char * buf = new unsigned char[bufSize];
00273 
00274     reportEvent( 6, "Connector :: tranfer, bytes", bytes);
00275     
00276     for ( b = 0; !bytes || b < bytes; ) {
00277         unsigned int    d = 0;
00278         unsigned int    e = 0;
00279 
00280         if ( source->canRead( sec, usec) ) {
00281             d = source->read( buf, bufSize);
00282 
00283             // check for EOF
00284             if ( d == 0 ) {
00285                 reportEvent( 3, "Connector :: transfer, EOF");
00286                 break;
00287             }
00288 
00289             for ( u = 0; u < numSinks; ++u ) {
00290 
00291                 if ( sinks[u]->canWrite( sec, usec) ) {
00292                     try {
00293                         // we expect the sink to accept all data written
00294                         e = sinks[u]->write( buf, d);
00295                     } catch ( Exception     & e ) {
00296                         sinks[u]->close();
00297                         detach( sinks[u].get() );
00298 
00299                         reportEvent( 4,
00300                               "Connector :: transfer, sink removed, remaining",
00301                               numSinks);
00302 
00303                         if ( numSinks == 0 ) {
00304                             reportEvent( 4,
00305                                         "Connector :: transfer, no more sinks");
00306                             delete[] buf;
00307                             return b;
00308                         }
00309                         // with the call to detach, numSinks gets 1 lower,
00310                         // and the next sink comes to sinks[u]
00311                         --u;
00312                     }
00313                 }
00314             }
00315             
00316             b += d;
00317         } else {
00318             reportEvent( 3, "Connector :: transfer, can't read");
00319             break;
00320         }
00321     }
00322 
00323     delete[] buf;
00324     return b;
00325 }
00326 
00327 
00328 /*------------------------------------------------------------------------------
00329  *  Close the source and all the sinks if needed
00330  *----------------------------------------------------------------------------*/
00331 void
00332 Connector :: close ( void )                         throw ( Exception )
00333 {
00334     unsigned int        u;
00335     
00336     source->close();
00337     for ( u = 0; u < numSinks; ++u ) {
00338         sinks[u]->close();
00339     }
00340 }
00341 
00342 
00343 
00344 /*------------------------------------------------------------------------------
00345  
00346   $Source: /cvsroot/darkice/darkice/src/Connector.cpp,v $
00347 
00348   $Log: Connector.cpp,v $
00349   Revision 1.11  2002/10/20 20:42:56  darkeye
00350   cosmetic changes
00351 
00352   Revision 1.10  2002/10/19 12:24:55  darkeye
00353   anged internals so that now each encoding/server connection is
00354   a separate thread
00355 
00356   Revision 1.9  2002/08/02 17:59:17  darkeye
00357   bug fix: when the last server dropped connection, darkice crashed
00358 
00359   Revision 1.8  2002/07/20 16:37:06  darkeye
00360   added fault tolerance in case a server connection is dropped
00361 
00362   Revision 1.7  2002/05/28 12:35:41  darkeye
00363   code cleanup: compiles under gcc-c++ 3.1, using -pedantic option
00364 
00365   Revision 1.6  2001/08/26 20:44:30  darkeye
00366   removed external command-line encoder support
00367   replaced it with a shared-object support for lame with the possibility
00368   of static linkage
00369 
00370   Revision 1.5  2001/08/26 08:43:13  darkeye
00371   added support for unlimited time encoding
00372 
00373   Revision 1.4  2000/11/15 18:37:37  darkeye
00374   changed the transferable number of bytes to unsigned long
00375 
00376   Revision 1.3  2000/11/15 18:08:43  darkeye
00377   added multiple verbosity-level event reporting and verbosity command
00378   line option
00379 
00380   Revision 1.2  2000/11/13 18:46:50  darkeye
00381   added kdoc-style documentation comments
00382 
00383   Revision 1.1.1.1  2000/11/05 10:05:49  darkeye
00384   initial version
00385 
00386   
00387 ------------------------------------------------------------------------------*/
00388 

Generated on Thu Apr 14 13:59:12 2005 for DarkIce by  doxygen 1.4.1