13
0

move Session::Event into SessionEvent class; add SessionEventManager (Session IS-A SessionEventManager); make session ops to toggle all track rec-enable be atomic with respect to process()

git-svn-id: svn://localhost/ardour2/branches/3.0@6273 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-12-04 02:15:12 +00:00
parent 1ef43ec89c
commit 9ad2875905
19 changed files with 528 additions and 460 deletions

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2004 Paul Davis
Copyright (C) 2009 Paul Davis
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
@ -20,17 +20,43 @@
#ifndef __ardour_click_h__
#define __ardour_click_h__
#include <list>
#include "pbd/pool.h"
#include "ardour/types.h"
#include "ardour/io.h"
namespace ARDOUR {
struct Click {
nframes_t start;
nframes_t duration;
nframes_t offset;
const Sample *data;
Click (nframes_t s, nframes_t d, const Sample *b) : start (s), duration (d), offset (0), data (b) {}
void *operator new (size_t) {
return pool.alloc ();
};
void operator delete(void *ptr, size_t /*size*/) {
pool.release (ptr);
}
private:
static Pool pool;
};
typedef std::list<Click*> Clicks;
class ClickIO : public IO
{
public:
public:
ClickIO (Session& s, const std::string& name) : IO (s, name, IO::Output) {}
~ClickIO() {}
protected:
protected:
uint32_t pans_required () const { return 1; }
};

View File

@ -85,6 +85,7 @@ class Diskstream : public SessionObject, public boost::noncopyable
bool record_enabled() const { return g_atomic_int_get (&_record_enabled); }
virtual void set_record_enabled (bool yn) = 0;
virtual void get_input_sources () = 0;
bool destructive() const { return _flags & Destructive; }
virtual int set_destructive (bool /*yn*/) { return -1; }
@ -233,7 +234,6 @@ class Diskstream : public SessionObject, public boost::noncopyable
virtual int use_pending_capture_data (XMLNode& node) = 0;
virtual void get_input_sources () = 0;
virtual void check_record_status (nframes_t transport_frame, nframes_t nframes, bool can_record);
virtual void prepare_record_status (nframes_t /*capture_start_frame*/) {}
virtual void set_align_style_from_io() {}
@ -310,6 +310,7 @@ class Diskstream : public SessionObject, public boost::noncopyable
sigc::connection plmod_connection;
sigc::connection plgone_connection;
sigc::connection plregion_connection;
sigc::connection ic_connection;
Flag _flags;

View File

@ -38,7 +38,6 @@
#include <glibmm/thread.h>
#include "pbd/error.h"
#include "pbd/pool.h"
#include "pbd/rcu.h"
#include "pbd/statefuldestructible.h"
#include "pbd/undo.h"
@ -50,9 +49,11 @@
#include "pbd/stateful.h"
#include "ardour/ardour.h"
#include "ardour/click.h"
#include "ardour/chan_count.h"
#include "ardour/rc_configuration.h"
#include "ardour/session_configuration.h"
#include "ardour/session_event.h"
#include "ardour/location.h"
#include "ardour/timecode.h"
#include "ardour/interpolation.h"
@ -120,7 +121,7 @@ class VSTPlugin;
extern void setup_enum_writer ();
class Session : public PBD::StatefulDestructible, public boost::noncopyable
class Session : public PBD::StatefulDestructible, public SessionEventManager, public boost::noncopyable
{
private:
typedef std::pair<boost::weak_ptr<Route>,bool> RouteBooleanState;
@ -135,100 +136,6 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
Recording = 2
};
struct Event {
enum Type {
SetTransportSpeed,
SetDiskstreamSpeed,
Locate,
LocateRoll,
LocateRollLocate,
SetLoop,
PunchIn,
PunchOut,
RangeStop,
RangeLocate,
Overwrite,
SetSyncSource,
Audition,
InputConfigurationChange,
SetPlayAudioRange,
/* only one of each of these events can be queued at any one time */
StopOnce,
AutoLoop
};
enum Action {
Add,
Remove,
Replace,
Clear
};
Type type;
Action action;
nframes64_t action_frame;
nframes64_t target_frame;
double speed;
union {
void* ptr;
bool yes_or_no;
nframes64_t target2_frame;
Slave* slave;
Route* route;
};
union {
bool second_yes_or_no;
};
std::list<AudioRange> audio_range;
std::list<MusicRange> music_range;
boost::shared_ptr<Region> region;
Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false, bool yn2 = false)
: type (t)
, action (a)
, action_frame (when)
, target_frame (where)
, speed (spd)
, yes_or_no (yn)
, second_yes_or_no (yn2)
{}
void set_ptr (void* p) {
ptr = p;
}
bool before (const Event& other) const {
return action_frame < other.action_frame;
}
bool after (const Event& other) const {
return action_frame > other.action_frame;
}
static bool compare (const Event *e1, const Event *e2) {
return e1->before (*e2);
}
void *operator new (size_t) {
return pool.alloc ();
}
void operator delete (void *ptr, size_t /*size*/) {
pool.release (ptr);
}
static const nframes_t Immediate = 0;
private:
static MultiAllocSingleReleasePool pool;
};
/* creating from an XML file */
Session (AudioEngine&,
@ -458,10 +365,6 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
void reset_input_monitor_state ();
void add_event (nframes_t action_frame, Event::Type type, nframes_t target_frame = 0);
void remove_event (nframes_t frame, Event::Type type);
void clear_events (Event::Type type);
nframes_t get_block_size() const { return current_block_size; }
nframes_t worst_output_latency () const { return _worst_output_latency; }
nframes_t worst_input_latency () const { return _worst_input_latency; }
@ -1160,8 +1063,6 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
boost::scoped_ptr<SessionDirectory> _session_dir;
RingBuffer<Event*> pending_events;
void hookup_io ();
void when_engine_running ();
void graph_reordered ();
@ -1247,27 +1148,6 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
sigc::connection auto_loop_changed_connection;
void auto_loop_changed (Location *);
typedef std::list<Event *> Events;
Events events;
Events immediate_events;
Events::iterator next_event;
/* there can only ever be one of each of these */
Event *auto_loop_event;
Event *punch_out_event;
Event *punch_in_event;
/* events */
void dump_events () const;
void queue_event (Event *ev);
void merge_event (Event*);
void replace_event (Event::Type, nframes_t action_frame, nframes_t target = 0);
bool _replace_event (Event*);
bool _remove_event (Event *);
void _clear_event_type (Event::Type);
void first_stage_init (std::string path, std::string snapshot_name);
int second_stage_init (bool new_tracks);
void find_current_end ();
@ -1299,8 +1179,12 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
void *do_work();
/* SessionEventManager interface */
void queue_event (SessionEvent*);
void process_event (SessionEvent*);
void set_next_event ();
void process_event (Event *ev);
void cleanup_event (SessionEvent*,int);
/* MIDI Machine Control */
@ -1585,34 +1469,12 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
int jack_sync_callback (jack_transport_state_t, jack_position_t*);
void reset_jack_connection (jack_client_t* jack);
void record_enable_change_all (bool yn);
void do_record_enable_change_all (RouteList*, bool);
XMLNode& state(bool);
/* click track */
struct Click {
nframes_t start;
nframes_t duration;
nframes_t offset;
const Sample *data;
Click (nframes_t s, nframes_t d, const Sample *b)
: start (s), duration (d), data (b) { offset = 0; }
void *operator new (size_t) {
return pool.alloc ();
};
void operator delete(void *ptr, size_t /*size*/) {
pool.release (ptr);
}
private:
static Pool pool;
};
typedef std::list<Click*> Clicks;
Clicks clicks;
bool _clicking;
boost::shared_ptr<IO> _click_io;

View File

@ -0,0 +1,152 @@
#ifndef __ardour_session_event_h__
#define __ardour_session_event_h__
#include <list>
#include <boost/shared_ptr.hpp>
#include <sigc++/signal.h>
#include "pbd/pool.h"
#include "pbd/ringbuffer.h"
#include "ardour/types.h"
namespace ARDOUR {
class Slave;
class Region;
struct SessionEvent {
enum Type {
SetTransportSpeed,
SetDiskstreamSpeed,
Locate,
LocateRoll,
LocateRollLocate,
SetLoop,
PunchIn,
PunchOut,
RangeStop,
RangeLocate,
Overwrite,
SetSyncSource,
Audition,
InputConfigurationChange,
SetPlayAudioRange,
SetRecordEnable,
/* only one of each of these events can be queued at any one time */
StopOnce,
AutoLoop
};
enum Action {
Add,
Remove,
Replace,
Clear
};
Type type;
Action action;
nframes64_t action_frame;
nframes64_t target_frame;
double speed;
union {
void* ptr;
bool yes_or_no;
nframes64_t target2_frame;
Slave* slave;
Route* route;
};
union {
bool second_yes_or_no;
RouteList* routes;
};
std::list<AudioRange> audio_range;
std::list<MusicRange> music_range;
boost::shared_ptr<Region> region;
sigc::signal<void,SessionEvent*,int> Complete;
SessionEvent (Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false, bool yn2 = false)
: type (t)
, action (a)
, action_frame (when)
, target_frame (where)
, speed (spd)
, yes_or_no (yn)
, second_yes_or_no (yn2) {}
void set_ptr (void* p) {
ptr = p;
}
bool before (const SessionEvent& other) const {
return action_frame < other.action_frame;
}
bool after (const SessionEvent& other) const {
return action_frame > other.action_frame;
}
static bool compare (const SessionEvent *e1, const SessionEvent *e2) {
return e1->before (*e2);
}
void *operator new (size_t) {
return pool.alloc ();
}
void operator delete (void *ptr, size_t /*size*/) {
pool.release (ptr);
}
static const nframes_t Immediate = 0;
private:
static MultiAllocSingleReleasePool pool;
};
class SessionEventManager {
public:
SessionEventManager () : pending_events (2048){}
virtual ~SessionEventManager() {}
void add_event (nframes64_t action_frame, SessionEvent::Type type, nframes64_t target_frame = 0);
void remove_event (nframes64_t frame, SessionEvent::Type type);
void clear_events (SessionEvent::Type type);
protected:
RingBuffer<SessionEvent*> pending_events;
typedef std::list<SessionEvent *> Events;
Events events;
Events immediate_events;
Events::iterator next_event;
/* there can only ever be one of each of these */
SessionEvent *auto_loop_event;
SessionEvent *punch_out_event;
SessionEvent *punch_in_event;
void dump_events () const;
void merge_event (SessionEvent*);
void replace_event (SessionEvent::Type, nframes64_t action_frame, nframes64_t target = 0);
bool _replace_event (SessionEvent*);
bool _remove_event (SessionEvent *);
void _clear_event_type (SessionEvent::Type);
virtual void process_event(SessionEvent*) = 0;
virtual void queue_event (SessionEvent *ev) = 0;
virtual void set_next_event () = 0;
};
} /* namespace */
#endif /* __ardour_session_event_h__ */

View File

@ -144,7 +144,6 @@ class Track : public Route
FreezeRecord _freeze_record;
XMLNode* pending_state;
sigc::connection recenable_connection;
sigc::connection ic_connection;
bool _destructive;
boost::shared_ptr<RecEnableControllable> _rec_enable_control;

View File

@ -1651,15 +1651,6 @@ AudioDiskstream::set_record_enabled (bool yn)
return;
}
if (yn && channels.reader()->front()->source == 0) {
/* pick up connections not initiated *from* the IO object
we're associated with.
*/
get_input_sources ();
}
/* yes, i know that this not proof against race conditions, but its
good enough. i think.
*/

