| @@ -503,7 +503,7 @@ Audio_Region::draw_box( void ) | |||||
| color = fl_color_average( color, sequence()->color(), 0.75f ); | color = fl_color_average( color, sequence()->color(), 0.75f ); | ||||
| if ( this == ((Audio_Sequence*)sequence())->capture() ) | |||||
| if ( this == ((Audio_Sequence*)sequence())->capture_region() ) | |||||
| { | { | ||||
| color = FL_RED; | color = FL_RED; | ||||
| } | } | ||||
| @@ -54,9 +54,9 @@ Audio_Sequence::~Audio_Sequence ( ) | |||||
| const Audio_Region * | const Audio_Region * | ||||
| Audio_Sequence::capture ( void ) const | |||||
| Audio_Sequence::capture_region ( void ) const | |||||
| { | { | ||||
| return track()->capture(); | |||||
| return track()->capture_region(); | |||||
| } | } | ||||
| void | void | ||||
| @@ -66,7 +66,7 @@ public: | |||||
| void dump ( void ); | void dump ( void ); | ||||
| void remove_selected ( void ); | void remove_selected ( void ); | ||||
| const Audio_Region *capture ( void ) const; | |||||
| const Audio_Region *capture_region ( void ) const; | |||||
| nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ); | nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ); | ||||
| @@ -209,6 +209,7 @@ Audio_Region::write ( nframes_t nframes ) | |||||
| return nframes; | return nframes; | ||||
| } | } | ||||
| /* THREAD: IO */ | |||||
| /** finalize region capture. Assumes that this *is* a captured region | /** finalize region capture. Assumes that this *is* a captured region | ||||
| and that no other regions refer to the same source */ | and that no other regions refer to the same source */ | ||||
| bool | bool | ||||
| @@ -222,8 +223,10 @@ Audio_Region::finalize ( nframes_t frame ) | |||||
| _clip->open(); | _clip->open(); | ||||
| /* FIXME: should we attempt to truncate the file? */ | /* FIXME: should we attempt to truncate the file? */ | ||||
| Fl::lock(); | |||||
| redraw(); | redraw(); | ||||
| Fl::awake(); | |||||
| Fl::unlock(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -122,7 +122,7 @@ Disk_Stream::base_flush ( bool is_output ) | |||||
| } | } | ||||
| /** stop the IO thread, block until it finishes. */ | |||||
| /** stop the IO thread. */ | |||||
| void | void | ||||
| Disk_Stream::shutdown ( void ) | Disk_Stream::shutdown ( void ) | ||||
| { | { | ||||
| @@ -132,11 +132,15 @@ Disk_Stream::shutdown ( void ) | |||||
| block_processed(); | block_processed(); | ||||
| if ( _thread ) | if ( _thread ) | ||||
| pthread_join( _thread, NULL ); | |||||
| pthread_detach( _thread ); | |||||
| _thread = 0; | |||||
| /* we must block until the thread returns, because it might | |||||
| * still have data left to process in its buffers--and we | |||||
| * don't want to delete any of the datastructures it's using | |||||
| * until it finishes with them. */ | |||||
| // pthread_join( _thread, NULL ); | |||||
| _terminate = false; | |||||
| _thread = 0; | |||||
| } | } | ||||
| Track * | Track * | ||||
| @@ -196,6 +196,8 @@ Playback_DS::disk_thread ( void ) | |||||
| #ifndef AVOID_UNNECESSARY_COPYING | #ifndef AVOID_UNNECESSARY_COPYING | ||||
| delete[] cbuf; | delete[] cbuf; | ||||
| #endif | #endif | ||||
| _terminate = false; | |||||
| } | } | ||||
| /* THREAD: RT */ | /* THREAD: RT */ | ||||
| @@ -31,6 +31,15 @@ | |||||
| #include "util/debug.h" | #include "util/debug.h" | ||||
| const Audio_Region * | |||||
| Record_DS::capture_region ( void ) const | |||||
| { | |||||
| if ( _capture ) | |||||
| return _capture->region; | |||||
| else | |||||
| return NULL; | |||||
| } | |||||
| /* THREAD: IO */ | /* THREAD: IO */ | ||||
| /** write /nframes/ from buf to the capture file of the attached track */ | /** write /nframes/ from buf to the capture file of the attached track */ | ||||
| void | void | ||||
| @@ -43,7 +52,7 @@ Record_DS::write_block ( sample_t *buf, nframes_t nframes ) | |||||
| // timeline->wrlock(); | // timeline->wrlock(); | ||||
| track()->write( buf, nframes ); | |||||
| track()->write( _capture, buf, nframes ); | |||||
| _frames_written += nframes; | _frames_written += nframes; | ||||
| @@ -181,6 +190,14 @@ Record_DS::disk_thread ( void ) | |||||
| #ifndef AVOID_UNNECESSARY_COPYING | #ifndef AVOID_UNNECESSARY_COPYING | ||||
| delete[] cbuf; | delete[] cbuf; | ||||
| #endif | #endif | ||||
| /* now finalize the recording */ | |||||
| track()->finalize( _capture, _stop_frame ); | |||||
| delete _capture; | |||||
| _capture = NULL; | |||||
| _terminate = false; | |||||
| } | } | ||||
| @@ -200,7 +217,9 @@ Record_DS::start ( nframes_t frame ) | |||||
| _frame = frame; | _frame = frame; | ||||
| track()->record( frame ); | |||||
| _capture = new Track::Capture; | |||||
| track()->record( _capture, frame ); | |||||
| run(); | run(); | ||||
| @@ -224,8 +243,6 @@ Record_DS::stop ( nframes_t frame ) | |||||
| shutdown(); | shutdown(); | ||||
| track()->stop( frame ); | |||||
| DMESSAGE( "recording finished" ); | DMESSAGE( "recording finished" ); | ||||
| } | } | ||||
| @@ -24,6 +24,7 @@ | |||||
| #include "Audio_File_SF.H" | #include "Audio_File_SF.H" | ||||
| class Audio_File; | class Audio_File; | ||||
| class Peak_Writer; | class Peak_Writer; | ||||
| class Track::Capture; | |||||
| class Record_DS : public Disk_Stream | class Record_DS : public Disk_Stream | ||||
| { | { | ||||
| @@ -32,6 +33,7 @@ class Record_DS : public Disk_Stream | |||||
| Record_DS ( const Record_DS &rhs ); | Record_DS ( const Record_DS &rhs ); | ||||
| Record_DS & operator= ( const Record_DS &rhs ); | Record_DS & operator= ( const Record_DS &rhs ); | ||||
| Track::Capture *_capture; | |||||
| nframes_t _frames_written; | nframes_t _frames_written; | ||||
| volatile nframes_t _stop_frame; | volatile nframes_t _stop_frame; | ||||
| @@ -53,6 +55,7 @@ public: | |||||
| sem_destroy( &_blocks ); | sem_destroy( &_blocks ); | ||||
| sem_init( &_blocks, 0, 0 ); | sem_init( &_blocks, 0, 0 ); | ||||
| _capture = NULL; | |||||
| _recording = false; | _recording = false; | ||||
| _stop_frame = -1; | _stop_frame = -1; | ||||
| _frames_written = 0; | _frames_written = 0; | ||||
| @@ -60,6 +63,7 @@ public: | |||||
| /* bool seek_pending ( void ); */ | /* bool seek_pending ( void ); */ | ||||
| /* void seek ( nframes_t frame ); */ | /* void seek ( nframes_t frame ); */ | ||||
| const Audio_Region * capture_region ( void ) const; | |||||
| void start ( nframes_t frame ); | void start ( nframes_t frame ); | ||||
| void stop ( nframes_t frame ); | void stop ( nframes_t frame ); | ||||
| @@ -34,12 +34,14 @@ Timeline::record ( void ) | |||||
| Loggable::block_start(); | Loggable::block_start(); | ||||
| nframes_t frame = transport->frame; | |||||
| for ( int i = tracks->children(); i-- ; ) | for ( int i = tracks->children(); i-- ; ) | ||||
| { | { | ||||
| Track *t = (Track*)tracks->child( i ); | Track *t = (Track*)tracks->child( i ); | ||||
| if ( t->armed() && t->record_ds ) | if ( t->armed() && t->record_ds ) | ||||
| t->record_ds->start( transport->frame ); | |||||
| t->record_ds->start( frame ); | |||||
| } | } | ||||
| deactivate(); | deactivate(); | ||||
| @@ -29,6 +29,15 @@ | |||||
| /* Engine */ | /* Engine */ | ||||
| /**********/ | /**********/ | ||||
| const Audio_Region * | |||||
| Track::capture_region ( void ) const | |||||
| { | |||||
| if ( record_ds ) | |||||
| return record_ds->capture_region(); | |||||
| else | |||||
| return NULL; | |||||
| } | |||||
| void | void | ||||
| Track::update_port_names ( void ) | Track::update_port_names ( void ) | ||||
| { | { | ||||
| @@ -209,57 +218,47 @@ uuid ( void ) | |||||
| } | } | ||||
| /* THREAD: IO */ | /* THREAD: IO */ | ||||
| /** create capture region and prepare to record */ | /** create capture region and prepare to record */ | ||||
| void | void | ||||
| Track::record ( nframes_t frame ) | |||||
| Track::record ( Capture *c, nframes_t frame ) | |||||
| { | { | ||||
| assert( ! _capture ); | |||||
| assert( ! _capture_af ); | |||||
| char pat[256]; | char pat[256]; | ||||
| snprintf( pat, sizeof( pat ), "%s-%llu", name(), uuid() ); | snprintf( pat, sizeof( pat ), "%s-%llu", name(), uuid() ); | ||||
| c->audio_file = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format ); | |||||
| _capture_af = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format ); | |||||
| if ( ! _capture_af ) | |||||
| { | |||||
| /* ERROR */ | |||||
| } | |||||
| if ( ! c->audio_file ) | |||||
| FATAL( "Could not create file for new capture!" ); | |||||
| /* open it again for reading in the GUI thread */ | /* open it again for reading in the GUI thread */ | ||||
| Audio_File *af = Audio_File::from_file( _capture_af->name() ); | |||||
| Audio_File *af = Audio_File::from_file( c->audio_file->name() ); | |||||
| _capture = new Audio_Region( af, sequence(), frame ); | |||||
| c->region = new Audio_Region( af, sequence(), frame ); | |||||
| _capture->prepare(); | |||||
| c->region->prepare(); | |||||
| } | } | ||||
| /* THREAD: IO */ | /* THREAD: IO */ | ||||
| /** write a block to the (already opened) capture file */ | /** write a block to the (already opened) capture file */ | ||||
| void | void | ||||
| Track::write ( sample_t *buf, nframes_t nframes ) | |||||
| Track::write ( Capture *c, sample_t *buf, nframes_t nframes ) | |||||
| { | { | ||||
| nframes_t l = _capture_af->write( buf, nframes ); | |||||
| nframes_t l = c->audio_file->write( buf, nframes ); | |||||
| _capture->write( l ); | |||||
| c->region->write( l ); | |||||
| } | } | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| /* THREAD: IO */ | /* THREAD: IO */ | ||||
| void | void | ||||
| Track::stop ( nframes_t frame ) | |||||
| Track::finalize ( Capture *c, nframes_t frame ) | |||||
| { | { | ||||
| _capture->finalize( frame ); | |||||
| _capture = NULL; | |||||
| _capture_af->finalize(); | |||||
| c->region->finalize( frame ); | |||||
| c->audio_file->finalize(); | |||||
| delete _capture_af; | |||||
| _capture_af = NULL; | |||||
| delete c->audio_file; | |||||
| } | } | ||||
| @@ -111,8 +111,6 @@ Track::cb_button ( Fl_Widget *w ) | |||||
| void | void | ||||
| Track::init ( void ) | Track::init ( void ) | ||||
| { | { | ||||
| _capture = NULL; | |||||
| _capture_af = NULL; | |||||
| _sequence = NULL; | _sequence = NULL; | ||||
| _name = NULL; | _name = NULL; | ||||
| _selected = false; | _selected = false; | ||||
| @@ -69,6 +69,12 @@ public: | |||||
| static const char *capture_format; | static const char *capture_format; | ||||
| struct Capture | |||||
| { | |||||
| Audio_File *audio_file; | |||||
| Audio_Region *region; | |||||
| }; | |||||
| private: | private: | ||||
| static int _soloing; | static int _soloing; | ||||
| @@ -85,9 +91,6 @@ private: | |||||
| Audio_Sequence *_sequence; | Audio_Sequence *_sequence; | ||||
| Audio_Region *_capture; /* capture region */ | |||||
| Audio_File *_capture_af; /* capture write source */ | |||||
| bool configure_outputs ( int n ); | bool configure_outputs ( int n ); | ||||
| bool configure_inputs ( int n ); | bool configure_inputs ( int n ); | ||||
| @@ -264,14 +267,15 @@ public: | |||||
| int handle ( int m ); | int handle ( int m ); | ||||
| const Audio_Region *capture ( void ) const { return _capture; } | |||||
| /* Engine */ | /* Engine */ | ||||
| const Audio_Region *capture_region ( void ) const; | |||||
| void resize_buffers ( nframes_t nframes ); | void resize_buffers ( nframes_t nframes ); | ||||
| nframes_t process ( nframes_t nframes ); | nframes_t process ( nframes_t nframes ); | ||||
| void seek ( nframes_t frame ); | void seek ( nframes_t frame ); | ||||
| void record ( nframes_t nframes ); | |||||
| void write ( sample_t *buf, nframes_t nframes ); | |||||
| void stop ( nframes_t nframes ); | |||||
| void record ( Capture *c, nframes_t frame ); | |||||
| void write ( Capture *c, sample_t *buf, nframes_t nframes ); | |||||
| void finalize ( Capture *c, nframes_t frame ); | |||||
| }; | }; | ||||