| @@ -1,5 +1,7 @@ | |||
| # -*- mode: makefile; -*- | |||
| all: FL | |||
| FL_SRCS := $(wildcard FL/*.C FL/*.fl) | |||
| FL_SRCS:=$(FL_SRCS:.fl=.C) | |||
| @@ -25,7 +25,7 @@ | |||
| VERSION := 0.5.0 | |||
| all: .config FL Timeline | |||
| all: .config | |||
| .config: configure | |||
| @ ./configure | |||
| @@ -58,10 +58,10 @@ CFLAGS+=-DVERSION=\"$(VERSION)\" \ | |||
| -DDOCUMENT_PATH=\"$(DOCUMENT_PATH)\" \ | |||
| -DPIXMAP_PATH=\"$(PIXMAP_PATH)\" | |||
| CXXFLAGS += $(SNDFILE_CFLAGS) $(LASH_CFLAGS) $(FLTK_CFLAGS) | |||
| CXXFLAGS += $(SNDFILE_CFLAGS) $(LASH_CFLAGS) $(FLTK_CFLAGS) $(JACK_CFLAGS) | |||
| CXXFLAGS := $(CFLAGS) $(CXXFLAGS) | |||
| INCLUDES := -I. -Iutil -IFL | |||
| INCLUDES := -I. -Iutil -IFL -Inonlib | |||
| include scripts/colors | |||
| @@ -81,10 +81,11 @@ endif | |||
| DONE := $(BOLD)$(GREEN)done$(SGR0) | |||
| include FL/makefile.inc | |||
| include nonlib/makefile.inc | |||
| include Timeline/makefile.inc | |||
| SRCS:=$(Timeline_SRCS) $(FL_SRCS) | |||
| OBJS:=$(FL_OBJS) $(Timeline_OBJS) | |||
| SRCS:=$(FL_SRCS) $(nonlib_SRCS) $(Timeline_SRCS) | |||
| OBJS:=$(FL_OBJS) $(nonlib_OBJS) $(Timeline_OBJS) | |||
| # FIXME: isn't there a better way? | |||
| $(OBJS): .config Makefile | |||
| @@ -120,7 +121,7 @@ clean_deps: | |||
| .PHONEY: clean config depend clean_deps | |||
| clean: FL_clean Timeline_clean | |||
| clean: FL_clean nonlib_clean Timeline_clean | |||
| dist: | |||
| git archive --prefix=non-daw-$(VERSION)/ v$(VERSION) | bzip2 > non-daw-$(VERSION).tar.bz2 | |||
| @@ -21,7 +21,6 @@ | |||
| #include "Control_Sequence.H" | |||
| #include "Track.H" | |||
| #include "Engine/Port.H" | |||
| #include "Engine/Engine.H" // for lock() | |||
| @@ -42,7 +41,7 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) | |||
| _track = track; | |||
| _output = new Port( Port::Output, track->name(), track->ncontrols(), "cv" ); | |||
| _output = new JACK::Port( engine->client(), JACK::Port::Output, track->name(), track->ncontrols(), "cv" ); | |||
| if ( track ) | |||
| track->add( this ); | |||
| @@ -111,7 +110,7 @@ Control_Sequence::set ( Log_Entry &e ) | |||
| assert( t ); | |||
| _output = new Port( Port::Output, t->name(), t->ncontrols(), "cv" ); | |||
| _output = new JACK::Port( engine->client(), JACK::Port::Output, t->name(), t->ncontrols(), "cv" ); | |||
| t->add( this ); | |||
| } | |||
| @@ -23,8 +23,9 @@ | |||
| #include "Sequence.H" | |||
| #include "Control_Point.H" | |||
| #include "JACK/Port.H" | |||
| #include "Engine/Port.H" | |||
| // class JACK::Port; | |||
| class Control_Sequence : public Sequence | |||
| { | |||
| @@ -38,7 +39,7 @@ public: | |||
| private: | |||
| Port *_output; | |||
| JACK::Port *_output; | |||
| bool _highlighted; | |||
| @@ -77,7 +78,7 @@ public: | |||
| Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } | |||
| /* Engine */ | |||
| void output ( Port *p ) { _output = p; } | |||
| void output ( JACK::Port *p ) { _output = p; } | |||
| nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes ); | |||
| nframes_t process ( nframes_t nframes ); | |||
| @@ -23,10 +23,7 @@ | |||
| #include "../Timeline.H" // for process() | |||
| #include "../Sequence_Widget.H" // for BBT and position info. | |||
| #define APP_NAME "Non-DAW" // FIXME: wrong place for this! | |||
| /* This is the home of the JACK process callback (does this *really* | |||
| need to be a class?) */ | |||
| /* This is the home of the JACK process callback */ | |||
| #include "const.h" | |||
| #include "util/debug.h" | |||
| @@ -36,71 +33,11 @@ | |||
| Engine::Engine ( ) : _thread( "RT" ) | |||
| { | |||
| _freewheeling = false; | |||
| _zombified = false; | |||
| _client = NULL; | |||
| _buffers_dropped = 0; | |||
| _xruns = 0; | |||
| } | |||
| Engine::~Engine ( ) | |||
| { | |||
| jack_deactivate( _client ); | |||
| jack_client_close( _client ); | |||
| } | |||
| /*******************/ | |||
| /* Static Wrappers */ | |||
| /*******************/ | |||
| int | |||
| Engine::process ( nframes_t nframes, void *arg ) | |||
| { | |||
| return ((Engine*)arg)->process( nframes ); | |||
| } | |||
| int | |||
| Engine::sync ( jack_transport_state_t state, jack_position_t *pos, void *arg ) | |||
| { | |||
| return ((Engine*)arg)->sync( state, pos ); | |||
| } | |||
| int | |||
| Engine::xrun ( void *arg ) | |||
| { | |||
| return ((Engine*)arg)->xrun(); | |||
| } | |||
| void | |||
| Engine::timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg ) | |||
| { | |||
| ((Engine*)arg)->timebase( state, nframes, pos, new_pos ); | |||
| } | |||
| void | |||
| Engine::freewheel ( int starting, void *arg ) | |||
| { | |||
| ((Engine*)arg)->freewheel( starting ); | |||
| } | |||
| int | |||
| Engine::buffer_size ( nframes_t nframes, void *arg ) | |||
| { | |||
| return ((Engine*)arg)->buffer_size( nframes ); | |||
| } | |||
| void | |||
| Engine::thread_init ( void *arg ) | |||
| { | |||
| ((Engine*)arg)->thread_init(); | |||
| } | |||
| void | |||
| Engine::shutdown ( void *arg ) | |||
| { | |||
| ((Engine*)arg)->shutdown(); | |||
| } | |||
| @@ -114,8 +51,6 @@ Engine::shutdown ( void *arg ) | |||
| int | |||
| Engine::xrun ( void ) | |||
| { | |||
| ++_xruns; | |||
| return 0; | |||
| } | |||
| @@ -123,8 +58,6 @@ Engine::xrun ( void ) | |||
| void | |||
| Engine::freewheel ( bool starting ) | |||
| { | |||
| _freewheeling = starting; | |||
| if ( starting ) | |||
| DMESSAGE( "entering freewheeling mode" ); | |||
| else | |||
| @@ -252,14 +185,6 @@ Engine::process ( nframes_t nframes ) | |||
| return 0; | |||
| } | |||
| /* THREAD: RT */ | |||
| /** enter or leave freehweeling mode */ | |||
| void | |||
| Engine::freewheeling ( bool yes ) | |||
| { | |||
| if ( jack_set_freewheel( _client, yes ) ) | |||
| WARNING( "Unkown error while setting freewheeling mode" ); | |||
| } | |||
| /* TRHEAD: RT */ | |||
| void | |||
| @@ -272,43 +197,6 @@ Engine::thread_init ( void ) | |||
| void | |||
| Engine::shutdown ( void ) | |||
| { | |||
| _zombified = true; | |||
| } | |||
| /** Connect to JACK */ | |||
| const char * | |||
| Engine::init ( void ) | |||
| { | |||
| if (( _client = jack_client_open ( APP_NAME, (jack_options_t)0, NULL )) == 0 ) | |||
| return NULL; | |||
| #define set_callback( name ) jack_set_ ## name ## _callback( _client, &Engine:: name , this ) | |||
| set_callback( thread_init ); | |||
| set_callback( process ); | |||
| set_callback( xrun ); | |||
| set_callback( freewheel ); | |||
| set_callback( buffer_size ); | |||
| /* FIXME: should we wait to register this until after the project | |||
| has been loaded (and we have disk threads running)? */ | |||
| set_callback( sync ); | |||
| jack_set_timebase_callback( _client, 0, &Engine::timebase, this ); | |||
| jack_on_shutdown( _client, &Engine::shutdown, this ); | |||
| jack_activate( _client ); | |||
| _sample_rate = frame_rate(); | |||
| MESSAGE( "Jack sample rate is %lu", (unsigned long)_sample_rate ); | |||
| timeline->_sample_rate = frame_rate(); | |||
| /* we don't need to create any ports until tracks are created */ | |||
| return jack_get_client_name( _client ); | |||
| } | |||
| void | |||
| @@ -21,41 +21,26 @@ | |||
| #include "util/Mutex.H" | |||
| #include <jack/jack.h> | |||
| typedef jack_nframes_t nframes_t; | |||
| class Port; | |||
| #include "JACK/Client.H" | |||
| #include "Thread.H" | |||
| class Engine : public Mutex | |||
| class Engine : public JACK::Client, public Mutex | |||
| { | |||
| jack_client_t *_client; | |||
| Thread _thread; /* only used for thread checking */ | |||
| int _buffers_dropped; /* buffers dropped because of locking */ | |||
| nframes_t _sample_rate; | |||
| volatile int _xruns; | |||
| volatile bool _freewheeling; | |||
| volatile bool _zombified; | |||
| /* int _buffers_dropped; /\* buffers dropped because of locking *\/ */ | |||
| static void shutdown ( void *arg ); | |||
| void shutdown ( void ); | |||
| static int process ( nframes_t nframes, void *arg ); | |||
| int process ( nframes_t nframes ); | |||
| static int sync ( jack_transport_state_t state, jack_position_t *pos, void *arg ); | |||
| int sync ( jack_transport_state_t state, jack_position_t *pos ); | |||
| static int xrun ( void *arg ); | |||
| int xrun ( void ); | |||
| static void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg ); | |||
| void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos ); | |||
| static void freewheel ( int yes, void *arg ); | |||
| void freewheel ( bool yes ); | |||
| static int buffer_size ( nframes_t nframes, void *arg ); | |||
| int buffer_size ( nframes_t nframes ); | |||
| static void thread_init ( void *arg ); | |||
| void thread_init ( void ); | |||
| Engine ( const Engine &rhs ); | |||
| @@ -67,34 +52,20 @@ private: | |||
| friend class Port; | |||
| friend class Transport; | |||
| jack_client_t * client ( void ) { return _client; } | |||
| public: | |||
| Engine ( ); | |||
| ~Engine ( ); | |||
| const char * init ( void ); | |||
| nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); } | |||
| float frame_rate ( void ) const { return jack_get_sample_rate( _client ); } | |||
| nframes_t sample_rate ( void ) const { return _sample_rate; } | |||
| int xruns ( void ) const { return _xruns; }; | |||
| int dropped ( void ) const { return _buffers_dropped; } | |||
| bool freewheeling ( void ) const { return _freewheeling; } | |||
| void freewheeling ( bool yes ); | |||
| bool zombified ( void ) const { return _zombified; } | |||
| nframes_t system_latency ( void ) const { return nframes(); } | |||
| float cpu_load ( void ) const { return jack_cpu_load( _client ); } | |||
| float frames_to_milliseconds ( nframes_t frames ) | |||
| { | |||
| return ( frames * 1000 ) / (float)frame_rate(); | |||
| } | |||
| }; | |||
| extern Engine * engine; | |||
| @@ -25,7 +25,7 @@ | |||
| #include "../Audio_Sequence.H" | |||
| #include "../Track.H" | |||
| #include "Port.H" | |||
| // #include "Port.H" | |||
| #include "Playback_DS.H" | |||
| #include "Engine.H" | |||
| #include "dsp.h" | |||
| @@ -1,169 +0,0 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| /* Wrapper for a JACK audio port */ | |||
| #include "Port.H" | |||
| #include <string.h> | |||
| #include "Engine.H" | |||
| #include <stdio.h> // sprintf | |||
| static const char *name_for_port ( Port::type_e dir, const char *base, int n, const char *type ); | |||
| int | |||
| Port::max_name ( void ) | |||
| { | |||
| return jack_port_name_size() - jack_client_name_size() - 6; | |||
| } | |||
| /* nframes is the number of frames to buffer */ | |||
| Port::Port ( jack_port_t *port ) | |||
| { | |||
| _port = port; | |||
| _name = jack_port_name( _port ); | |||
| } | |||
| Port::Port ( const char *name, type_e dir ) | |||
| { | |||
| activate( name, dir ); | |||
| } | |||
| Port::Port ( type_e dir, const char *base, int n, const char *type ) | |||
| { | |||
| const char *name = name_for_port( dir, base, n, type ); | |||
| activate( name, dir ); | |||
| } | |||
| Port::~Port ( ) | |||
| { | |||
| /* if ( _port ) */ | |||
| /* jack_port_unregister( engine->client(), _port ); */ | |||
| } | |||
| static const char * | |||
| name_for_port ( Port::type_e dir, const char *base, int n, const char *type ) | |||
| { | |||
| static char pname[ 512 ]; | |||
| const char *dir_s = dir == Port::Output ? "out" : "in"; | |||
| strncpy( pname, base, Port::max_name() ); | |||
| pname[ Port::max_name() - 1 ] = '\0'; | |||
| int l = strlen( pname ); | |||
| if ( type ) | |||
| snprintf( pname + l, sizeof( pname ) - l, "/%s-%s-%d", type, dir_s, n + 1 ); | |||
| else | |||
| snprintf( pname + l, sizeof( pname ) - l, "/%s-%d", dir_s, n + 1 ); | |||
| return pname; | |||
| } | |||
| void | |||
| Port::activate ( const char *name, type_e dir ) | |||
| { | |||
| _name = name; | |||
| _port = jack_port_register( engine->client(), _name, | |||
| JACK_DEFAULT_AUDIO_TYPE, | |||
| dir == Output ? JackPortIsOutput : JackPortIsInput, | |||
| 0 ); | |||
| } | |||
| /** returns the sum of latency of all ports between this one and a | |||
| terminal port. */ | |||
| /* FIMXE: how does JACK know that input A of client Foo connects to | |||
| output Z of the same client in order to draw the line through Z to a | |||
| terminal port? And, if this determination cannot be made, what use is | |||
| this function? */ | |||
| nframes_t | |||
| Port::total_latency ( void ) const | |||
| { | |||
| return jack_port_get_total_latency( engine->client(), _port ); | |||
| } | |||
| /** returns the number of frames of latency assigned to this port */ | |||
| nframes_t | |||
| Port::latency ( void ) const | |||
| { | |||
| return jack_port_get_latency( _port ); | |||
| } | |||
| /** inform JACK that port has /frames/ frames of latency */ | |||
| void | |||
| Port::latency ( nframes_t frames ) | |||
| { | |||
| jack_port_set_latency( _port, frames ); | |||
| } | |||
| void | |||
| Port::shutdown ( void ) | |||
| { | |||
| if ( _port ) | |||
| jack_port_unregister( engine->client(), _port ); | |||
| } | |||
| /** rename port */ | |||
| bool | |||
| Port::name ( const char *name ) | |||
| { | |||
| _name = name; | |||
| return 0 == jack_port_set_name( _port, name ); | |||
| } | |||
| bool | |||
| Port::name ( const char *base, int n, const char *type ) | |||
| { | |||
| return name( name_for_port( this->type(), base, n, type ) ); | |||
| } | |||
| void | |||
| Port::write ( sample_t *buf, nframes_t nframes ) | |||
| { | |||
| memcpy( buffer( nframes ), buf, nframes * sizeof( sample_t ) ); | |||
| } | |||
| void | |||
| Port::read ( sample_t *buf, nframes_t nframes ) | |||
| { | |||
| memcpy( buf, buffer( nframes ), nframes * sizeof( sample_t ) ); | |||
| } | |||
| void * | |||
| Port::buffer ( nframes_t nframes ) | |||
| { | |||
| return jack_port_get_buffer( _port, nframes ); | |||
| } | |||
| void | |||
| Port::silence ( nframes_t nframes ) | |||
| { | |||
| memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) ); | |||
| } | |||
| @@ -24,7 +24,7 @@ | |||
| #include "../Audio_Sequence.H" | |||
| #include "../Track.H" | |||
| #include "Port.H" | |||
| // #include "Port.H" | |||
| #include "Record_DS.H" | |||
| #include "Engine.H" | |||
| #include "dsp.h" | |||
| @@ -77,7 +77,7 @@ Track::configure_outputs ( int n ) | |||
| { | |||
| for ( int i = on; i < n; ++i ) | |||
| { | |||
| Port p( Port::Output, name(), i ); | |||
| JACK::Port p( engine->client(), JACK::Port::Output, name(), i ); | |||
| if ( p.valid() ) | |||
| output.push_back( p ); | |||
| @@ -124,7 +124,7 @@ Track::configure_inputs ( int n ) | |||
| { | |||
| for ( int i = on; i < n; ++i ) | |||
| { | |||
| Port p( Port::Input, name(), i ); | |||
| JACK::Port p( engine->client(), JACK::Port::Input, name(), i ); | |||
| if ( p.valid() ) | |||
| input.push_back( p ); | |||
| @@ -1,129 +0,0 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| /* Handler based wrapper for LASH */ | |||
| #include "LASH_Client.H" | |||
| #include "const.h" | |||
| #include "util/debug.h" | |||
| LASH_Client::LASH_Client ( ) | |||
| { | |||
| _void = 0; | |||
| } | |||
| LASH_Client::~LASH_Client ( ) | |||
| { | |||
| /* TODO: anything? */ | |||
| } | |||
| #ifdef HAVE_LASH | |||
| #include <lash/lash.h> | |||
| #define _client (static_cast<lash_client_t*>(_void)) | |||
| bool | |||
| LASH_Client::init ( const char *jack_name, const char *long_name, int *argc, char ***argv ) | |||
| { | |||
| if ( ! ( _void = lash_init( lash_extract_args( argc, argv ), jack_name, | |||
| LASH_Config_File, LASH_PROTOCOL( 2, 0 ) ) ) ) | |||
| return false; | |||
| /* register name */ | |||
| lash_jack_client_name( _client, jack_name ); | |||
| lash_event_t *e = lash_event_new_with_type( LASH_Client_Name ); | |||
| lash_event_set_string( e, long_name ); | |||
| lash_send_event( _client, e ); | |||
| return true; | |||
| } | |||
| bool | |||
| LASH_Client::enabled ( void ) | |||
| { | |||
| return lash_enabled( _client ); | |||
| } | |||
| /** process any queued events */ | |||
| void | |||
| LASH_Client::poll ( void ) | |||
| { | |||
| if ( ! _client ) | |||
| return; | |||
| lash_event_t *e; | |||
| while ( ( e = lash_get_event( _client ) ) ) | |||
| { | |||
| const char *name = lash_event_get_string( e ); | |||
| switch ( lash_event_get_type( e ) ) | |||
| { | |||
| case LASH_Save_File: | |||
| handle_save_file( name ); | |||
| lash_send_event( _client, lash_event_new_with_type( LASH_Save_File ) ); | |||
| break; | |||
| case LASH_Restore_File: | |||
| if ( ! handle_restore_file( name ) ) | |||
| /* FIXME: should we tell lash that we couldn't load the song? */; | |||
| lash_send_event( _client, lash_event_new_with_type( LASH_Restore_File ) ); | |||
| break; | |||
| case LASH_Quit: | |||
| handle_quit(); | |||
| break; | |||
| default: | |||
| WARNING( "unhandled LASH event" ); | |||
| break; | |||
| } | |||
| lash_event_destroy( e ); | |||
| } | |||
| } | |||
| #else | |||
| bool | |||
| LASH_Client::init ( const char *jack_name, const char *long_name, int *argc, char ***argv ) | |||
| { | |||
| return true; | |||
| } | |||
| bool | |||
| LASH_Client::enabled ( void ) | |||
| { | |||
| return false; | |||
| } | |||
| void | |||
| LASH_Client::poll ( void ) | |||
| { | |||
| } | |||
| #endif | |||
| @@ -17,13 +17,13 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| /* Actual implementation of our side of the LASH protocol */ | |||
| /* Actual implementation of our side of the LASH_Engine protocol */ | |||
| /* NOTES: Since LASH doesn't provide us with the information we | |||
| * need--when we need it--we just punt and only use LASH to save and | |||
| * load the path to the *real* project data. */ | |||
| #include "LASH.H" | |||
| #include "LASH_Engine.H" | |||
| #include "Project.H" | |||
| #include "TLE.H" // all this just for quit() | |||
| @@ -37,24 +37,24 @@ extern TLE *tle; | |||
| const float lash_poll_interval = 0.2f; | |||
| void | |||
| LASH::timer_cb ( void *v ) | |||
| LASH_Engine::timer_cb ( void *v ) | |||
| { | |||
| ((LASH*)v)->poll(); | |||
| Fl::repeat_timeout( lash_poll_interval, &LASH::timer_cb, v ); | |||
| ((LASH_Engine*)v)->poll(); | |||
| Fl::repeat_timeout( lash_poll_interval, &LASH_Engine::timer_cb, v ); | |||
| } | |||
| LASH::LASH ( ) | |||
| LASH_Engine::LASH_Engine ( ) | |||
| { | |||
| Fl::add_timeout( lash_poll_interval, &LASH::timer_cb, this ); | |||
| Fl::add_timeout( lash_poll_interval, &LASH_Engine::timer_cb, this ); | |||
| } | |||
| LASH::~LASH ( ) | |||
| LASH_Engine::~LASH_Engine ( ) | |||
| { | |||
| Fl::remove_timeout( &LASH::timer_cb ); | |||
| Fl::remove_timeout( &LASH_Engine::timer_cb ); | |||
| } | |||
| bool | |||
| LASH::handle_save_file ( const char *path ) | |||
| LASH_Engine::handle_save_file ( const char *path ) | |||
| { | |||
| MESSAGE( "LASH wants us to save \"%s\"", path ); | |||
| @@ -84,7 +84,7 @@ LASH::handle_save_file ( const char *path ) | |||
| } | |||
| bool | |||
| LASH::handle_restore_file ( const char *path ) | |||
| LASH_Engine::handle_restore_file ( const char *path ) | |||
| { | |||
| MESSAGE( "LASH wants us to load \"%s\"", path ); | |||
| @@ -112,7 +112,7 @@ LASH::handle_restore_file ( const char *path ) | |||
| } | |||
| void | |||
| LASH::handle_quit ( void ) | |||
| LASH_Engine::handle_quit ( void ) | |||
| { | |||
| MESSAGE( "LASH wants us to quit" ); | |||
| tle->quit(); | |||
| @@ -19,17 +19,17 @@ | |||
| #pragma once | |||
| #include "LASH_Client.H" | |||
| #include "LASH/Client.H" | |||
| class LASH : public LASH_Client | |||
| class LASH_Engine : public LASH::Client | |||
| { | |||
| static void timer_cb ( void *v ); | |||
| public: | |||
| LASH ( ); | |||
| ~LASH ( ); | |||
| LASH_Engine ( ); | |||
| ~LASH_Engine ( ); | |||
| bool handle_save_file ( const char *path ); | |||
| bool handle_restore_file ( const char *path ); | |||
| @@ -45,9 +45,6 @@ | |||
| extern TLE *tle; | |||
| /* FIXME: wrong place for this */ | |||
| #define APP_TITLE "Non-DAW" | |||
| const int PROJECT_VERSION = 1; | |||
| @@ -1,5 +1,5 @@ | |||
| # data file for the Fltk User Interface Designer (fluid) | |||
| version 1.0108 | |||
| version 1.0108 | |||
| header_name {.H} | |||
| code_name {.C} | |||
| comment {// | |||
| @@ -24,7 +24,7 @@ comment {// | |||
| decl {const float STATUS_UPDATE_FREQ = 0.5f;} {} | |||
| decl {\#include "LASH.H"} {} | |||
| decl {\#include "LASH_Engine.H"} {} | |||
| decl {\#include "Fl_Menu_Settings.H"} {} | |||
| @@ -67,7 +67,7 @@ decl {extern char project_display_name[256];} {global | |||
| decl {extern char *user_config_dir;} {global | |||
| } | |||
| decl {extern LASH *lash;} {global | |||
| decl {extern LASH_Engine *lash;} {global | |||
| } | |||
| class TLE {open | |||
| @@ -36,7 +36,7 @@ | |||
| #include <vector> | |||
| using std::vector; | |||
| #include "Engine/Port.H" | |||
| #include "JACK/Port.H" | |||
| #include "Timeline.H" | |||
| @@ -44,7 +44,7 @@ class Control_Sequence; | |||
| class Annotation_Sequence; | |||
| class Playback_DS; | |||
| class Record_DS; | |||
| class Port; | |||
| // class JACK::Port; | |||
| class Audio_Region; | |||
| class Audio_File; | |||
| @@ -94,7 +94,7 @@ private: | |||
| bool configure_inputs ( int n ); | |||
| void update_port_names ( void ); | |||
| const char *name_for_port( Port::type_e type, int n ); | |||
| const char *name_for_port( JACK::Port::type_e type, int n ); | |||
| void update_take_menu ( void ); | |||
| Track ( ); | |||
| @@ -124,8 +124,8 @@ public: | |||
| Fl_Pack *takes; | |||
| vector<Port> input; /* input ports... */ | |||
| vector<Port> output; /* output ports... */ | |||
| vector<JACK::Port> input; /* input ports... */ | |||
| vector<JACK::Port> output; /* output ports... */ | |||
| Playback_DS *playback_ds; | |||
| Record_DS *record_ds; | |||
| @@ -17,4 +17,6 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #define APP_NAME "Non-DAW" | |||
| #define APP_TITLE "The Non-DAW" | |||
| #define __MODULE__ "non-daw" | |||
| @@ -43,7 +43,7 @@ | |||
| #include "../FL/Boxtypes.H" | |||
| #include "Project.H" | |||
| #include "LASH.H" | |||
| #include "LASH_Engine.H" | |||
| #include "Transport.H" | |||
| #include "Engine/Engine.H" | |||
| @@ -52,7 +52,7 @@ | |||
| Engine *engine; | |||
| Timeline *timeline; | |||
| Transport *transport; | |||
| LASH *lash; | |||
| LASH_Engine *lash; | |||
| TLE *tle; | |||
| /* TODO: put these in a header */ | |||
| @@ -138,15 +138,17 @@ main ( int argc, char **argv ) | |||
| const char *jack_name; | |||
| if ( ! ( jack_name = engine->init() ) ) | |||
| if ( ! ( jack_name = engine->init( APP_NAME ) ) ) | |||
| FATAL( "Could not connect to JACK!" ); | |||
| timeline->sample_rate( engine->sample_rate() ); | |||
| /* always start stopped (please imagine for me a realistic | |||
| * scenario requiring otherwise */ | |||
| transport->stop(); | |||
| MESSAGE( "Initializing LASH" ); | |||
| lash = new LASH; | |||
| lash = new LASH_Engine; | |||
| if ( argc > 1 && ! strcmp( argv[1], "--no-lash" ) ) | |||
| { | |||
| @@ -1,5 +1,7 @@ | |||
| # -*- mode: makefile; -*- | |||
| all: Timeline | |||
| Timeline_VERSION := 0.5.0 | |||
| Timeline_SRCS := $(wildcard Timeline/*.C Timeline/*.fl Timeline/Engine/*.C) | |||
| @@ -14,7 +16,7 @@ Timeline_LIBS := $(FLTK_LIBS) $(JACK_LIBS) $(SNDFILE_LIBS) $(LASH_LIBS) | |||
| Timeline/timeline: $(Timeline_OBJS) FL | |||
| @ echo -n Linking timeline... | |||
| @ $(CXX) $(CXXFLAGS) $(INCLUDES) $(Timeline_LIBS) $(Timeline_OBJS) -o $@ -LFL -lfl_widgets && echo $(DONE) | |||
| @ $(CXX) $(CXXFLAGS) $(INCLUDES) $(Timeline_LIBS) $(Timeline_OBJS) -o $@ -LFL -lfl_widgets -Lnonlib -lnonlib && echo $(DONE) | |||
| Timeline: Timeline/timeline | |||
| @@ -0,0 +1,143 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #include "Client.H" | |||
| namespace JACK | |||
| { | |||
| Client::Client ( ) | |||
| { | |||
| _freewheeling = false; | |||
| _zombified = false; | |||
| _client = NULL; | |||
| _xruns = 0; | |||
| } | |||
| Client::~Client ( ) | |||
| { | |||
| jack_deactivate( _client ); | |||
| jack_client_close( _client ); | |||
| } | |||
| /*******************/ | |||
| /* Static Wrappers */ | |||
| /*******************/ | |||
| int | |||
| Client::process ( nframes_t nframes, void *arg ) | |||
| { | |||
| return ((Client*)arg)->process( nframes ); | |||
| } | |||
| int | |||
| Client::sync ( jack_transport_state_t state, jack_position_t *pos, void *arg ) | |||
| { | |||
| return ((Client*)arg)->sync( state, pos ); | |||
| } | |||
| int | |||
| Client::xrun ( void *arg ) | |||
| { | |||
| ++((Client*)arg)->_xruns; | |||
| return ((Client*)arg)->xrun(); | |||
| } | |||
| void | |||
| Client::timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg ) | |||
| { | |||
| ((Client*)arg)->timebase( state, nframes, pos, new_pos ); | |||
| } | |||
| void | |||
| Client::freewheel ( int starting, void *arg ) | |||
| { | |||
| ((Client*)arg)->_freewheeling = starting; | |||
| ((Client*)arg)->freewheel( starting ); | |||
| } | |||
| int | |||
| Client::buffer_size ( nframes_t nframes, void *arg ) | |||
| { | |||
| return ((Client*)arg)->buffer_size( nframes ); | |||
| } | |||
| void | |||
| Client::thread_init ( void *arg ) | |||
| { | |||
| ((Client*)arg)->thread_init(); | |||
| } | |||
| void | |||
| Client::shutdown ( void *arg ) | |||
| { | |||
| ((Client*)arg)->_zombified = true; | |||
| ((Client*)arg)->shutdown(); | |||
| } | |||
| /** Connect to JACK using client name /client_name/. Return a static | |||
| * pointer to actual name as reported by JACK */ | |||
| const char * | |||
| Client::init ( const char *client_name ) | |||
| { | |||
| if (( _client = jack_client_open ( client_name, (jack_options_t)0, NULL )) == 0 ) | |||
| return NULL; | |||
| #define set_callback( name ) jack_set_ ## name ## _callback( _client, &Client:: name , this ) | |||
| set_callback( thread_init ); | |||
| set_callback( process ); | |||
| set_callback( xrun ); | |||
| set_callback( freewheel ); | |||
| set_callback( buffer_size ); | |||
| /* FIXME: should we wait to register this until after the project | |||
| has been loaded (and we have disk threads running)? */ | |||
| set_callback( sync ); | |||
| jack_set_timebase_callback( _client, 0, &Client::timebase, this ); | |||
| jack_on_shutdown( _client, &Client::shutdown, this ); | |||
| jack_activate( _client ); | |||
| _sample_rate = frame_rate(); | |||
| return jack_get_client_name( _client ); | |||
| } | |||
| /* THREAD: RT */ | |||
| /** enter or leave freehweeling mode */ | |||
| void | |||
| Client::freewheeling ( bool yes ) | |||
| { | |||
| if ( jack_set_freewheel( _client, yes ) ) | |||
| ; | |||
| // WARNING( "Unkown error while setting freewheeling mode" ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,82 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #pragma once | |||
| #include <jack/jack.h> | |||
| typedef jack_nframes_t nframes_t; | |||
| typedef float sample_t; | |||
| namespace JACK | |||
| { | |||
| class Client | |||
| { | |||
| jack_client_t *_client; | |||
| nframes_t _sample_rate; | |||
| volatile int _xruns; | |||
| volatile bool _freewheeling; | |||
| volatile bool _zombified; | |||
| static void shutdown ( void *arg ); | |||
| virtual void shutdown ( void ) = 0; | |||
| static int process ( nframes_t nframes, void *arg ); | |||
| virtual int process ( nframes_t nframes ) = 0; | |||
| static int sync ( jack_transport_state_t state, jack_position_t *pos, void *arg ); | |||
| virtual int sync ( jack_transport_state_t state, jack_position_t *pos ) = 0; | |||
| static int xrun ( void *arg ); | |||
| virtual int xrun ( void ) = 0; | |||
| static void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg ); | |||
| virtual void timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos ) = 0; | |||
| static void freewheel ( int yes, void *arg ); | |||
| virtual void freewheel ( bool yes ) = 0; | |||
| static int buffer_size ( nframes_t nframes, void *arg ); | |||
| virtual int buffer_size ( nframes_t nframes ) = 0; | |||
| static void thread_init ( void *arg ); | |||
| virtual void thread_init ( void ) = 0; | |||
| Client ( const Client &rhs ); | |||
| Client & operator = ( const Client &rhs ); | |||
| private: | |||
| friend class Port; | |||
| friend class Transport; | |||
| public: | |||
| jack_client_t * client ( void ) { return _client; } | |||
| Client ( ); | |||
| virtual ~Client ( ); | |||
| const char * init ( const char *client_name ); | |||
| nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); } | |||
| float frame_rate ( void ) const { return jack_get_sample_rate( _client ); } | |||
| nframes_t sample_rate ( void ) const { return _sample_rate; } | |||
| int xruns ( void ) const { return _xruns; }; | |||
| bool freewheeling ( void ) const { return _freewheeling; } | |||
| void freewheeling ( bool yes ); | |||
| bool zombified ( void ) const { return _zombified; } | |||
| float cpu_load ( void ) const { return jack_cpu_load( _client ); } | |||
| }; | |||
| } | |||
| @@ -0,0 +1,173 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| /* Wrapper for a JACK audio port */ | |||
| #include "Port.H" | |||
| #include <string.h> | |||
| #include <stdio.h> // sprintf | |||
| namespace JACK | |||
| { | |||
| static const char *name_for_port ( Port::type_e dir, const char *base, int n, const char *type ); | |||
| int | |||
| Port::max_name ( void ) | |||
| { | |||
| return jack_port_name_size() - jack_client_name_size() - 6; | |||
| } | |||
| /* nframes is the number of frames to buffer */ | |||
| Port::Port ( jack_client_t *client, jack_port_t *port ) | |||
| { | |||
| _client = client; | |||
| _port = port; | |||
| _name = jack_port_name( _port ); | |||
| } | |||
| Port::Port ( jack_client_t *client, const char *name, type_e dir ) | |||
| { | |||
| _client = client; | |||
| activate( name, dir ); | |||
| } | |||
| Port::Port ( jack_client_t *client, type_e dir, const char *base, int n, const char *type ) | |||
| { | |||
| _client = client; | |||
| const char *name = name_for_port( dir, base, n, type ); | |||
| activate( name, dir ); | |||
| } | |||
| Port::~Port ( ) | |||
| { | |||
| /* if ( _port ) */ | |||
| /* jack_port_unregister( _client, _port ); */ | |||
| } | |||
| static const char * | |||
| name_for_port ( Port::type_e dir, const char *base, int n, const char *type ) | |||
| { | |||
| static char pname[ 512 ]; | |||
| const char *dir_s = dir == Port::Output ? "out" : "in"; | |||
| strncpy( pname, base, Port::max_name() ); | |||
| pname[ Port::max_name() - 1 ] = '\0'; | |||
| int l = strlen( pname ); | |||
| if ( type ) | |||
| snprintf( pname + l, sizeof( pname ) - l, "/%s-%s-%d", type, dir_s, n + 1 ); | |||
| else | |||
| snprintf( pname + l, sizeof( pname ) - l, "/%s-%d", dir_s, n + 1 ); | |||
| return pname; | |||
| } | |||
| void | |||
| Port::activate ( const char *name, type_e dir ) | |||
| { | |||
| _name = name; | |||
| _port = jack_port_register( _client, _name, | |||
| JACK_DEFAULT_AUDIO_TYPE, | |||
| dir == Output ? JackPortIsOutput : JackPortIsInput, | |||
| 0 ); | |||
| } | |||
| /** returns the sum of latency of all ports between this one and a | |||
| terminal port. */ | |||
| /* FIMXE: how does JACK know that input A of client Foo connects to | |||
| output Z of the same client in order to draw the line through Z to a | |||
| terminal port? And, if this determination cannot be made, what use is | |||
| this function? */ | |||
| nframes_t | |||
| Port::total_latency ( void ) const | |||
| { | |||
| return jack_port_get_total_latency( _client, _port ); | |||
| } | |||
| /** returns the number of frames of latency assigned to this port */ | |||
| nframes_t | |||
| Port::latency ( void ) const | |||
| { | |||
| return jack_port_get_latency( _port ); | |||
| } | |||
| /** inform JACK that port has /frames/ frames of latency */ | |||
| void | |||
| Port::latency ( nframes_t frames ) | |||
| { | |||
| jack_port_set_latency( _port, frames ); | |||
| } | |||
| void | |||
| Port::shutdown ( void ) | |||
| { | |||
| if ( _port ) | |||
| jack_port_unregister( _client, _port ); | |||
| } | |||
| /** rename port */ | |||
| bool | |||
| Port::name ( const char *name ) | |||
| { | |||
| _name = name; | |||
| return 0 == jack_port_set_name( _port, name ); | |||
| } | |||
| bool | |||
| Port::name ( const char *base, int n, const char *type ) | |||
| { | |||
| return name( name_for_port( this->type(), base, n, type ) ); | |||
| } | |||
| void | |||
| Port::write ( sample_t *buf, nframes_t nframes ) | |||
| { | |||
| memcpy( buffer( nframes ), buf, nframes * sizeof( sample_t ) ); | |||
| } | |||
| void | |||
| Port::read ( sample_t *buf, nframes_t nframes ) | |||
| { | |||
| memcpy( buf, buffer( nframes ), nframes * sizeof( sample_t ) ); | |||
| } | |||
| void * | |||
| Port::buffer ( nframes_t nframes ) | |||
| { | |||
| return jack_port_get_buffer( _port, nframes ); | |||
| } | |||
| void | |||
| Port::silence ( nframes_t nframes ) | |||
| { | |||
| memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) ); | |||
| } | |||
| } | |||
| @@ -19,33 +19,35 @@ | |||
| #pragma once | |||
| #include <jack/jack.h> | |||
| // #include <jack/jack.h> | |||
| #include "Client.H" | |||
| #include "types.h" | |||
| class Port | |||
| namespace JACK | |||
| { | |||
| jack_port_t *_port; | |||
| const char *_name; | |||
| class Port | |||
| { | |||
| jack_port_t *_port; | |||
| const char *_name; | |||
| jack_client_t *_client; | |||
| /* FIXME: reference count? */ | |||
| /* FIXME: reference count? */ | |||
| /* /\* not permitted *\/ */ | |||
| /* Port ( const Port &rhs ); */ | |||
| /* Port & operator= ( const Port &rhs ); */ | |||
| public: | |||
| public: | |||
| enum type_e { Output, Input }; | |||
| enum type_e { Output, Input }; | |||
| static int max_name ( void ); | |||
| static int max_name ( void ); | |||
| Port ( jack_port_t *port ); | |||
| Port ( const char *name, type_e dir ); | |||
| Port ( type_e dir, const char *base, int n, const char *type=0 ); | |||
| Port ( jack_client_t *client, jack_port_t *port ); | |||
| Port ( jack_client_t *client, const char *name, type_e dir ); | |||
| Port ( jack_client_t *client, type_e dir, const char *base, int n, const char *type=0 ); | |||
| // Port ( ); | |||
| ~Port ( ); | |||
| ~Port ( ); | |||
| /* Port ( const Port & rhs ) */ | |||
| /* { */ | |||
| @@ -54,23 +56,26 @@ public: | |||
| /* } */ | |||
| bool valid ( void ) const { return _port; } | |||
| bool connected ( void ) const { return jack_port_connected( _port ); } | |||
| type_e type ( void ) const | |||
| { | |||
| return jack_port_flags( _port ) == JackPortIsOutput ? Output : Input; | |||
| } | |||
| const char * name ( void ) const { return _name; } | |||
| bool name ( const char *name ); | |||
| bool name ( const char *base, int n, const char *type=0 ); | |||
| nframes_t total_latency ( void ) const; | |||
| nframes_t latency ( void ) const; | |||
| void latency ( nframes_t frames ); | |||
| void activate ( const char *name, type_e dir ); | |||
| void shutdown ( void ); | |||
| void write ( sample_t *buf, nframes_t nframes ); | |||
| void read ( sample_t *buf, nframes_t nframes ); | |||
| void *buffer ( nframes_t nframes ); | |||
| void silence ( nframes_t nframes ); | |||
| }; | |||
| bool valid ( void ) const { return _port; } | |||
| bool connected ( void ) const { return jack_port_connected( _port ); } | |||
| type_e type ( void ) const | |||
| { | |||
| return jack_port_flags( _port ) == JackPortIsOutput ? Output : Input; | |||
| } | |||
| const char * name ( void ) const { return _name; } | |||
| bool name ( const char *name ); | |||
| bool name ( const char *base, int n, const char *type=0 ); | |||
| nframes_t total_latency ( void ) const; | |||
| nframes_t latency ( void ) const; | |||
| void latency ( nframes_t frames ); | |||
| void activate ( const char *name, type_e dir ); | |||
| void shutdown ( void ); | |||
| void write ( sample_t *buf, nframes_t nframes ); | |||
| void read ( sample_t *buf, nframes_t nframes ); | |||
| void *buffer ( nframes_t nframes ); | |||
| void silence ( nframes_t nframes ); | |||
| }; | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| # -*- mode: makefile; -*- | |||
| nonlib_SRCS := $(wildcard JACK/*.C LASH/*.C) | |||
| nonlib_SRCS:=$(sort $(nonlib_SRCS)) | |||
| nonlib_OBJS:=$(nonlib_SRCS:.C=.o) | |||
| all: nonlib/libnonlib.a | |||
| nonlib/libnonlib.a: $(nonlib_OBJS) | |||
| @ ar rcs $@ $(nonlib_OBJS) | |||
| .PHONEY: nonlib | |||
| nonlib: nonlib/libnonlib.a | |||
| nonlib_clean: | |||
| rm -f $(nonlib_OBJS) nonlib/libnonlib.a | |||
| @@ -0,0 +1,134 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| /* Handler based wrapper for LASH */ | |||
| #include "Client.H" | |||
| /* #include "const.h" */ | |||
| /* #include "util/debug.h" */ | |||
| namespace LASH | |||
| { | |||
| Client::Client ( ) | |||
| { | |||
| _void = 0; | |||
| } | |||
| Client::~Client ( ) | |||
| { | |||
| /* TODO: anything? */ | |||
| } | |||
| #ifdef HAVE_LASH | |||
| #include <lash/lash.h> | |||
| #define _client (static_cast<lash_client_t*>(_void)) | |||
| bool | |||
| Client::init ( const char *jack_name, const char *long_name, int *argc, char ***argv ) | |||
| { | |||
| if ( ! ( _void = lash_init( lash_extract_args( argc, argv ), jack_name, | |||
| LASH_Config_File, LASH_PROTOCOL( 2, 0 ) ) ) ) | |||
| return false; | |||
| /* register name */ | |||
| lash_jack_client_name( _client, jack_name ); | |||
| lash_event_t *e = lash_event_new_with_type( LASH_Client_Name ); | |||
| lash_event_set_string( e, long_name ); | |||
| lash_send_event( _client, e ); | |||
| return true; | |||
| } | |||
| bool | |||
| Client::enabled ( void ) | |||
| { | |||
| return lash_enabled( _client ); | |||
| } | |||
| /** process any queued events */ | |||
| void | |||
| Client::poll ( void ) | |||
| { | |||
| if ( ! _client ) | |||
| return; | |||
| lash_event_t *e; | |||
| while ( ( e = lash_get_event( _client ) ) ) | |||
| { | |||
| const char *name = lash_event_get_string( e ); | |||
| switch ( lash_event_get_type( e ) ) | |||
| { | |||
| case LASH_Save_File: | |||
| handle_save_file( name ); | |||
| lash_send_event( _client, lash_event_new_with_type( LASH_Save_File ) ); | |||
| break; | |||
| case LASH_Restore_File: | |||
| if ( ! handle_restore_file( name ) ) | |||
| /* FIXME: should we tell lash that we couldn't load the song? */; | |||
| lash_send_event( _client, lash_event_new_with_type( LASH_Restore_File ) ); | |||
| break; | |||
| case LASH_Quit: | |||
| handle_quit(); | |||
| break; | |||
| default: | |||
| // WARNING( "unhandled LASH event" ); | |||
| break; | |||
| } | |||
| lash_event_destroy( e ); | |||
| } | |||
| } | |||
| #else | |||
| bool | |||
| Client::init ( const char *jack_name, const char *long_name, int *argc, char ***argv ) | |||
| { | |||
| return true; | |||
| } | |||
| bool | |||
| Client::enabled ( void ) | |||
| { | |||
| return false; | |||
| } | |||
| void | |||
| Client::poll ( void ) | |||
| { | |||
| } | |||
| #endif | |||
| } | |||
| @@ -21,29 +21,32 @@ | |||
| #pragma once | |||
| class LASH_Client | |||
| namespace LASH | |||
| { | |||
| /* to avoid including the lash header here... */ | |||
| void *_void; | |||
| class Client | |||
| { | |||
| /* to avoid including the lash header here... */ | |||
| void *_void; | |||
| protected: | |||
| protected: | |||
| virtual bool handle_save_file ( const char *path ) = 0; | |||
| virtual bool handle_restore_file ( const char *path ) = 0; | |||
| virtual void handle_quit ( void ) = 0; | |||
| virtual bool handle_save_file ( const char *path ) = 0; | |||
| virtual bool handle_restore_file ( const char *path ) = 0; | |||
| virtual void handle_quit ( void ) = 0; | |||
| public: | |||
| public: | |||
| LASH_Client ( ); | |||
| virtual ~LASH_Client ( ); | |||
| Client ( ); | |||
| virtual ~Client ( ); | |||
| bool init ( const char *jack_name, const char *full_name, int *argc, char ***argv ); | |||
| bool enabled ( void ); | |||
| void poll ( void ); | |||
| bool init ( const char *jack_name, const char *full_name, int *argc, char ***argv ); | |||
| bool enabled ( void ); | |||
| void poll ( void ); | |||
| void project_save ( void ); | |||
| void project_quit ( void ); | |||
| void project_save ( void ); | |||
| void project_quit ( void ); | |||
| /* TODO: project_add, project_remove, project_dir, project_name, percentage */ | |||
| /* TODO: project_add, project_remove, project_dir, project_name, percentage */ | |||
| }; | |||
| }; | |||
| } | |||
| @@ -19,7 +19,7 @@ | |||
| #include "Log_Entry.H" | |||
| #include "const.h" | |||
| // #include "const.h" | |||
| #include "util/debug.h" | |||
| Log_Entry::Log_Entry ( ) | |||
| @@ -20,6 +20,7 @@ | |||
| #pragma once | |||
| #include "Loggable.H" | |||
| #include "types.h" | |||
| class Log_Entry | |||
| @@ -33,7 +33,7 @@ | |||
| #include "util/file.h" | |||
| #include "const.h" | |||
| // #include "const.h" | |||
| #include "util/debug.h" | |||
| #include <algorithm> | |||
| @@ -66,7 +66,6 @@ Loggable::~Loggable ( ) | |||
| _loggables[ _id ].loggable = NULL; | |||
| } | |||
| void | |||
| @@ -92,7 +91,6 @@ Loggable::find ( unsigned int id ) | |||
| return _loggables[ id ].loggable; | |||
| } | |||
| /** Open the journal /filename/ and replay it, bringing the end state back into RAM */ | |||
| bool | |||
| Loggable::open ( const char *filename ) | |||
| @@ -161,6 +159,17 @@ Loggable::load_unjournaled_state ( void ) | |||
| #include <sys/stat.h> | |||
| #include <unistd.h> | |||
| /** replay journal or snapshot */ | |||
| bool | |||
| Loggable::replay ( const char *file ) | |||
| { | |||
| FILE *fp = fopen( file, "r" ); | |||
| replay( fp ); | |||
| fclose( fp ); | |||
| } | |||
| /** replay journal or snapshot */ | |||
| bool | |||
| Loggable::replay ( FILE *fp ) | |||
| @@ -31,7 +31,7 @@ | |||
| #include <string> | |||
| #include <queue> | |||
| #include "types.h" | |||
| // #include "types.h" | |||
| typedef void (progress_func)( int, void * ); | |||
| typedef void (snapshot_func)( void * ); | |||
| @@ -102,9 +102,6 @@ private: | |||
| static void flush ( void ); | |||
| static bool snapshot ( FILE * fp ); | |||
| static bool snapshot ( const char *name ); | |||
| static bool replay ( FILE *fp ); | |||
| void init ( bool loggable=true ) | |||
| { | |||
| @@ -129,8 +126,15 @@ private: | |||
| void record_unjournaled ( void ) const; | |||
| static bool load_unjournaled_state ( void ); | |||
| static bool replay ( FILE *fp ); | |||
| static bool replay ( const char *name ); | |||
| public: | |||
| static bool snapshot( FILE * fp ); | |||
| static bool snapshot( const char *name ); | |||
| static void snapshot_callback ( snapshot_func *p, void *arg ) { _snapshot_callback = p; _snapshot_callback_arg = arg; } | |||
| static void progress_callback ( progress_func *p, void *arg ) { _progress_callback = p; _progress_callback_arg = arg;} | |||
| static const char *escape ( const char *s ); | |||
| @@ -33,28 +33,35 @@ buffer_apply_gain ( sample_t *buf, nframes_t nframes, float g ) | |||
| } | |||
| void | |||
| buffer_apply_gain_buffer ( sample_t *buf, sample_t *gainbuf, nframes_t nframes ) | |||
| buffer_apply_gain_buffer ( sample_t *buf, const sample_t *gainbuf, nframes_t nframes ) | |||
| { | |||
| while ( nframes-- ) | |||
| *(buf++) *= *(gainbuf++); | |||
| } | |||
| void | |||
| buffer_mix ( sample_t *dst, sample_t *src, nframes_t nframes ) | |||
| buffer_copy_and_apply_gain_buffer ( sample_t *dst, const sample_t *src, const sample_t *gainbuf, nframes_t nframes ) | |||
| { | |||
| while ( nframes-- ) | |||
| *(dst++) = *(src++) * *(gainbuf++); | |||
| } | |||
| void | |||
| buffer_mix ( sample_t *dst, const sample_t *src, nframes_t nframes ) | |||
| { | |||
| while ( nframes-- ) | |||
| *(dst++) += *(src++); | |||
| } | |||
| void | |||
| buffer_mix_with_gain ( sample_t *dst, sample_t *src, nframes_t nframes, float g ) | |||
| buffer_mix_with_gain ( sample_t *dst, const sample_t *src, nframes_t nframes, float g ) | |||
| { | |||
| while ( nframes-- ) | |||
| *(dst++) += *(src++) * g; | |||
| } | |||
| void | |||
| buffer_interleave_one_channel ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes ) | |||
| buffer_interleave_one_channel ( sample_t *dst, const sample_t *src, int channel, int channels, nframes_t nframes ) | |||
| { | |||
| dst += channel; | |||
| @@ -66,7 +73,7 @@ buffer_interleave_one_channel ( sample_t *dst, sample_t *src, int channel, int c | |||
| } | |||
| void | |||
| buffer_interleave_one_channel_and_mix ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes ) | |||
| buffer_interleave_one_channel_and_mix ( sample_t *dst, const sample_t *src, int channel, int channels, nframes_t nframes ) | |||
| { | |||
| dst += channel; | |||
| @@ -78,7 +85,7 @@ buffer_interleave_one_channel_and_mix ( sample_t *dst, sample_t *src, int channe | |||
| } | |||
| void | |||
| buffer_deinterleave_one_channel ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes ) | |||
| buffer_deinterleave_one_channel ( sample_t *dst, const sample_t *src, int channel, int channels, nframes_t nframes ) | |||
| { | |||
| src += channel; | |||
| @@ -107,3 +114,16 @@ buffer_is_digital_black ( sample_t *buf, nframes_t nframes ) | |||
| return true; | |||
| } | |||
| void | |||
| buffer_copy ( sample_t *dst, const sample_t *src, nframes_t nframes ) | |||
| { | |||
| memcpy( dst, src, nframes * sizeof( sample_t ) ); | |||
| } | |||
| void | |||
| buffer_copy_and_apply_gain ( sample_t *dst, const sample_t *src, nframes_t nframes, float gain ) | |||
| { | |||
| memcpy( dst, src, nframes * sizeof( sample_t ) ); | |||
| buffer_apply_gain( dst, nframes, gain ); | |||
| } | |||
| @@ -0,0 +1,41 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #pragma once | |||
| #include "JACK/Client.H" | |||
| #include <math.h> | |||
| void buffer_apply_gain ( sample_t *buf, nframes_t nframes, float g ); | |||
| void buffer_apply_gain_buffer ( sample_t *buf, const sample_t *gainbuf, nframes_t nframes ); | |||
| void buffer_copy_and_apply_gain_buffer ( sample_t *dst, const sample_t *src, const sample_t *gainbuf, nframes_t nframes ); | |||
| void buffer_mix ( sample_t *dst, const sample_t *src, nframes_t nframes ); | |||
| void buffer_mix_with_gain ( sample_t *dst, const sample_t *src, nframes_t nframes, float g ); | |||
| void buffer_interleave_one_channel ( sample_t *dst, const sample_t *src, int channel, int channels, nframes_t nframes ); | |||
| void buffer_interleave_one_channel_and_mix ( sample_t *dst, const sample_t *src, int channel, int channels, nframes_t nframes ); | |||
| void buffer_deinterleave_one_channel ( sample_t *dst, const sample_t *src, int channel, int channels, nframes_t nframes ); | |||
| void buffer_fill_with_silence ( sample_t *buf, nframes_t nframes ); | |||
| bool buffer_is_digital_black ( sample_t *buf, nframes_t nframes ); | |||
| void buffer_copy ( sample_t *dst, const sample_t *src, nframes_t nframes ); | |||
| void buffer_copy_and_apply_gain ( sample_t *dst, const sample_t *src, nframes_t nframes, float gain ); | |||
| // from SWH plugins. | |||
| // Convert a value in dB's to a coefficent | |||
| #define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f) | |||
| #define CO_DB(v) (20.0f * log10f(v)) | |||
| @@ -0,0 +1,17 @@ | |||
| # -*- mode: makefile; -*- | |||
| nonlib_SRCS := $(wildcard nonlib/*.C nonlib/JACK/*.C nonlib/LASH/*.C) | |||
| nonlib_SRCS:=$(sort $(nonlib_SRCS)) | |||
| nonlib_OBJS:=$(nonlib_SRCS:.C=.o) | |||
| all: nonlib/libnonlib.a | |||
| nonlib/libnonlib.a: $(nonlib_OBJS) | |||
| @ ar rcs $@ $(nonlib_OBJS) | |||
| .PHONEY: nonlib | |||
| nonlib: nonlib/libnonlib.a | |||
| nonlib_clean: | |||
| rm -f $(nonlib_OBJS) nonlib/libnonlib.a | |||
| @@ -19,14 +19,7 @@ | |||
| #pragma once | |||
| #include "types.h" | |||
| #include <jack/jack.h> | |||
| void buffer_apply_gain ( sample_t *buf, nframes_t nframes, float g ); | |||
| void buffer_apply_gain_buffer ( sample_t *buf, sample_t *gainbuf, nframes_t nframes ); | |||
| void buffer_mix ( sample_t *dst, sample_t *src, nframes_t nframes ); | |||
| void buffer_mix_with_gain ( sample_t *dst, sample_t *src, nframes_t nframes, float g ); | |||
| void buffer_interleave_one_channel ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes ); | |||
| void buffer_interleave_one_channel_and_mix ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes ); | |||
| void buffer_deinterleave_one_channel ( sample_t *dst, sample_t *src, int channel, int channels, nframes_t nframes ); | |||
| void buffer_fill_with_silence ( sample_t *buf, nframes_t nframes ); | |||
| bool buffer_is_digital_black ( sample_t *buf, nframes_t nframes ); | |||
| typedef jack_nframes_t nframes_t; | |||
| typedef float sample_t; | |||