View File

@ -193,9 +193,6 @@ AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void * /*src*
_diskstream->set_record_enabled (false);
_diskstream->monitor_input (false);
ic_connection.disconnect();
ic_connection = _input->changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
DiskstreamChanged (); /* EMIT SIGNAL */
return 0;

View File

@ -141,6 +141,10 @@ Diskstream::set_route (Route& r)
{
_route = &r;
_io = _route->input();
ic_connection.disconnect();
ic_connection = _io->changed.connect (mem_fun (*this, &Diskstream::handle_input_change));
input_change_pending = ConfigurationChanged;
non_realtime_input_change ();
set_align_style_from_io ();

View File

@ -76,7 +76,7 @@ setup_enum_writer ()
ShuttleBehaviour _ShuttleBehaviour;
ShuttleUnits _ShuttleUnits;
Session::RecordState _Session_RecordState;
Session::Event::Type _Session_Event_Type;
SessionEvent::Type _SessionEvent_Type;
TimecodeFormat _Session_TimecodeFormat;
Session::PullupFormat _Session_PullupFormat;
AudioRegion::FadeShape _AudioRegion_FadeShape;
@ -290,24 +290,25 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session, Recording);
REGISTER (_Session_RecordState);
REGISTER_CLASS_ENUM (Session::Event, SetTransportSpeed);
REGISTER_CLASS_ENUM (Session::Event, SetDiskstreamSpeed);
REGISTER_CLASS_ENUM (Session::Event, Locate);
REGISTER_CLASS_ENUM (Session::Event, LocateRoll);
REGISTER_CLASS_ENUM (Session::Event, LocateRollLocate);
REGISTER_CLASS_ENUM (Session::Event, SetLoop);
REGISTER_CLASS_ENUM (Session::Event, PunchIn);
REGISTER_CLASS_ENUM (Session::Event, PunchOut);
REGISTER_CLASS_ENUM (Session::Event, RangeStop);
REGISTER_CLASS_ENUM (Session::Event, RangeLocate);
REGISTER_CLASS_ENUM (Session::Event, Overwrite);
REGISTER_CLASS_ENUM (Session::Event, SetSyncSource);
REGISTER_CLASS_ENUM (Session::Event, Audition);
REGISTER_CLASS_ENUM (Session::Event, InputConfigurationChange);
REGISTER_CLASS_ENUM (Session::Event, SetPlayAudioRange);
REGISTER_CLASS_ENUM (Session::Event, StopOnce);
REGISTER_CLASS_ENUM (Session::Event, AutoLoop);
REGISTER (_Session_Event_Type);
REGISTER_CLASS_ENUM (SessionEvent, SetTransportSpeed);
REGISTER_CLASS_ENUM (SessionEvent, SetDiskstreamSpeed);
REGISTER_CLASS_ENUM (SessionEvent, Locate);
REGISTER_CLASS_ENUM (SessionEvent, LocateRoll);
REGISTER_CLASS_ENUM (SessionEvent, LocateRollLocate);
REGISTER_CLASS_ENUM (SessionEvent, SetLoop);
REGISTER_CLASS_ENUM (SessionEvent, PunchIn);
REGISTER_CLASS_ENUM (SessionEvent, PunchOut);
REGISTER_CLASS_ENUM (SessionEvent, RangeStop);
REGISTER_CLASS_ENUM (SessionEvent, RangeLocate);
REGISTER_CLASS_ENUM (SessionEvent, Overwrite);
REGISTER_CLASS_ENUM (SessionEvent, SetSyncSource);
REGISTER_CLASS_ENUM (SessionEvent, Audition);
REGISTER_CLASS_ENUM (SessionEvent, InputConfigurationChange);
REGISTER_CLASS_ENUM (SessionEvent, SetPlayAudioRange);
REGISTER_CLASS_ENUM (SessionEvent, SetRecordEnable);
REGISTER_CLASS_ENUM (SessionEvent, StopOnce);
REGISTER_CLASS_ENUM (SessionEvent, AutoLoop);
REGISTER (_SessionEvent_Type);
REGISTER_CLASS_ENUM (Session, Stopped);
REGISTER_CLASS_ENUM (Session, Waiting);

