libGDF
Writer.cpp
00001 //
00002 // This file is part of libGDF.
00003 //
00004 // libGDF is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser General Public License as
00006 // published by the Free Software Foundation, either version 3 of
00007 // the License, or (at your option) any later version.
00008 //
00009 // libGDF is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with libGDF.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // Copyright 2010 Martin Billinger
00018 
00019 #include "GDF/Writer.h"
00020 #include "GDF/Exceptions.h"
00021 #include "GDF/Record.h"
00022 #include "GDF/tools.h"
00023 #include <iostream>
00024 
00025 namespace gdf
00026 {
00027     Writer::Writer( ) : m_recbuf( &m_header ), m_eventbuffer( NULL )
00028     {
00029         m_eventbuffermemory = writer_ev_file;
00030         setMaxFullRecords( 0 );
00031         m_recbuf.registerRecordFullCallback( this );
00032     }
00033 
00034     //===================================================================================================
00035     //===================================================================================================
00036 
00037     Writer::~Writer( )
00038     {
00039         //std::cout << "~Writer( )" << std::endl;
00040         if( m_file.is_open( ) )
00041             close( );
00042     }
00043 
00044     //===================================================================================================
00045     //===================================================================================================
00046 
00047     void Writer::open(const int flags )
00048     {
00049         if( m_file.is_open() )
00050             throw exception::file_open( "" );
00051 
00052         assert( !m_file.is_open() );
00053         m_header.setLock( true );
00054 
00055         bool warn = false;
00056         std::list< std::string > wmsg;
00057         try {
00058             m_header.sanitize( );
00059         } catch( exception::header_issues &e )
00060         {
00061             wmsg = e.warnings;
00062             if( e.errors.size() != 0 )
00063                 throw e;
00064             if( e.warnings.size() != 0 )
00065                 warn = true;
00066         }
00067 
00068         if( !(flags & writer_overwrite) )
00069         {
00070             m_file.open( m_filename.c_str(), std::ios_base::in );
00071             if( !m_file.fail() )
00072             {
00073                 m_header.setLock( false );
00074                 m_file.close( );
00075                 throw exception::file_exists( m_filename );
00076             }
00077         }
00078 
00079         m_file.clear( );
00080 
00081         m_file.open( m_filename.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc );
00082 
00083         if( m_file.fail() )
00084         {
00085             throw std::invalid_argument( "Error opening file for writing." );
00086         }
00087 
00088         m_eventbuffermemory = flags & writer_ev_memory;
00089         if( m_eventbuffermemory )
00090         {
00091             m_eventbuffer.rdbuf( m_evbuf_memory.rdbuf() );
00092             m_evbuf_memory.clear( );
00093         }
00094         else
00095         {
00096             m_evbuf_file.open( (m_filename+".events").c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc );
00097             m_eventbuffer.rdbuf( m_evbuf_file.rdbuf() );
00098         }
00099 
00100         m_recbuf.reset( );
00101         m_num_datarecords = 0;
00102 
00103         m_file << m_header;
00104         m_file.flush( );
00105 
00106         if( warn )
00107             throw exception::header_issues( wmsg );
00108     }
00109 
00110     //===================================================================================================
00111     //===================================================================================================
00112 
00113     void Writer::open( const std::string filename, const int flags )
00114     {
00115         setFilename( filename );
00116         open( flags );
00117     }
00118 
00119     //===================================================================================================
00120     //===================================================================================================
00121 
00122     void Writer::close( )
00123     {
00124         if( !m_file.is_open() )
00125             return;
00126             //throw exception::file_not_open( "" );
00127 
00128         if( !m_eventbuffermemory )
00129             m_evbuf_file.close( );
00130 
00131         m_recbuf.flood( );
00132 
00133         flush( );
00134 
00135         if( !m_eventbuffermemory )
00136         {
00137             m_evbuf_file.open( (m_filename+".events").c_str(), std::ios_base::in | std::ios_base::binary );
00138             m_eventbuffer.rdbuf( m_evbuf_file.rdbuf() );
00139         }
00140 
00141         writeEvents( );
00142 
00143         if( !m_eventbuffermemory )
00144         {
00145             m_evbuf_file.close( );
00146             remove( (m_filename+".events").c_str() );
00147         }
00148 
00149         m_header.setLock( false );
00150 
00151         getMainHeader().set_num_datarecords( m_num_datarecords );
00152 
00153         m_file.seekp( getMainHeader_readonly().num_datarecords.pos );
00154         getMainHeader().num_datarecords.tostream( m_file );
00155 
00156         m_file.close( );
00157     }
00158 
00159     //===================================================================================================
00160     //===================================================================================================
00161 
00162     bool Writer::isOpen( )
00163     {
00164         return m_file.is_open( );
00165     }
00166 
00167     //===================================================================================================
00168     //===================================================================================================
00169 
00170     void Writer::setFilename( std::string filename )
00171     {
00172         m_filename = filename;
00173     }
00174 
00175     //===================================================================================================
00176     //===================================================================================================
00177 
00178     void Writer::setMaxFullRecords( size_t num )
00179     {
00180         max_full_records = num;
00181     }
00182 
00183     //===================================================================================================
00184     //===================================================================================================
00185 
00186     bool Writer::createSignal( size_t index, bool throwexc )
00187     {
00188         return m_header.createSignal( index, throwexc );
00189     }
00190 
00191     //===================================================================================================
00192     //===================================================================================================
00193 
00194     void  Writer::swapSignals( size_t a, size_t b )
00195     {
00196         m_header.swapSignals( a, b );
00197     }
00198 
00199     //===================================================================================================
00200     //===================================================================================================
00201 
00202     void  Writer::relocateSignal( size_t src, size_t dst )
00203     {
00204         m_header.swapSignals( src, dst );
00205     }
00206 
00207     //===================================================================================================
00208     //===================================================================================================
00209 
00210     size_t Writer::getFirstFreeSignalIndex( )
00211     {
00212         return m_header.getFirstFreeSignalIndex( );
00213     }
00214 
00215     //===================================================================================================
00216     //===================================================================================================
00217 
00218     void Writer::blitFromSerialBufferPhys( const double *buf, const std::vector<size_t> &samples_per_channel )
00219     {
00220         if( !m_file.is_open() )
00221             throw exception::file_not_open( "" );
00222 
00223         size_t M = samples_per_channel.size( );
00224         std::vector<size_t> samples_remaining = samples_per_channel;
00225         size_t total_samples_remaining = sum( samples_remaining );
00226 
00227         std::vector<size_t> readpos;
00228         readpos.resize( M );
00229         readpos[0] = 0;
00230         for( size_t i=1; i<M; i++ )
00231             readpos[i] = readpos[i-1] + samples_per_channel[i-1];
00232 
00233         while( total_samples_remaining > 0 )
00234         {
00235             for( size_t i=0; i<M; i++ )
00236             {
00237                 size_t n = std::min( samples_remaining[i], m_recbuf.getNumFreeAlloc( i ) );
00238                 m_recbuf.blitSamplesPhys( i, &buf[readpos[i]], n );
00239                 total_samples_remaining -= n;
00240                 samples_remaining[i] -= n;
00241                 readpos[i] += n;
00242             }
00243         }
00244     }
00245 
00246     //===================================================================================================
00247     //===================================================================================================
00248 
00249     void Writer::addSamplePhys( const size_t channel_idx, const float64 value )
00250     {
00251         if( !m_file.is_open() )
00252             throw exception::file_not_open( "" );
00253         m_recbuf.addSamplePhys( channel_idx, value );
00254     }
00255 
00256     //===================================================================================================
00257     //===================================================================================================
00258 
00259     void Writer::blitSamplesPhys( const size_t channel_idx, const float64 *values, size_t num )
00260     {
00261         if( !m_file.is_open() )
00262             throw exception::file_not_open( "" );
00263         m_recbuf.blitSamplesPhys( channel_idx, values, num );
00264     }
00265 
00266     //===================================================================================================
00267     //===================================================================================================
00268 
00269     void Writer::blitSamplesPhys( const size_t channel_idx, const std::vector<float64> &values )
00270     {
00271         if( !m_file.is_open() )
00272             throw exception::file_not_open( "" );
00273         m_recbuf.blitSamplesPhys( channel_idx, &values[0], values.size() );
00274     }
00275 
00276     //===================================================================================================
00277     //===================================================================================================
00278 
00279     void Writer::addRecord( Record *r )
00280     {
00281         m_recbuf.addRecord( r );
00282     }
00283 
00284     //===================================================================================================
00285     //===================================================================================================
00286 
00287     Record *Writer::acquireRecord( )
00288     {
00289         return m_recbuf.acquireRecord( );
00290     }
00291 
00292     //===================================================================================================
00293     //===================================================================================================
00294 
00295     void Writer::writeRecord( )
00296     {
00297         if( !m_file.is_open() )
00298             throw exception::file_not_open( "" );
00299         Record *r = m_recbuf.getFirstFullRecord( );
00300         if( r != NULL )
00301         {
00302             m_file << *r;
00303             m_recbuf.removeFirstFullRecord( );
00304             m_num_datarecords++;
00305         }
00306     }
00307 
00308     //===================================================================================================
00309     //===================================================================================================
00310 
00311     void Writer::writeRecordDirect( Record *r )
00312     {
00313         m_file << *r;
00314         m_num_datarecords++;
00315     }
00316 
00317     //===================================================================================================
00318     //===================================================================================================
00319 
00320     void Writer::flush( )
00321     {
00322         //std::cout << "Writer::flush( )" << std::endl;
00323         if( !m_file.is_open() )
00324             throw exception::file_not_open( "" );
00325         size_t R = m_recbuf.getNumFullRecords();
00326 
00327         for( size_t r=0; r<R; r++ )
00328             writeRecord( );
00329     }
00330 
00331     //===================================================================================================
00332     //===================================================================================================
00333 
00334     void Writer::setEventMode( uint8 mode )
00335     {
00336         if( m_file.is_open() )
00337             throw exception::file_open( "" );
00338         m_header.getEventHeader( ).setMode( mode );
00339     }
00340 
00341     //===================================================================================================
00342     //===================================================================================================
00343 
00344     void Writer::setEventSamplingRate( float32 fs )
00345     {
00346         if( m_file.is_open() )
00347             throw exception::file_open( "" );
00348         m_header.getEventHeader( ).setSamplingRate( fs );
00349     }
00350 
00351     //===================================================================================================
00352     //===================================================================================================
00353 
00354     void Writer::addEvent( const Mode1Event &ev )
00355     {
00356         if( !m_file.is_open() )
00357             throw exception::file_not_open( "" );
00358         if( m_header.getEventHeader( ).getMode() != 1 )
00359             throw exception::wrong_eventmode( "Expected mode 1" );
00360         m_eventbuffer.write( reinterpret_cast<const char*>(&ev), sizeof(ev) );
00361     }
00362 
00363     //===================================================================================================
00364     //===================================================================================================
00365 
00366     void Writer::addEvent( uint32 position, uint16 type )
00367     {
00368         if( !m_file.is_open() )
00369             throw exception::file_not_open( "" );
00370         Mode1Event ev;
00371         ev.position = position;
00372         ev.type = type;
00373         addEvent( ev );
00374     }
00375 
00376     //===================================================================================================
00377     //===================================================================================================
00378 
00379     void Writer::addEvent( const Mode3Event &ev )
00380     {
00381         if( !m_file.is_open() )
00382             throw exception::file_not_open( "" );
00383         if( m_header.getEventHeader( ).getMode() != 3 )
00384             throw exception::wrong_eventmode( "Expected mode 3" );
00385         m_eventbuffer.write( reinterpret_cast<const char*>(&ev), sizeof(ev) );
00386     }
00387 
00388     //===================================================================================================
00389     //===================================================================================================
00390 
00391     void Writer::addEvent( uint32 position, uint16 type, uint16 channel, uint32 duration )
00392     {
00393         Mode3Event ev;
00394         ev.position = position;
00395         ev.type = type;
00396         ev.channel = channel;
00397         ev.duration = duration;
00398         addEvent( ev );
00399     }
00400 
00401     //===================================================================================================
00402     //===================================================================================================
00403 
00404     void Writer::addEvent( uint32 position, uint16 type, uint16 channel, float32 value )
00405     {
00406         Mode3Event ev;
00407         ev.position = position;
00408         ev.type = type;
00409         ev.channel = channel;
00410         ev.value = value;
00411         addEvent( ev );
00412     }
00413 
00414     //===================================================================================================
00415     //===================================================================================================
00416 
00417     void Writer::writeEvents( )
00418     {
00419         m_header.getEventHeader( ).clear( );
00420         while( !m_eventbuffer.eof() )
00421         {
00422             switch( m_header.getEventHeader( ).getMode() )
00423             {
00424             case 1:
00425                 {
00426                     Mode1Event ev;
00427                     m_eventbuffer.read( reinterpret_cast<char*>(&ev), sizeof(ev) );
00428                     if( !m_eventbuffer.eof( ) )
00429                         m_header.getEventHeader( ).addEvent( ev );
00430                 } break;
00431             case 3:
00432                 {
00433                     Mode3Event ev;
00434                     m_eventbuffer.read( reinterpret_cast<char*>(&ev), sizeof(ev) );
00435                     if( !m_eventbuffer.eof( ) )
00436                         m_header.getEventHeader( ).addEvent( ev );
00437                 } break;
00438             default: throw exception::invalid_eventmode( boost::lexical_cast<std::string>(m_header.getEventHeader( ).getMode()) ); break;
00439             }
00440         }
00441         m_header.getEventHeader( ).toStream( m_file );
00442     }
00443 
00444     //===================================================================================================
00445     //===================================================================================================
00446 
00447     void Writer::triggerRecordFull( Record* /*rec*/ )
00448     {
00449         if( m_recbuf.getNumFullRecords() > max_full_records )
00450         {
00451             flush( );
00452         }
00453     }
00454 
00455 }
 All Data Structures Functions Variables Friends