|
libGDF
|
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 }