| @@ -53,6 +53,10 @@ public: | |||
| _length = _channels = 0; | |||
| } | |||
| virtual ~Audio_File ( ) | |||
| { | |||
| } | |||
| static Audio_File *from_file ( const char *filename ); | |||
| Peaks const * peaks ( ) { return _peaks; } | |||
| @@ -103,22 +103,31 @@ Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels | |||
| bool | |||
| Audio_File_SF::open ( void ) | |||
| { | |||
| SF_INFO si; | |||
| assert( _in == NULL ); | |||
| /* SF_INFO si; */ | |||
| memset( &si, 0, sizeof( si ) ); | |||
| /* memset( &si, 0, sizeof( si ) ); */ | |||
| if ( ! ( _in = sf_open( _filename, SFM_READ, &si ) ) ) | |||
| return false; | |||
| /* if ( ! ( _in = sf_open( _filename, SFM_READ, &si ) ) ) */ | |||
| /* return false; */ | |||
| _current_read = 0; | |||
| _length = si.frames; | |||
| _samplerate = si.samplerate; | |||
| _channels = si.channels; | |||
| seek( 0 ); | |||
| // seek( 0 ); | |||
| return true; | |||
| } | |||
| void | |||
| Audio_File_SF::close ( void ) | |||
| { | |||
| // sf_close( _in ); | |||
| if ( _in ) | |||
| sf_close( _in ); | |||
| _in = NULL; | |||
| } | |||
| void | |||
| @@ -36,6 +36,12 @@ public: | |||
| static Audio_File_SF *from_file ( const char *filename ); | |||
| static Audio_File_SF *create ( const char *filename, nframes_t samplerate, int channels, const char *format ); | |||
| ~Audio_File_SF ( ) | |||
| { | |||
| /* stupid C++ */ | |||
| close(); | |||
| } | |||
| bool open ( void ); | |||
| void close ( void ); | |||
| void seek ( nframes_t offset ); | |||
| @@ -78,11 +78,6 @@ Disk_Stream::Disk_Stream ( Track_Header *th, float frame_rate, nframes_t nframes | |||
| Disk_Stream::~Disk_Stream ( ) | |||
| { | |||
| /* stop the IO thread */ | |||
| _terminate = true; | |||
| pthread_join( _thread, NULL ); | |||
| /* it isn't safe to do all this with the RT thread running */ | |||
| engine->lock(); | |||
| @@ -96,6 +91,14 @@ Disk_Stream::~Disk_Stream ( ) | |||
| engine->unlock(); | |||
| } | |||
| /** stop the IO thread, block until it finishes. */ | |||
| void | |||
| Disk_Stream::shutdown ( void ) | |||
| { | |||
| _terminate = true; | |||
| pthread_join( _thread, NULL ); | |||
| } | |||
| Audio_Track * | |||
| Disk_Stream::track ( void ) | |||
| { | |||
| @@ -119,12 +122,6 @@ Disk_Stream::resize ( nframes_t nframes ) | |||
| } | |||
| /* void */ | |||
| /* DIsk_Stream::shutdown ( void ) */ | |||
| /* { */ | |||
| /* pthread_join( &_thread, NULL ); */ | |||
| /* } */ | |||
| /* static wrapper */ | |||
| void * | |||
| Disk_Stream::disk_thread ( void *arg ) | |||
| @@ -94,6 +94,7 @@ public: | |||
| /* bool seek_pending ( void ); */ | |||
| void run ( void ); | |||
| void shutdown ( void ); | |||
| virtual nframes_t process ( nframes_t nframes ) = 0; | |||
| @@ -123,15 +123,66 @@ Record_DS::disk_thread ( void ) | |||
| printf( "IO thread terminating.\n" ); | |||
| delete[] cbuf; | |||
| delete[] buf; | |||
| } | |||
| /** begin recording */ | |||
| /* FIXME: we need to make note of the exact frame we were on when recording began */ | |||
| void | |||
| Record_DS::start ( nframes_t frame ) | |||
| { | |||
| /* FIXME: flush buffers here? */ | |||
| if ( _recording ) | |||
| { | |||
| printf( "programming error: attempt to start recording while recording is still in progress\n" ); | |||
| return; | |||
| } | |||
| _af = Audio_File_SF::create( "testing.wav", 48000, channels(), "Wav/24" ); | |||
| _frame = frame; | |||
| run(); | |||
| _recording = true; | |||
| } | |||
| /** finalize the recording process. */ | |||
| void | |||
| Record_DS::stop ( nframes_t frame ) | |||
| { | |||
| if ( ! _recording ) | |||
| { | |||
| printf( "programming error: attempt to stop recording when no recording is being made\n" ); | |||
| return; | |||
| } | |||
| shutdown(); | |||
| /* FIXME: flush buffers here? */ | |||
| delete _af; | |||
| _af = NULL; | |||
| _recording = false; | |||
| printf( "recording finished\n" ); | |||
| } | |||
| /* THREAD: RT */ | |||
| /** take a single block from the ringbuffers and send it out the | |||
| * attached track's ports */ | |||
| /** read from the attached track's ports and stuff the ringbuffers */ | |||
| nframes_t | |||
| Record_DS::process ( nframes_t nframes ) | |||
| { | |||
| if ( ! _recording ) | |||
| return 0; | |||
| const size_t block_size = nframes * sizeof( sample_t ); | |||
| // printf( "process: %lu %lu %lu\n", _frame, _frame + nframes, nframes ); | |||
| @@ -27,6 +27,8 @@ class Audio_File; | |||
| class Record_DS : public Disk_Stream | |||
| { | |||
| volatile bool _recording; | |||
| Audio_File_SF *_af; /* capture file */ | |||
| void write_block ( sample_t *buf, nframes_t nframes ); | |||
| @@ -37,19 +39,17 @@ public: | |||
| Record_DS ( Track_Header *th, float frame_rate, nframes_t nframes, int channels ) : | |||
| Disk_Stream( th, frame_rate, nframes, channels ) | |||
| { | |||
| /* FIXME: we need our semaphore set to 0, no? */ | |||
| _af = Audio_File_SF::create( "testing.wav", 48000, 1, "Wav/24" ); | |||
| sem_destroy( &_blocks ); | |||
| sem_init( &_blocks, 0, 0 ); | |||
| run(); | |||
| _recording = false; | |||
| } | |||
| /* bool seek_pending ( void ); */ | |||
| /* void seek ( nframes_t frame ); */ | |||
| void start ( nframes_t frame ); | |||
| void stop ( nframes_t frame ); | |||
| nframes_t process ( nframes_t nframes ); | |||
| }; | |||
| @@ -19,6 +19,7 @@ | |||
| #include "Track_Header.H" | |||
| #include "Transport.H" | |||
| #include "Playback_DS.H" | |||
| #include "Record_DS.H" | |||
| @@ -59,8 +60,11 @@ Track_Header::cb_button ( Fl_Widget *w ) | |||
| printf( "FIXME: inform mixer here\n" ); | |||
| if ( w == record_button ) | |||
| { | |||
| /* FIXME: wrong place for this! */ | |||
| if ( record_button->value() ) | |||
| record_ds->start( transport.frame ); | |||
| else | |||
| record_ds->stop( transport.frame ); | |||
| } | |||
| else | |||
| if ( w == take_menu ) | |||
| @@ -114,10 +118,14 @@ Track_Header::Track_Header ( int X, int Y, int W, int H, const char *L ) : | |||
| input.push_back( Port( strdup( pname ), Port::Input ) ); | |||
| snprintf( pname, sizeof( pname ), "in-%d", ni++ ); | |||
| input.push_back( Port( strdup( pname ), Port::Input ) ); | |||
| } | |||
| playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), 1 ); | |||
| record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), 1 ); | |||
| record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), 2 ); | |||
| Fl_Group::size( w(), height() ); | |||