/* * copies "header" to a newly allocated data structure */ srmio_data_t srmio_data_header( srmio_data_t src, srmio_error_t *err ) { srmio_data_t dst; assert(src); if( NULL == ( dst = srmio_data_new( err ) )) return NULL; if( src->notes && NULL == ( dst->notes = strdup( src->notes ) ) ){ srmio_error_errno( err, "data notes" ); goto clean1; } if( src->athlete && NULL == ( dst->athlete = strdup( src->athlete ) ) ){ srmio_error_errno( err, "data athlete"); goto clean1; } dst->slope = src->slope; dst->zeropos = src->zeropos; dst->circum = src->circum; return dst; clean1: srmio_data_free(dst); return NULL; }
bool SrmDevice::download( const QDir &tmpdir, QList<DeviceDownloadFile> &files, QString &err) { srmio_error_t serr; struct _srmio_pc_xfer_block_t block; srmio_data_t data( NULL ); srmio_data_t *splitList( NULL ); srmio_data_t *split; int mfirst( -1 ); size_t block_cnt, block_num( 0 ); size_t prog_sum( 0 ), prog_prev( 0 ); size_t chunks_done( 0 ); srmio_time_t splitGap( 72000 ); // 2h - NOTE: we could make this configurable if( ! is_open ){ if( ! open( err ) ) return false; } // fetch preview in case user didn't if( srmio_pc_can_preview(pc) && rideList.size() == 0 ){ if( ! preview( err ) ) return false; } data = srmio_data_new( &serr ); if( ! data ){ err = tr("failed to allocate data handle: %1") .arg(serr.message); goto fail; } if( m_Cancelled ){ err = tr("download cancelled"); goto fail; } if( ! srmio_pc_xfer_start( pc, &serr )){ err = tr("failed to start download: %1") .arg(serr.message); goto fail; } if( ! srmio_pc_xfer_get_blocks( pc, &block_cnt, &serr ) ){ err = tr("failed to get number of data blocks: %1") .arg(serr.message); goto fail1; } for( int i = 0; i < rideList.size(); ++i ){ if( rideList.at(i)->wanted ) prog_sum += rideList.at(i)->work; } while( srmio_pc_xfer_block_next( pc, &block )){ bool wanted = false; struct _srmio_chunk_t chunk; bool is_int; bool is_first; size_t prog_total; if( rideList.empty() ){ wanted = true; } else { for( int i = 0; i < rideList.size(); ++i ){ if( rideList.at(i)->startTime.toTime_t() == block.start / 10 ){ wanted = rideList.at(i)->wanted; break; } } } if( ! wanted ){ emit updateStatus(tr("skipping unselected ride block %1") .arg(block_num +1)); ++block_num; continue; } data->slope = block.slope; data->zeropos = block.zeropos; data->circum = block.circum; if( block.athlete ){ if( data->athlete ) free( data->athlete ); data->athlete = strdup( block.athlete ); } if( ! rideList.empty() ){ prog_total = prog_sum; } else if( block_cnt == 1 ){ prog_total = block.total; } else { prog_total = block_cnt * 1000; } while( srmio_pc_xfer_chunk_next( pc, &chunk, &is_int, &is_first ) ){ if( m_Cancelled ){ err = tr("download cancelled"); goto fail1; } if( chunks_done % 16 == 0 ){ size_t block_done; srmio_pc_xfer_block_progress( pc, &block_done ); if( ! rideList.empty() ){ block_done += prog_prev; } else if( block_cnt == 1 ){ // unchanged } else { block_done = (double)block_num * 1000 + 1000 * block.total / block_done; } emit updateProgress( tr("progress: %1/%2") .arg(block_done) .arg(prog_total)); } if( ! srmio_data_add_chunk( data, &chunk, &serr ) ){ err = tr("adding chunk failed: %1") .arg(serr.message); goto fail1; } ++chunks_done; /* finish previous marker */ if( mfirst >= 0 && ( ! is_int || is_first ) ) if( ! srmio_data_add_marker( data, mfirst, data->cused -2, &serr ) ){ err = tr("adding marker failed: %1") .arg(serr.message); goto fail1; } /* start marker */ if( is_first ){ mfirst = (int)data->cused -1; } else if( ! is_int ){ mfirst = -1; } } /* finalize marker at block end */ if( mfirst >= 0 ){ if( ! srmio_data_add_marker( data, mfirst, data->cused -1, &serr ) ){; err = tr("adding marker failed: %1") .arg(serr.message); goto fail1; } mfirst = -1; } if( ! rideList.empty() ) prog_prev += block.total; else prog_prev += 1000; if( block.athlete ) free( block.athlete ); block.athlete = NULL; ++block_num; } if( srmio_pc_xfer_state_success != srmio_pc_xfer_status( pc, &serr ) ){ err = tr( "download failed: %1") .arg(serr.message); goto fail; } if( ! srmio_pc_xfer_finish( pc, &serr ) ){ err = tr( "download failed: %1") .arg(serr.message); goto fail; } emit updateStatus( tr("got %1 records").arg(data->cused) ); if( m_Cancelled ){ err = tr("download cancelled"); goto fail; } if( ! data->cused ){ err = tr("no data available"); goto fail; } splitList = srmio_data_split( data, splitGap, 1000, &serr ); if( ! splitList ){ err = tr("Couldn't split data: %1") .arg(serr.message); goto fail; } for( split = splitList; *split; ++split ){ FILE *fh( NULL ); srmio_time_t stime; srmio_data_t fixed; DeviceDownloadFile file; // skip empty hunks ... shouldn't happen, just to be safe if( ! (*split)->cused ){ continue; } fixed = srmio_data_fixup( *split, &serr ); if( ! fixed ){ err = tr("Couldn't fixup data: %1") .arg(serr.message); goto fail; } // skip empty hunks ... shouldn't happen, just to be safe if( ! fixed->cused ){ srmio_data_free(fixed); continue; } file.extension = "srm"; if (!get_tmpname(tmpdir, file.name, err)) goto fail; if( ! srmio_data_time_start( fixed, &stime, &serr ) ){ srmio_data_free(fixed); err = tr("Couldn't get start time of data: %1") .arg(serr.message); goto fail; } file.startTime.setTime_t( 0.1 * stime ); fh = fopen( file.name.toAscii().constData(), "wb" ); if( ! fh ){ srmio_data_free(fixed); err = tr( "failed to open file %1: %2") .arg(file.name) .arg(strerror(errno)); goto fail; } if( ! srmio_file_srm7_write(fixed, fh, &serr) ){ srmio_data_free(fixed); err = tr("Couldn't write to file %1: %2") .arg(file.name) .arg(serr.message); fclose(fh); goto fail; } files.append(file); fclose( fh ); srmio_data_free(fixed); } for( split = splitList; *split; ++split ) srmio_data_free( *split ); free(splitList); srmio_data_free( data ); return true; fail1: srmio_pc_xfer_finish(pc, NULL); fail: if( data ) srmio_data_free( data ); if( splitList ){ for( split = splitList; *split; ++split ) srmio_data_free( *split ); free(splitList); } close(); return false; }