View File

@ -1128,15 +1128,6 @@ MidiDiskstream::set_record_enabled (bool yn)
assert(!destructive());
if (yn && _source_port == 0) {
/* pick up connections not initiated *from* the IO object
we're associated with.
*/
get_input_sources ();
}
/* yes, i know that this not proof against race conditions, but its
good enough. i think.
*/

View File

@ -111,9 +111,6 @@ MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
_diskstream->set_record_enabled (false);
//_diskstream->monitor_input (false);
ic_connection.disconnect();
ic_connection = _input->changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
DiskstreamChanged (); /* EMIT SIGNAL */
return 0;

View File

@ -133,7 +133,6 @@ Session::Session (AudioEngine &eng,
_midi_port (default_midi_port),
_midi_clock_port (default_midi_clock_port),
_session_dir (new SessionDirectory(fullpath)),
pending_events (2048),
state_tree (0),
_butler (new Butler (this)),
_post_transport_work (0),
@ -219,7 +218,6 @@ Session::Session (AudioEngine &eng,
_midi_port (default_midi_port),
_midi_clock_port (default_midi_clock_port),
_session_dir ( new SessionDirectory(fullpath)),
pending_events (2048),
state_tree (0),
_butler (new Butler (this)),
_post_transport_work (0),
@ -916,7 +914,7 @@ Session::reset_input_monitor_state ()
void
Session::auto_punch_start_changed (Location* location)
{
replace_event (Event::PunchIn, location->start());
replace_event (SessionEvent::PunchIn, location->start());
if (get_record_enabled() && config.get_punch_in()) {
/* capture start has been changed, so save new pending state */
@ -929,7 +927,7 @@ Session::auto_punch_end_changed (Location* location)
{
nframes_t when_to_stop = location->end();
// when_to_stop += _worst_output_latency + _worst_input_latency;
replace_event (Event::PunchOut, when_to_stop);
replace_event (SessionEvent::PunchOut, when_to_stop);
}
void
@ -937,15 +935,15 @@ Session::auto_punch_changed (Location* location)
{
nframes_t when_to_stop = location->end();
replace_event (Event::PunchIn, location->start());
replace_event (SessionEvent::PunchIn, location->start());
//when_to_stop += _worst_output_latency + _worst_input_latency;
replace_event (Event::PunchOut, when_to_stop);
replace_event (SessionEvent::PunchOut, when_to_stop);
}
void
Session::auto_loop_changed (Location* location)
{
replace_event (Event::AutoLoop, location->end(), location->start());
replace_event (SessionEvent::AutoLoop, location->end(), location->start());
if (transport_rolling() && play_loop) {
@ -954,7 +952,7 @@ Session::auto_loop_changed (Location* location)
if (_transport_frame < location->start() || _transport_frame > location->end()) {
// relocate to beginning of loop
clear_events (Event::LocateRoll);
clear_events (SessionEvent::LocateRoll);
request_locate (location->start(), true);
@ -966,8 +964,8 @@ Session::auto_loop_changed (Location* location)
loop_changing = true;
if (location->end() > last_loopend) {
clear_events (Event::LocateRoll);
Event *ev = new Event (Event::LocateRoll, Event::Add, last_loopend, last_loopend, 0, true);
clear_events (SessionEvent::LocateRoll);
SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true);
queue_event (ev);
}
@ -987,8 +985,8 @@ Session::set_auto_punch_location (Location* location)
auto_punch_end_changed_connection.disconnect();
auto_punch_changed_connection.disconnect();
existing->set_auto_punch (false, this);
remove_event (existing->start(), Event::PunchIn);
clear_events (Event::PunchOut);
remove_event (existing->start(), SessionEvent::PunchIn);
clear_events (SessionEvent::PunchOut);
auto_punch_location_changed (0);
}
@ -1029,7 +1027,7 @@ Session::set_auto_loop_location (Location* location)
auto_loop_end_changed_connection.disconnect();
auto_loop_changed_connection.disconnect();
existing->set_auto_loop (false, this);
remove_event (existing->end(), Event::AutoLoop);
remove_event (existing->end(), SessionEvent::AutoLoop);
auto_loop_location_changed (0);
}
@ -3424,7 +3422,7 @@ Session::set_audition (boost::shared_ptr<Region> r)
void
Session::audition_playlist ()
{
Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
ev->region.reset ();
queue_event (ev);
}
@ -3444,7 +3442,7 @@ Session::non_realtime_set_audition ()
void
Session::audition_region (boost::shared_ptr<Region> r)
{
Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
ev->region = r;
queue_event (ev);
}
@ -3601,12 +3599,20 @@ Session::graph_reordered ()
void
Session::record_disenable_all ()
{
if (!writable()) {
return;
}
record_enable_change_all (false);
}
void
Session::record_enable_all ()
{
if (!writable()) {
return;
}
record_enable_change_all (true);
}
@ -3614,16 +3620,33 @@ void
Session::record_enable_change_all (bool yn)
{
shared_ptr<RouteList> r = routes.reader ();
RouteList* tracks = new RouteList;
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
boost::shared_ptr<Track> t;
if (boost::dynamic_pointer_cast<Track>(*i) != 0) {
tracks->push_back (*i);
}
}
SessionEvent* ev = new SessionEvent (SessionEvent::SetRecordEnable, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, yn);
ev->routes = tracks;
ev->Complete.connect (mem_fun (*this, &Session::cleanup_event));
queue_event (ev);
}
void
Session::do_record_enable_change_all (RouteList* rl, bool yn)
{
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> t;
if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
t->set_record_enable (yn, this);
}
}
/* since we don't keep rec-enable state, don't mark session dirty */
}
void

View File

@ -75,7 +75,7 @@ Session::schedule_curve_reallocation ()
void
Session::request_overwrite_buffer (Diskstream* stream)
{
Event *ev = new Event (Event::Overwrite, Event::Add, Event::Immediate, 0, 0, 0.0);
SessionEvent *ev = new SessionEvent (SessionEvent::Overwrite, SessionEvent::Add, SessionEvent::Immediate, 0, 0, 0.0);
ev->set_ptr (stream);
queue_event (ev);
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 20002 Paul Davis
Copyright (C) 2002 Paul Davis
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
@ -35,7 +35,7 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
Pool Session::Click::pool ("click", sizeof (Click), 128);
Pool Click::pool ("click", sizeof (Click), 128);
void
Session::click (nframes_t start, nframes_t nframes)

View File

@ -24,13 +24,12 @@
#include "pbd/error.h"
#include "pbd/enumwriter.h"
#include <glibmm/thread.h>
#include "ardour/ardour.h"
#include "ardour/audio_diskstream.h"
#include "ardour/butler.h"
#include "ardour/debug.h"
#include "ardour/session.h"
#include "ardour/session_event.h"
#include "i18n.h"
@ -38,39 +37,39 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
MultiAllocSingleReleasePool SessionEvent::pool ("event", sizeof (SessionEvent), 512);
void
Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
SessionEventManager::add_event (nframes64_t frame, SessionEvent::Type type, nframes64_t target_frame)
{
Event* ev = new Event (type, Event::Add, frame, target_frame, 0);
SessionEvent* ev = new SessionEvent (type, SessionEvent::Add, frame, target_frame, 0);
queue_event (ev);
}
void
Session::remove_event (nframes_t frame, Event::Type type)
SessionEventManager::remove_event (nframes64_t frame, SessionEvent::Type type)
{
Event* ev = new Event (type, Event::Remove, frame, 0, 0);
SessionEvent* ev = new SessionEvent (type, SessionEvent::Remove, frame, 0, 0);
queue_event (ev);
}
void
Session::replace_event (Event::Type type, nframes_t frame, nframes_t target)
SessionEventManager::replace_event (SessionEvent::Type type, nframes64_t frame, nframes64_t target)
{
Event* ev = new Event (type, Event::Replace, frame, target, 0);
SessionEvent* ev = new SessionEvent (type, SessionEvent::Replace, frame, target, 0);
queue_event (ev);
}
void
Session::clear_events (Event::Type type)
SessionEventManager::clear_events (SessionEvent::Type type)
{
Event* ev = new Event (type, Event::Clear, 0, 0, 0);
SessionEvent* ev = new SessionEvent (type, SessionEvent::Clear, 0, 0, 0);
queue_event (ev);
}
void
Session::dump_events () const
SessionEventManager::dump_events () const
{
cerr << "EVENT DUMP" << endl;
for (Events::const_iterator i = events.begin(); i != events.end(); ++i) {
@ -93,34 +92,24 @@ Session::dump_events () const
}
void
Session::queue_event (Event* ev)
{
if (_state_of_the_state & Loading) {
merge_event (ev);
} else {
pending_events.write (&ev, 1);
}
}
void
Session::merge_event (Event* ev)
SessionEventManager::merge_event (SessionEvent* ev)
{
switch (ev->action) {
case Event::Remove:
case SessionEvent::Remove:
_remove_event (ev);
delete ev;
return;
case Event::Replace:
case SessionEvent::Replace:
_replace_event (ev);
return;
case Event::Clear:
case SessionEvent::Clear:
_clear_event_type (ev->type);
delete ev;
return;
case Event::Add:
case SessionEvent::Add:
break;
}
@ -132,8 +121,8 @@ Session::merge_event (Event* ev)
}
switch (ev->type) {
case Event::AutoLoop:
case Event::StopOnce:
case SessionEvent::AutoLoop:
case SessionEvent::StopOnce:
_clear_event_type (ev->type);
break;
@ -148,14 +137,14 @@ Session::merge_event (Event* ev)
}
events.insert (events.begin(), ev);
events.sort (Event::compare);
events.sort (SessionEvent::compare);
next_event = events.begin();
set_next_event ();
}
/** @return true when @a ev is deleted. */
bool
Session::_replace_event (Event* ev)
SessionEventManager::_replace_event (SessionEvent* ev)
{
bool ret = false;
Events::iterator i;
@ -178,7 +167,7 @@ Session::_replace_event (Event* ev)
events.insert (events.begin(), ev);
}
events.sort (Event::compare);
events.sort (SessionEvent::compare);
next_event = events.end();
set_next_event ();
@ -187,7 +176,7 @@ Session::_replace_event (Event* ev)
/** @return true when @a ev is deleted. */
bool
Session::_remove_event (Session::Event* ev)
SessionEventManager::_remove_event (SessionEvent* ev)
{
bool ret = false;
Events::iterator i;
@ -215,7 +204,7 @@ Session::_remove_event (Session::Event* ev)
}
void
Session::_clear_event_type (Event::Type type)
SessionEventManager::_clear_event_type (SessionEvent::Type type)
{
Events::iterator i, tmp;
@ -251,179 +240,3 @@ Session::_clear_event_type (Event::Type type)
set_next_event ();
}
void
Session::set_next_event ()
{
if (events.empty()) {
next_event = events.end();
return;
}
if (next_event == events.end()) {
next_event = events.begin();
}
if ((*next_event)->action_frame > _transport_frame) {
next_event = events.begin();
}
for (; next_event != events.end(); ++next_event) {
if ((*next_event)->action_frame >= _transport_frame) {
break;
}
}
}
void
Session::process_event (Event* ev)
{
bool remove = true;
bool del = true;
/* if we're in the middle of a state change (i.e. waiting
for the butler thread to complete the non-realtime
part of the change), we'll just have to queue this
event for a time when the change is complete.
*/
if (non_realtime_work_pending()) {
/* except locates, which we have the capability to handle */
if (ev->type != Event::Locate) {
immediate_events.insert (immediate_events.end(), ev);
_remove_event (ev);
return;
}
}
DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
switch (ev->type) {
case Event::SetLoop:
set_play_loop (ev->yes_or_no);
break;
case Event::AutoLoop:
if (play_loop) {
start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
}
remove = false;
del = false;
break;
case Event::Locate:
if (ev->yes_or_no) {
// cerr << "forced locate to " << ev->target_frame << endl;
locate (ev->target_frame, false, true, false);
} else {
// cerr << "soft locate to " << ev->target_frame << endl;
start_locate (ev->target_frame, false, true, false);
}
_send_timecode_update = true;
break;
case Event::LocateRoll:
if (ev->yes_or_no) {
// cerr << "forced locate to+roll " << ev->target_frame << endl;
locate (ev->target_frame, true, true, false);
} else {
// cerr << "soft locate to+roll " << ev->target_frame << endl;
start_locate (ev->target_frame, true, true, false);
}
_send_timecode_update = true;
break;
case Event::LocateRollLocate:
// locate is handled by ::request_roll_at_and_return()
_requested_return_frame = ev->target_frame;
request_locate (ev->target2_frame, true);
break;
case Event::SetTransportSpeed:
set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
break;
case Event::PunchIn:
// cerr << "PunchIN at " << transport_frame() << endl;
if (config.get_punch_in() && record_status() == Enabled) {
enable_record ();
}
remove = false;
del = false;
break;
case Event::PunchOut:
// cerr << "PunchOUT at " << transport_frame() << endl;
if (config.get_punch_out()) {
step_back_from_record ();
}
remove = false;
del = false;
break;
case Event::StopOnce:
if (!non_realtime_work_pending()) {
stop_transport (ev->yes_or_no);
_clear_event_type (Event::StopOnce);
}
remove = false;
del = false;
break;
case Event::RangeStop:
if (!non_realtime_work_pending()) {
stop_transport (ev->yes_or_no);
}
remove = false;
del = false;
break;
case Event::RangeLocate:
start_locate (ev->target_frame, true, true, false);
remove = false;
del = false;
break;
case Event::Overwrite:
overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
break;
case Event::SetDiskstreamSpeed:
set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
break;
case Event::SetSyncSource:
use_sync_source (ev->slave);
break;
case Event::Audition:
set_audition (ev->region);
// drop reference to region
ev->region.reset ();
break;
case Event::InputConfigurationChange:
add_post_transport_work (PostTransportInputChange);
_butler->schedule_transport_work ();
break;
case Event::SetPlayAudioRange:
set_play_range (ev->audio_range, (ev->speed == 1.0f));
break;
default:
fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
/*NOTREACHED*/
break;
};
if (remove) {
del = del && !_remove_event (ev);
}
if (del) {
delete ev;
}
}

View File

@ -23,6 +23,7 @@
#include <unistd.h>
#include "pbd/error.h"
#include "pbd/enumwriter.h"
#include <glibmm/thread.h>
@ -274,7 +275,7 @@ Session::commit_diskstreams (nframes_t nframes, bool &needs_butler)
void
Session::process_with_events (nframes_t nframes)
{
Event* ev;
SessionEvent* ev;
nframes_t this_nframes;
nframes_t end_frame;
bool session_needs_butler = false;
@ -299,7 +300,7 @@ Session::process_with_events (nframes_t nframes)
*/
while (!non_realtime_work_pending() && !immediate_events.empty()) {
Event *ev = immediate_events.front ();
SessionEvent *ev = immediate_events.front ();
immediate_events.pop_front ();
process_event (ev);
}
@ -334,7 +335,7 @@ Session::process_with_events (nframes_t nframes)
end_frame = _transport_frame + (nframes_t)frames_moved;
{
Event* this_event;
SessionEvent* this_event;
Events::iterator the_next_one;
if (!process_can_proceed()) {
@ -863,7 +864,7 @@ Session::process_without_events (nframes_t nframes)
void
Session::process_audition (nframes_t nframes)
{
Event* ev;
SessionEvent* ev;
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@ -890,7 +891,7 @@ Session::process_audition (nframes_t nframes)
*/
while (!non_realtime_work_pending() && !immediate_events.empty()) {
Event *ev = immediate_events.front ();
SessionEvent *ev = immediate_events.front ();
immediate_events.pop_front ();
process_event (ev);
}
@ -947,3 +948,209 @@ Session::maybe_sync_start (nframes_t& nframes)
return false;
}
void
Session::queue_event (SessionEvent* ev)
{
if (_state_of_the_state & Deletion) {
return;
} else if (_state_of_the_state & Loading) {
merge_event (ev);
} else {
pending_events.write (&ev, 1);
}
}
void
Session::set_next_event ()
{
if (events.empty()) {
next_event = events.end();
return;
}
if (next_event == events.end()) {
next_event = events.begin();
}
if ((*next_event)->action_frame > _transport_frame) {
next_event = events.begin();
}
for (; next_event != events.end(); ++next_event) {
if ((*next_event)->action_frame >= _transport_frame) {
break;
}
}
}
void
Session::cleanup_event (SessionEvent* ev, int status)
{
switch (ev->type) {
case SessionEvent::SetRecordEnable:
delete ev->routes;
break;
default:
break;
}
}
void
Session::process_event (SessionEvent* ev)
{
bool remove = true;
bool del = true;
/* if we're in the middle of a state change (i.e. waiting
for the butler thread to complete the non-realtime
part of the change), we'll just have to queue this
event for a time when the change is complete.
*/
if (non_realtime_work_pending()) {
/* except locates, which we have the capability to handle */
if (ev->type != SessionEvent::Locate) {
immediate_events.insert (immediate_events.end(), ev);
_remove_event (ev);
return;
}
}
DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
switch (ev->type) {
case SessionEvent::SetLoop:
set_play_loop (ev->yes_or_no);
break;
case SessionEvent::AutoLoop:
if (play_loop) {
start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
}
remove = false;
del = false;
break;
case SessionEvent::Locate:
if (ev->yes_or_no) {
// cerr << "forced locate to " << ev->target_frame << endl;
locate (ev->target_frame, false, true, false);
} else {
// cerr << "soft locate to " << ev->target_frame << endl;
start_locate (ev->target_frame, false, true, false);
}
_send_timecode_update = true;
break;
case SessionEvent::LocateRoll:
if (ev->yes_or_no) {
// cerr << "forced locate to+roll " << ev->target_frame << endl;
locate (ev->target_frame, true, true, false);
} else {
// cerr << "soft locate to+roll " << ev->target_frame << endl;
start_locate (ev->target_frame, true, true, false);
}
_send_timecode_update = true;
break;
case SessionEvent::LocateRollLocate:
// locate is handled by ::request_roll_at_and_return()
_requested_return_frame = ev->target_frame;
request_locate (ev->target2_frame, true);
break;
case SessionEvent::SetTransportSpeed:
set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
break;
case SessionEvent::PunchIn:
// cerr << "PunchIN at " << transport_frame() << endl;
if (config.get_punch_in() && record_status() == Enabled) {
enable_record ();
}
remove = false;
del = false;
break;
case SessionEvent::PunchOut:
// cerr << "PunchOUT at " << transport_frame() << endl;
if (config.get_punch_out()) {
step_back_from_record ();
}
remove = false;
del = false;
break;
case SessionEvent::StopOnce:
if (!non_realtime_work_pending()) {
stop_transport (ev->yes_or_no);
_clear_event_type (SessionEvent::StopOnce);
}
remove = false;
del = false;
break;
case SessionEvent::RangeStop:
if (!non_realtime_work_pending()) {
stop_transport (ev->yes_or_no);
}
remove = false;
del = false;
break;
case SessionEvent::RangeLocate:
start_locate (ev->target_frame, true, true, false);
remove = false;
del = false;
break;
case SessionEvent::Overwrite:
overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
break;
case SessionEvent::SetDiskstreamSpeed:
set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
break;
case SessionEvent::SetSyncSource:
use_sync_source (ev->slave);
break;
case SessionEvent::Audition:
set_audition (ev->region);
// drop reference to region
ev->region.reset ();
break;
case SessionEvent::InputConfigurationChange:
add_post_transport_work (PostTransportInputChange);
_butler->schedule_transport_work ();
break;
case SessionEvent::SetPlayAudioRange:
set_play_range (ev->audio_range, (ev->speed == 1.0f));
break;
case SessionEvent::SetRecordEnable:
do_record_enable_change_all (ev->routes, ev->yes_or_no);
break;
default:
fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
/*NOTREACHED*/
break;
};
if (remove) {
del = del && !_remove_event (ev);
}
ev->Complete (ev, 0); /* EMIT SIGNAL */
if (del) {
delete ev;
}
}

View File

@ -2947,9 +2947,9 @@ Session::config_changed (std::string p, bool ours)
if ((location = _locations.auto_punch_location()) != 0) {
if (config.get_punch_in ()) {
replace_event (Event::PunchIn, location->start());
replace_event (SessionEvent::PunchIn, location->start());
} else {
remove_event (location->start(), Event::PunchIn);
remove_event (location->start(), SessionEvent::PunchIn);
}
}
@ -2960,9 +2960,9 @@ Session::config_changed (std::string p, bool ours)
if ((location = _locations.auto_punch_location()) != 0) {
if (config.get_punch_out()) {
replace_event (Event::PunchOut, location->end());
replace_event (SessionEvent::PunchOut, location->end());
} else {
clear_events (Event::PunchOut);
clear_events (SessionEvent::PunchOut);
}
}

View File

@ -73,7 +73,7 @@ void
Session::request_input_change_handling ()
{
if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
queue_event (ev);
}
}
@ -81,7 +81,7 @@ Session::request_input_change_handling ()
void
Session::request_sync_source (Slave* new_slave)
{
Event* ev = new Event (Event::SetSyncSource, Event::Add, Event::Immediate, 0, 0.0);
SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
bool seamless;
seamless = Config->get_seamless_loop ();
@ -104,7 +104,7 @@ Session::request_sync_source (Slave* new_slave)
void
Session::request_transport_speed (double speed)
{
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
queue_event (ev);
}
@ -112,7 +112,7 @@ Session::request_transport_speed (double speed)
void
Session::request_diskstream_speed (Diskstream& ds, double speed)
{
Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
SessionEvent* ev = new SessionEvent (SessionEvent::SetDiskstreamSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
ev->set_ptr (&ds);
queue_event (ev);
}
@ -120,7 +120,7 @@ Session::request_diskstream_speed (Diskstream& ds, double speed)
void
Session::request_stop (bool abort, bool clear_state)
{
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort, clear_state);
SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
queue_event (ev);
}
@ -128,7 +128,7 @@ Session::request_stop (bool abort, bool clear_state)
void
Session::request_locate (nframes_t target_frame, bool with_roll)
{
Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
queue_event (ev);
}
@ -136,7 +136,7 @@ Session::request_locate (nframes_t target_frame, bool with_roll)
void
Session::force_locate (nframes64_t target_frame, bool with_roll)
{
Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
queue_event (ev);
}
@ -144,7 +144,7 @@ Session::force_locate (nframes64_t target_frame, bool with_roll)
void
Session::request_play_loop (bool yn, bool leave_rolling)
{
Event* ev;
SessionEvent* ev;
Location *location = _locations.auto_loop_location();
if (location == 0 && yn) {
@ -153,7 +153,7 @@ Session::request_play_loop (bool yn, bool leave_rolling)
return;
}
ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
queue_event (ev);
@ -167,7 +167,7 @@ Session::request_play_loop (bool yn, bool leave_rolling)
void
Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
{
Event* ev = new Event (Event::SetPlayAudioRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
if (range) {
ev->audio_range = *range;
} else {
@ -222,9 +222,9 @@ Session::realtime_stop (bool abort, bool clear_state)
add_post_transport_work (todo);
}
_clear_event_type (Event::StopOnce);
_clear_event_type (Event::RangeStop);
_clear_event_type (Event::RangeLocate);
_clear_event_type (SessionEvent::StopOnce);
_clear_event_type (SessionEvent::RangeStop);
_clear_event_type (SessionEvent::RangeLocate);
disable_record (true);
@ -615,7 +615,7 @@ void
Session::unset_play_loop ()
{
play_loop = false;
clear_events (Event::AutoLoop);
clear_events (SessionEvent::AutoLoop);
// set all diskstreams to NOT use internal looping
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
@ -676,7 +676,7 @@ Session::set_play_loop (bool yn)
/* put the loop event into the event list */
Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
merge_event (event);
/* locate to start of loop and roll. If doing seamless loop, force a
@ -1033,7 +1033,7 @@ Session::stop_transport (bool abort, bool clear_state)
and then we'll really be stopped.
*/
Event *ev = new Event (Event::StopOnce, Event::Replace,
SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
_transport_frame + _worst_output_latency - current_block_size,
0, 0, abort);
@ -1276,14 +1276,14 @@ void
Session::unset_play_range ()
{
_play_range = false;
_clear_event_type (Event::RangeStop);
_clear_event_type (Event::RangeLocate);
_clear_event_type (SessionEvent::RangeStop);
_clear_event_type (SessionEvent::RangeLocate);
}
void
Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
{
Event* ev;
SessionEvent* ev;
/* Called from event-processing context */
@ -1294,7 +1294,7 @@ Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
*/
if (!leave_rolling) {
/* stop transport */
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
merge_event (ev);
}
return;
@ -1329,9 +1329,9 @@ Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
}
if (next == range.end()) {
ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
} else {
ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
}
merge_event (ev);
@ -1341,7 +1341,7 @@ Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
} else if (sz == 1) {
ev = new Event (Event::RangeStop, Event::Add, range.front().end, 0, 0.0f);
ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
merge_event (ev);
}
@ -1352,7 +1352,7 @@ Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
/* now start rolling at the right place */
ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, range.front().start, 0.0f, false);
ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
merge_event (ev);
TransportStateChange ();
@ -1370,7 +1370,7 @@ Session::request_bounded_roll (nframes_t start, nframes_t end)
void
Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
{
Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
ev->target2_frame = start;
queue_event (ev);
}

View File

@ -192,13 +192,17 @@ Track::set_record_enable (bool yn, void *src)
_diskstream->set_record_enabled (yn);
#if 0
if (_diskstream->record_enabled()) {
set_meter_point (MeterInput, this);
} else {
set_meter_point (_saved_meter_point, this);
}
#endif
cerr << "4\n";
_rec_enable_control->Changed ();
cerr << "5\n";
}