Returns (i.e. sidechains).
And lo, upon the revision of our hoarde 5061, was the last Big Feature committed to Three Poino, who, now more than ever, lurks imposingly on the sidelines, heir to the throne, and eventual ruler of the realm. His eventual succession all but guaranteed, only time and the number of heads that must roll remain mysteries. git-svn-id: svn://localhost/ardour2/branches/3.0@5061 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
80c8866303
commit
2c231282ba
|
@ -424,6 +424,7 @@
|
|||
; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newreturn" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/rename" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/selectall" "")
|
||||
|
|
|
@ -354,6 +354,7 @@
|
|||
<menuitem action='newplugin'/>
|
||||
<menuitem action='newinsert'/>
|
||||
<menuitem action='newsend'/>
|
||||
<menuitem action='newreturn'/>
|
||||
<separator/>
|
||||
<menuitem action='clear'/>
|
||||
<separator/>
|
||||
|
|
|
@ -607,6 +607,7 @@
|
|||
<menuitem action='newplugin'/>
|
||||
<menuitem action='newinsert'/>
|
||||
<menuitem action='newsend'/>
|
||||
<menuitem action='newreturn'/>
|
||||
<separator/>
|
||||
<menuitem action='clear'/>
|
||||
<separator/>
|
||||
|
@ -663,6 +664,7 @@
|
|||
<menuitem action='newplugin'/>
|
||||
<menuitem action='newinsert'/>
|
||||
<menuitem action='newsend'/>
|
||||
<menuitem action='newreturn'/>
|
||||
<separator/>
|
||||
<menuitem action='clear'/>
|
||||
<separator/>
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
|
||||
(gtk_accel_path "<Actions>/Editor/crop" "c")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newreturn" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
|
||||
; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
|
||||
|
|
|
@ -439,6 +439,7 @@
|
|||
; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
|
||||
; (gtk_accel_path "<Actions>/redirectmenu/newreturn" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
|
||||
; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
|
||||
|
|
|
@ -47,23 +47,26 @@
|
|||
#include "ardour/plugin_insert.h"
|
||||
#include "ardour/port_insert.h"
|
||||
#include "ardour/profile.h"
|
||||
#include "ardour/return.h"
|
||||
#include "ardour/route.h"
|
||||
#include "ardour/send.h"
|
||||
#include "ardour/session.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "ardour_dialog.h"
|
||||
#include "public_editor.h"
|
||||
#include "processor_box.h"
|
||||
#include "keyboard.h"
|
||||
#include "plugin_selector.h"
|
||||
#include "route_processor_selection.h"
|
||||
#include "mixer_ui.h"
|
||||
#include "actions.h"
|
||||
#include "plugin_ui.h"
|
||||
#include "io_selector.h"
|
||||
#include "utils.h"
|
||||
#include "ardour_dialog.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "gui_thread.h"
|
||||
#include "io_selector.h"
|
||||
#include "keyboard.h"
|
||||
#include "mixer_ui.h"
|
||||
#include "plugin_selector.h"
|
||||
#include "plugin_ui.h"
|
||||
#include "processor_box.h"
|
||||
#include "public_editor.h"
|
||||
#include "return_ui.h"
|
||||
#include "route_processor_selection.h"
|
||||
#include "send_ui.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
@ -216,6 +219,7 @@ void
|
|||
ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
|
||||
{
|
||||
boost::shared_ptr<Send> send;
|
||||
boost::shared_ptr<Return> retrn;
|
||||
boost::shared_ptr<PortInsert> port_insert;
|
||||
|
||||
if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
|
||||
|
@ -226,6 +230,10 @@ ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
|
|||
SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
|
||||
send->set_gui (0);
|
||||
delete sui;
|
||||
} else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
|
||||
ReturnUIWindow *rui = reinterpret_cast<ReturnUIWindow*> (retrn->get_gui());
|
||||
retrn->set_gui (0);
|
||||
delete rui;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,20 +503,13 @@ void
|
|||
ProcessorBox::choose_send ()
|
||||
{
|
||||
boost::shared_ptr<Send> send (new Send (_session));
|
||||
//send->set_default_type(_route->default_type());
|
||||
|
||||
ChanCount outs;
|
||||
|
||||
/* make an educated guess at the initial number of outputs for the send */
|
||||
|
||||
if (_session.master_out()) {
|
||||
outs = _session.master_out()->n_outputs();
|
||||
} else {
|
||||
outs = _route->n_outputs();
|
||||
}
|
||||
ChanCount outs = (_session.master_out())
|
||||
? _session.master_out()->n_outputs()
|
||||
: _route->n_outputs();
|
||||
|
||||
/* XXX need processor lock on route */
|
||||
|
||||
try {
|
||||
send->io()->ensure_io (ChanCount::ZERO, outs, false, this);
|
||||
} catch (AudioEngine::PortRegistrationFailure& err) {
|
||||
|
@ -516,23 +517,17 @@ ProcessorBox::choose_send ()
|
|||
return;
|
||||
}
|
||||
|
||||
/* let the user adjust the output setup (number and connections) before passing
|
||||
it along to the Route
|
||||
*/
|
||||
|
||||
/* let the user adjust the IO setup before creation */
|
||||
IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true);
|
||||
|
||||
ios->show_all ();
|
||||
|
||||
/* bit of a hack; keep a shared_ptr to send around so that it doesn't get deleted while
|
||||
/* keep a reference to the send so it doesn't get deleted while
|
||||
the IOSelectorWindow is doing its stuff */
|
||||
_send_being_created = send;
|
||||
|
||||
boost::shared_ptr<Processor> r = boost::static_pointer_cast<Processor>(send);
|
||||
_processor_being_created = send;
|
||||
|
||||
ios->selector().Finished.connect (bind (
|
||||
mem_fun(*this, &ProcessorBox::send_io_finished),
|
||||
boost::weak_ptr<Processor>(r), ios));
|
||||
boost::weak_ptr<Processor>(send), ios));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -540,8 +535,65 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
|
|||
{
|
||||
boost::shared_ptr<Processor> processor (weak_processor.lock());
|
||||
|
||||
/* now we can lose the dummy shared_ptr */
|
||||
_send_being_created.reset ();
|
||||
/* drop our temporary reference to the new send */
|
||||
_processor_being_created.reset ();
|
||||
|
||||
if (!processor) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
case IOSelector::Cancelled:
|
||||
// processor will go away when all shared_ptrs to it vanish
|
||||
break;
|
||||
|
||||
case IOSelector::Accepted:
|
||||
_route->add_processor (processor, 0, 0, _placement);
|
||||
if (Profile->get_sae()) {
|
||||
processor->activate ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
delete_when_idle (ios);
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorBox::choose_return ()
|
||||
{
|
||||
boost::shared_ptr<Return> retrn (new Return (_session));
|
||||
|
||||
/* assume user just wants a single audio input (sidechain) by default */
|
||||
ChanCount ins(DataType::AUDIO, 1);
|
||||
|
||||
/* XXX need processor lock on route */
|
||||
try {
|
||||
retrn->io()->ensure_io (ins, ChanCount::ZERO, false, this);
|
||||
} catch (AudioEngine::PortRegistrationFailure& err) {
|
||||
error << string_compose (_("Cannot set up new return: %1"), err.what()) << endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
/* let the user adjust the IO setup before creation */
|
||||
IOSelectorWindow *ios = new IOSelectorWindow (_session, retrn->io(), true, true);
|
||||
ios->show_all ();
|
||||
|
||||
/* keep a reference to the send so it doesn't get deleted while
|
||||
the IOSelectorWindow is doing its stuff */
|
||||
_processor_being_created = retrn;
|
||||
|
||||
ios->selector().Finished.connect (bind (
|
||||
mem_fun(*this, &ProcessorBox::return_io_finished),
|
||||
boost::weak_ptr<Processor>(retrn), ios));
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
|
||||
{
|
||||
boost::shared_ptr<Processor> processor (weak_processor.lock());
|
||||
|
||||
/* drop our temporary reference to the new return */
|
||||
_processor_being_created.reset ();
|
||||
|
||||
if (!processor) {
|
||||
return;
|
||||
|
@ -1067,6 +1119,7 @@ void
|
|||
ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
|
||||
{
|
||||
boost::shared_ptr<Send> send;
|
||||
boost::shared_ptr<Return> retrn;
|
||||
boost::shared_ptr<PluginInsert> plugin_insert;
|
||||
boost::shared_ptr<PortInsert> port_insert;
|
||||
Window* gidget = 0;
|
||||
|
@ -1103,6 +1156,32 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
|
|||
}
|
||||
|
||||
gidget = send_ui;
|
||||
|
||||
} else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor);
|
||||
|
||||
ReturnUIWindow *return_ui;
|
||||
|
||||
if (retrn->get_gui() == 0) {
|
||||
|
||||
return_ui = new ReturnUIWindow (retrn, _session);
|
||||
|
||||
WindowTitle title(Glib::get_application_name());
|
||||
title += retrn->name();
|
||||
return_ui->set_title (title.get_string());
|
||||
|
||||
send->set_gui (return_ui);
|
||||
|
||||
} else {
|
||||
return_ui = reinterpret_cast<ReturnUIWindow *> (retrn->get_gui());
|
||||
}
|
||||
|
||||
gidget = return_ui;
|
||||
|
||||
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
|
||||
|
||||
|
@ -1194,6 +1273,9 @@ ProcessorBox::register_actions ()
|
|||
act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."),
|
||||
sigc::ptr_fun (ProcessorBox::rb_choose_send));
|
||||
ActionManager::jack_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (popup_act_grp, X_("newreturn"), _("New Return ..."),
|
||||
sigc::ptr_fun (ProcessorBox::rb_choose_return));
|
||||
ActionManager::jack_sensitive_actions.push_back (act);
|
||||
|
||||
ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear"),
|
||||
sigc::ptr_fun (ProcessorBox::rb_clear));
|
||||
|
@ -1267,6 +1349,15 @@ ProcessorBox::rb_choose_send ()
|
|||
_current_processor_box->choose_send ();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorBox::rb_choose_return ()
|
||||
{
|
||||
if (_current_processor_box == 0) {
|
||||
return;
|
||||
}
|
||||
_current_processor_box->choose_return ();
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorBox::rb_clear ()
|
||||
{
|
||||
|
|
|
@ -94,8 +94,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
|
|||
bool ab_direction;
|
||||
std::vector<sigc::connection> connections;
|
||||
|
||||
/// a send that is in the process of creation
|
||||
boost::shared_ptr<ARDOUR::Send> _send_being_created;
|
||||
boost::shared_ptr<ARDOUR::Processor> _processor_being_created;
|
||||
|
||||
ARDOUR::Placement _placement;
|
||||
|
||||
|
@ -147,6 +146,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
|
|||
|
||||
void choose_send ();
|
||||
void send_io_finished (IOSelector::Result, boost::weak_ptr<ARDOUR::Processor>, IOSelectorWindow*);
|
||||
void choose_return ();
|
||||
void return_io_finished (IOSelector::Result, boost::weak_ptr<ARDOUR::Processor>, IOSelectorWindow*);
|
||||
void choose_insert ();
|
||||
void choose_plugin ();
|
||||
void use_plugins (const SelectedPlugins&);
|
||||
|
@ -209,6 +210,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
|
|||
static void rb_choose_plugin ();
|
||||
static void rb_choose_insert ();
|
||||
static void rb_choose_send ();
|
||||
static void rb_choose_return ();
|
||||
static void rb_clear ();
|
||||
static void rb_cut ();
|
||||
static void rb_copy ();
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
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
|
||||
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; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <gtkmm2ext/doi.h>
|
||||
|
||||
#include "ardour/io.h"
|
||||
#include "ardour/return.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "return_ui.h"
|
||||
#include "io_selector.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "gui_thread.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
|
||||
: _return (r)
|
||||
, _session (se)
|
||||
, _gpm (se)
|
||||
{
|
||||
_gpm.set_io (r->io());
|
||||
|
||||
_hbox.pack_start (_gpm, true, true);
|
||||
set_name ("ReturnUIFrame");
|
||||
|
||||
_vbox.set_spacing (5);
|
||||
_vbox.set_border_width (5);
|
||||
|
||||
_vbox.pack_start (_hbox, false, false, false);
|
||||
|
||||
io = manage (new IOSelector (se, r->io(), true));
|
||||
|
||||
pack_start (_vbox, false, false);
|
||||
|
||||
pack_start (*io, true, true);
|
||||
|
||||
show_all ();
|
||||
|
||||
//_return->set_metering (true);
|
||||
|
||||
_return->io()->input_changed.connect (mem_fun (*this, &ReturnUI::ins_changed));
|
||||
//_return->io()->output_changed.connect (mem_fun (*this, &ReturnUI::outs_changed));
|
||||
|
||||
_gpm.setup_meters ();
|
||||
_gpm.set_fader_name ("ReturnUIFrame");
|
||||
|
||||
// screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::update));
|
||||
fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::fast_update));
|
||||
}
|
||||
|
||||
ReturnUI::~ReturnUI ()
|
||||
{
|
||||
//_return->set_metering (false);
|
||||
|
||||
/* XXX not clear that we need to do this */
|
||||
|
||||
screen_update_connection.disconnect();
|
||||
fast_screen_update_connection.disconnect();
|
||||
}
|
||||
|
||||
void
|
||||
ReturnUI::ins_changed (IOChange change, void* ignored)
|
||||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun (*this, &ReturnUI::ins_changed), change, ignored));
|
||||
if (change & ConfigurationChanged) {
|
||||
_gpm.setup_meters ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReturnUI::update ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ReturnUI::fast_update ()
|
||||
{
|
||||
if (Config->get_meter_falloff() > 0.0f) {
|
||||
_gpm.update_meters ();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnUIWindow::ReturnUIWindow (boost::shared_ptr<Return> s, Session& ss)
|
||||
: ArdourDialog (string("Ardour: return ") + s->name())
|
||||
{
|
||||
ui = new ReturnUI (s, ss);
|
||||
|
||||
hpacker.pack_start (*ui, true, true);
|
||||
|
||||
get_vbox()->set_border_width (5);
|
||||
get_vbox()->pack_start (hpacker);
|
||||
|
||||
set_name ("ReturnUIWindow");
|
||||
|
||||
going_away_connection = s->GoingAway.connect (
|
||||
mem_fun (*this, &ReturnUIWindow::return_going_away));
|
||||
|
||||
signal_delete_event().connect (bind (
|
||||
ptr_fun (just_hide_it),
|
||||
reinterpret_cast<Window *> (this)));
|
||||
}
|
||||
|
||||
ReturnUIWindow::~ReturnUIWindow ()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void
|
||||
ReturnUIWindow::return_going_away ()
|
||||
{
|
||||
ENSURE_GUI_THREAD (mem_fun (*this, &ReturnUIWindow::return_going_away));
|
||||
delete_when_idle (this);
|
||||
going_away_connection.disconnect ();
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
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
|
||||
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; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ardour_gtk_return_ui_h__
|
||||
#define __ardour_gtk_return_ui_h__
|
||||
|
||||
#include "gain_meter.h"
|
||||
#include "panner_ui.h"
|
||||
#include "ardour_dialog.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class Return;
|
||||
class Session;
|
||||
class IOProcessor;
|
||||
}
|
||||
|
||||
class IOSelector;
|
||||
|
||||
class ReturnUI : public Gtk::HBox
|
||||
{
|
||||
public:
|
||||
ReturnUI (boost::shared_ptr<ARDOUR::Return>, ARDOUR::Session&);
|
||||
~ReturnUI();
|
||||
|
||||
void update ();
|
||||
void fast_update ();
|
||||
|
||||
IOSelector* io;
|
||||
|
||||
boost::shared_ptr<ARDOUR::Return>& retrn() { return _return; }
|
||||
|
||||
private:
|
||||
boost::shared_ptr<ARDOUR::Return> _return;
|
||||
ARDOUR::Session& _session;
|
||||
GainMeter _gpm;
|
||||
Gtk::VBox _vbox;
|
||||
Gtk::VBox _hbox;
|
||||
|
||||
sigc::connection screen_update_connection;
|
||||
sigc::connection fast_screen_update_connection;
|
||||
|
||||
void ins_changed (ARDOUR::IOChange, void*);
|
||||
};
|
||||
|
||||
class ReturnUIWindow : public ArdourDialog
|
||||
{
|
||||
public:
|
||||
ReturnUIWindow(boost::shared_ptr<ARDOUR::Return>, ARDOUR::Session&);
|
||||
~ReturnUIWindow();
|
||||
|
||||
ReturnUI* ui;
|
||||
|
||||
private:
|
||||
Gtk::HBox hpacker;
|
||||
|
||||
void return_going_away ();
|
||||
sigc::connection going_away_connection;
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_return_ui_h__ */
|
||||
|
|
@ -26,29 +26,31 @@
|
|||
#include <gtkmm2ext/stop_signal.h>
|
||||
#include <gtkmm2ext/window_title.h>
|
||||
|
||||
#include "ardour/ardour.h"
|
||||
#include "ardour/audio_diskstream.h"
|
||||
#include "ardour/audio_track.h"
|
||||
#include "ardour/plugin.h"
|
||||
#include "ardour/plugin_insert.h"
|
||||
#include "ardour/plugin_manager.h"
|
||||
#include "ardour/port_insert.h"
|
||||
#include "ardour/return.h"
|
||||
#include "ardour/route.h"
|
||||
#include "ardour/send.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/session_route.h"
|
||||
#include "ardour/audio_diskstream.h"
|
||||
#include "ardour/plugin.h"
|
||||
#include "ardour/plugin_manager.h"
|
||||
#include "ardour/ardour.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/route.h"
|
||||
#include "ardour/audio_track.h"
|
||||
#include "ardour/send.h"
|
||||
#include "ardour/plugin_insert.h"
|
||||
#include "ardour/port_insert.h"
|
||||
|
||||
#include "route_params_ui.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "gui_thread.h"
|
||||
#include "io_selector.h"
|
||||
#include "keyboard.h"
|
||||
#include "mixer_strip.h"
|
||||
#include "plugin_selector.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "plugin_ui.h"
|
||||
#include "io_selector.h"
|
||||
#include "return_ui.h"
|
||||
#include "route_params_ui.h"
|
||||
#include "send_ui.h"
|
||||
#include "utils.h"
|
||||
#include "gui_thread.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
@ -559,6 +561,7 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
|
|||
}
|
||||
|
||||
boost::shared_ptr<Send> send;
|
||||
boost::shared_ptr<Return> retrn;
|
||||
boost::shared_ptr<PluginInsert> plugin_insert;
|
||||
boost::shared_ptr<PortInsert> port_insert;
|
||||
|
||||
|
@ -568,35 +571,66 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
|
|||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_pre_plugin_conn = send->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::redirect_going_away),
|
||||
insert));
|
||||
_active_pre_view = send_ui;
|
||||
|
||||
pre_redir_hpane.add2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_post_plugin_conn = send->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::redirect_going_away),
|
||||
insert));
|
||||
_active_post_view = send_ui;
|
||||
|
||||
post_redir_hpane.add2 (*_active_post_view);
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
|
||||
} else if ((retrn = boost::dynamic_pointer_cast<Return> (insert)) != 0) {
|
||||
|
||||
ReturnUI *return_ui = new ReturnUI (retrn, *session);
|
||||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = retrn->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::redirect_going_away),
|
||||
insert));
|
||||
_active_pre_view = return_ui;
|
||||
|
||||
pre_redir_hpane.add2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
} else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = retrn->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::redirect_going_away),
|
||||
insert));
|
||||
_active_post_view = return_ui;
|
||||
|
||||
post_redir_hpane.add2 (*_active_post_view);
|
||||
post_redir_hpane.show_all();
|
||||
}
|
||||
|
||||
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
|
||||
|
||||
GenericPluginUI *plugin_ui = new GenericPluginUI (plugin_insert, true);
|
||||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PreFader));
|
||||
_pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::plugin_going_away),
|
||||
PreFader));
|
||||
plugin_ui->start_updating (0);
|
||||
_active_pre_view = plugin_ui;
|
||||
pre_redir_hpane.pack2 (*_active_pre_view);
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PostFader));
|
||||
_post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::plugin_going_away),
|
||||
PostFader));
|
||||
plugin_ui->start_updating (0);
|
||||
_active_post_view = plugin_ui;
|
||||
post_redir_hpane.pack2 (*_active_post_view);
|
||||
|
@ -609,15 +643,18 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
|
|||
|
||||
if (place == PreFader) {
|
||||
cleanup_pre_view();
|
||||
_pre_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_pre_plugin_conn = port_insert->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::redirect_going_away),
|
||||
insert));
|
||||
_active_pre_view = portinsert_ui;
|
||||
pre_redir_hpane.pack2 (*_active_pre_view);
|
||||
portinsert_ui->redisplay();
|
||||
pre_redir_hpane.show_all();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cleanup_post_view();
|
||||
_post_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
|
||||
_post_plugin_conn = port_insert->GoingAway.connect (bind (
|
||||
mem_fun(*this, &RouteParams_UI::redirect_going_away),
|
||||
insert));
|
||||
_active_post_view = portinsert_ui;
|
||||
post_redir_hpane.pack2 (*_active_post_view);
|
||||
portinsert_ui->redisplay();
|
||||
|
|
|
@ -34,24 +34,24 @@ using namespace PBD;
|
|||
SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
||||
: _send (s)
|
||||
, _session (se)
|
||||
, gpm (se)
|
||||
, panners (se)
|
||||
, _gpm (se)
|
||||
, _panners (se)
|
||||
{
|
||||
panners.set_io (s->io());
|
||||
gpm.set_io (s->io());
|
||||
_panners.set_io (s->io());
|
||||
_gpm.set_io (s->io());
|
||||
|
||||
hbox.pack_start (gpm, true, true);
|
||||
_hbox.pack_start (_gpm, true, true);
|
||||
set_name ("SendUIFrame");
|
||||
|
||||
vbox.set_spacing (5);
|
||||
vbox.set_border_width (5);
|
||||
_vbox.set_spacing (5);
|
||||
_vbox.set_border_width (5);
|
||||
|
||||
vbox.pack_start (hbox, false, false, false);
|
||||
vbox.pack_start (panners, false,false);
|
||||
_vbox.pack_start (_hbox, false, false, false);
|
||||
_vbox.pack_start (_panners, false,false);
|
||||
|
||||
io = manage (new IOSelector (se, s->io(), true));
|
||||
|
||||
pack_start (vbox, false, false);
|
||||
pack_start (_vbox, false, false);
|
||||
|
||||
pack_start (*io, true, true);
|
||||
|
||||
|
@ -62,14 +62,16 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
|
|||
_send->io()->input_changed.connect (mem_fun (*this, &SendUI::ins_changed));
|
||||
_send->io()->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
|
||||
|
||||
panners.set_width (Wide);
|
||||
panners.setup_pan ();
|
||||
_panners.set_width (Wide);
|
||||
_panners.setup_pan ();
|
||||
|
||||
gpm.setup_meters ();
|
||||
gpm.set_fader_name ("SendUIFrame");
|
||||
_gpm.setup_meters ();
|
||||
_gpm.set_fader_name ("SendUIFrame");
|
||||
|
||||
// screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &SendUI::update));
|
||||
fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &SendUI::fast_update));
|
||||
// screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (
|
||||
// mem_fun (*this, &SendUI::update));
|
||||
fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
|
||||
mem_fun (*this, &SendUI::fast_update));
|
||||
}
|
||||
|
||||
SendUI::~SendUI ()
|
||||
|
@ -87,7 +89,7 @@ SendUI::ins_changed (IOChange change, void* ignored)
|
|||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun (*this, &SendUI::ins_changed), change, ignored));
|
||||
if (change & ConfigurationChanged) {
|
||||
panners.setup_pan ();
|
||||
_panners.setup_pan ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,8 +98,8 @@ SendUI::outs_changed (IOChange change, void* ignored)
|
|||
{
|
||||
ENSURE_GUI_THREAD(bind (mem_fun (*this, &SendUI::outs_changed), change, ignored));
|
||||
if (change & ConfigurationChanged) {
|
||||
panners.setup_pan ();
|
||||
gpm.setup_meters ();
|
||||
_panners.setup_pan ();
|
||||
_gpm.setup_meters ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +112,7 @@ void
|
|||
SendUI::fast_update ()
|
||||
{
|
||||
if (Config->get_meter_falloff() > 0.0f) {
|
||||
gpm.update_meters ();
|
||||
_gpm.update_meters ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,9 +128,12 @@ SendUIWindow::SendUIWindow (boost::shared_ptr<Send> s, Session& ss)
|
|||
|
||||
set_name ("SendUIWindow");
|
||||
|
||||
going_away_connection = s->GoingAway.connect (mem_fun (*this, &SendUIWindow::send_going_away));
|
||||
going_away_connection = s->GoingAway.connect (
|
||||
mem_fun (*this, &SendUIWindow::send_going_away));
|
||||
|
||||
signal_delete_event().connect (bind (ptr_fun (just_hide_it), reinterpret_cast<Window *> (this)));
|
||||
signal_delete_event().connect (bind (
|
||||
ptr_fun (just_hide_it),
|
||||
reinterpret_cast<Window *> (this)));
|
||||
}
|
||||
|
||||
SendUIWindow::~SendUIWindow ()
|
||||
|
|
|
@ -47,11 +47,11 @@ class SendUI : public Gtk::HBox
|
|||
|
||||
private:
|
||||
boost::shared_ptr<ARDOUR::Send> _send;
|
||||
ARDOUR::Session& _session;
|
||||
GainMeter gpm;
|
||||
PannerUI panners;
|
||||
Gtk::VBox vbox;
|
||||
Gtk::VBox hbox;
|
||||
ARDOUR::Session& _session;
|
||||
GainMeter _gpm;
|
||||
PannerUI _panners;
|
||||
Gtk::VBox _vbox;
|
||||
Gtk::VBox _hbox;
|
||||
|
||||
sigc::connection screen_update_connection;
|
||||
sigc::connection fast_screen_update_connection;
|
||||
|
@ -66,7 +66,7 @@ class SendUIWindow : public ArdourDialog
|
|||
SendUIWindow(boost::shared_ptr<ARDOUR::Send>, ARDOUR::Session&);
|
||||
~SendUIWindow();
|
||||
|
||||
SendUI* ui;
|
||||
SendUI* ui;
|
||||
|
||||
private:
|
||||
Gtk::HBox hpacker;
|
||||
|
|
|
@ -182,6 +182,7 @@ def build(bld):
|
|||
region_gain_line.cc
|
||||
region_selection.cc
|
||||
region_view.cc
|
||||
return_ui.cc
|
||||
rhythm_ferret.cc
|
||||
route_params_ui.cc
|
||||
route_processor_selection.cc
|
||||
|
|
|
@ -106,6 +106,14 @@ public:
|
|||
return ( (*this > other) || (*this == other) );
|
||||
}
|
||||
|
||||
ChanCount operator+(const ChanCount& other) const {
|
||||
ChanCount ret;
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
ret.set(*t, get(*t) + other.get(*t));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ChanCount min(const ChanCount& a, const ChanCount& b) {
|
||||
ChanCount ret;
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
|
|
|
@ -102,7 +102,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
|||
|
||||
virtual void silence (nframes_t);
|
||||
|
||||
void collect_input (BufferSet& bufs, nframes_t nframes);
|
||||
void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
|
||||
void deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
|
||||
void just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
|
||||
|
||||
|
@ -214,7 +214,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
|
|||
static sigc::signal<int> ConnectingLegal;
|
||||
/// raised when the number of input or output ports changes
|
||||
static sigc::signal<void,ChanCount> PortCountChanged;
|
||||
static sigc::signal<int> PortsCreated;
|
||||
static sigc::signal<void,nframes_t> CycleStart;
|
||||
|
||||
static void update_meters();
|
||||
|
|
|
@ -54,9 +54,6 @@ class PortInsert : public IOProcessor
|
|||
|
||||
nframes_t signal_latency() const;
|
||||
|
||||
ChanCount output_streams() const;
|
||||
ChanCount input_streams() const;
|
||||
|
||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||
bool configure_io (ChanCount in, ChanCount out);
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Copyright (C) 2009 Paul Davis
|
||||
Author: Dave Robillard
|
||||
|
||||
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; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ardour_return_h__
|
||||
#define __ardour_return_h__
|
||||
|
||||
#include <sigc++/signal.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "pbd/stateful.h"
|
||||
#include "ardour/ardour.h"
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/io_processor.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Return : public IOProcessor
|
||||
{
|
||||
public:
|
||||
Return (Session&);
|
||||
Return (Session&, const XMLNode&);
|
||||
virtual ~Return ();
|
||||
|
||||
uint32_t bit_slot() const { return _bitslot; }
|
||||
|
||||
void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
|
||||
|
||||
void activate() {}
|
||||
void deactivate () {}
|
||||
|
||||
XMLNode& state(bool full);
|
||||
XMLNode& get_state(void);
|
||||
int set_state(const XMLNode& node);
|
||||
|
||||
uint32_t pans_required() const { return _configured_input.n_audio(); }
|
||||
|
||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||
bool configure_io (ChanCount in, ChanCount out);
|
||||
|
||||
static uint32_t how_many_sends();
|
||||
static void make_unique (XMLNode &, Session &);
|
||||
|
||||
private:
|
||||
/* disallow copy construction */
|
||||
Return (const Return&);
|
||||
|
||||
uint32_t _bitslot;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
#endif /* __ardour_return_h__ */
|
||||
|
|
@ -38,10 +38,7 @@ class Send : public IOProcessor
|
|||
Send (Session&, const XMLNode&);
|
||||
virtual ~Send ();
|
||||
|
||||
uint32_t bit_slot() const { return bitslot; }
|
||||
|
||||
ChanCount output_streams() const;
|
||||
ChanCount input_streams () const;
|
||||
uint32_t bit_slot() const { return _bitslot; }
|
||||
|
||||
void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
|
||||
|
||||
|
@ -55,7 +52,6 @@ class Send : public IOProcessor
|
|||
int set_state(const XMLNode& node);
|
||||
|
||||
uint32_t pans_required() const { return _configured_input.n_audio(); }
|
||||
void expect_inputs (const ChanCount&);
|
||||
|
||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
|
||||
bool configure_io (ChanCount in, ChanCount out);
|
||||
|
@ -68,8 +64,7 @@ class Send : public IOProcessor
|
|||
Send (const Send&);
|
||||
|
||||
bool _metering;
|
||||
ChanCount expected_inputs;
|
||||
uint32_t bitslot;
|
||||
uint32_t _bitslot;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -101,6 +101,7 @@ class Port;
|
|||
class PortInsert;
|
||||
class Processor;
|
||||
class Region;
|
||||
class Return;
|
||||
class Route;
|
||||
class RouteGroup;
|
||||
class SMFSource;
|
||||
|
@ -764,8 +765,10 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
}
|
||||
|
||||
uint32_t next_send_id();
|
||||
uint32_t next_return_id();
|
||||
uint32_t next_insert_id();
|
||||
void mark_send_id (uint32_t);
|
||||
void mark_return_id (uint32_t);
|
||||
void mark_insert_id (uint32_t);
|
||||
|
||||
/* s/w "RAID" management */
|
||||
|
@ -1566,7 +1569,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
list<PortInsert *> _port_inserts;
|
||||
list<PluginInsert *> _plugin_inserts;
|
||||
list<Send *> _sends;
|
||||
list<Return *> _returns;
|
||||
boost::dynamic_bitset<uint32_t> send_bitset;
|
||||
boost::dynamic_bitset<uint32_t> return_bitset;
|
||||
boost::dynamic_bitset<uint32_t> insert_bitset;
|
||||
uint32_t send_cnt;
|
||||
uint32_t insert_cnt;
|
||||
|
|
|
@ -74,7 +74,6 @@ sigc::signal<int> IO::ConnectingLegal;
|
|||
sigc::signal<int> IO::PortsLegal;
|
||||
sigc::signal<int> IO::PannersLegal;
|
||||
sigc::signal<void,ChanCount> IO::PortCountChanged;
|
||||
sigc::signal<int> IO::PortsCreated;
|
||||
sigc::signal<void,nframes_t> IO::CycleStart;
|
||||
|
||||
Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
|
||||
|
@ -290,24 +289,31 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
|
|||
}
|
||||
|
||||
void
|
||||
IO::collect_input (BufferSet& outs, nframes_t nframes)
|
||||
IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset)
|
||||
{
|
||||
assert(outs.available() >= n_inputs());
|
||||
|
||||
if (n_inputs() == ChanCount::ZERO)
|
||||
if (n_inputs() == ChanCount::ZERO) {
|
||||
return;
|
||||
}
|
||||
|
||||
outs.set_count(n_inputs());
|
||||
|
||||
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
|
||||
PortSet::iterator i = _inputs.begin(*t);
|
||||
BufferSet::iterator o = outs.begin(*t);
|
||||
PortSet::iterator e = _inputs.end (*t);
|
||||
for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
|
||||
|
||||
cerr << (*t).to_string() << endl;
|
||||
for (uint32_t off = 0; off < offset.get(*t); ++off, ++o) {
|
||||
if (o == outs.end(*t)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for ( ; i != _inputs.end(*t); ++i, ++o) {
|
||||
Buffer& b (i->get_buffer (nframes));
|
||||
o->read_from (b, nframes);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,7 +801,8 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
|
|||
{
|
||||
Port* input_port = 0;
|
||||
bool changed = false;
|
||||
|
||||
|
||||
_configured_inputs = count;
|
||||
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
|
||||
|
@ -867,14 +874,14 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
|
|||
|
||||
in = ChanCount::min (_input_maximum, in);
|
||||
out = ChanCount::min (_output_maximum, out);
|
||||
|
||||
_configured_inputs = in;
|
||||
_configured_outputs = out;
|
||||
|
||||
if (in == n_inputs() && out == n_outputs() && !clear) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_configured_inputs = in;
|
||||
_configured_outputs = out;
|
||||
|
||||
{
|
||||
BLOCK_PROCESS_CALLBACK ();
|
||||
Glib::Mutex::Lock lm (io_lock);
|
||||
|
@ -1034,6 +1041,8 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
|
|||
Port* output_port = 0;
|
||||
bool changed = false;
|
||||
bool need_pan_reset = false;
|
||||
|
||||
_configured_outputs = count;
|
||||
|
||||
if (n_outputs() != count) {
|
||||
need_pan_reset = true;
|
||||
|
@ -1708,7 +1717,6 @@ IO::create_ports (const XMLNode& node)
|
|||
|
||||
set_deferred_state ();
|
||||
|
||||
PortsCreated();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,23 +162,7 @@ PortInsert::signal_latency() const
|
|||
bool
|
||||
PortInsert::configure_io (ChanCount in, ChanCount out)
|
||||
{
|
||||
/* do not allow configuration to be changed outside the range of
|
||||
the last request config. or something like that.
|
||||
*/
|
||||
|
||||
/* this is a bit odd:
|
||||
|
||||
the number of inputs we are required to handle corresponds
|
||||
to the number of output ports we need.
|
||||
|
||||
the number of outputs we are required to have corresponds
|
||||
to the number of input ports we need.
|
||||
*/
|
||||
|
||||
/*_io->set_output_maximum (in);
|
||||
_io->set_output_minimum (in);
|
||||
_io->set_input_maximum (out);
|
||||
_io->set_input_minimum (out);*/
|
||||
/* for an insert, processor input corresponds to IO output, and vice versa */
|
||||
|
||||
if (_io->ensure_io (out, in, false, this) != 0) {
|
||||
return false;
|
||||
|
@ -187,21 +171,10 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
|
|||
return Processor::configure_io (in, out);
|
||||
}
|
||||
|
||||
ChanCount
|
||||
PortInsert::output_streams() const
|
||||
{
|
||||
return _io->n_inputs ();
|
||||
}
|
||||
|
||||
ChanCount
|
||||
PortInsert::input_streams() const
|
||||
{
|
||||
return _io->n_outputs ();
|
||||
}
|
||||
|
||||
bool
|
||||
PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
|
||||
{
|
||||
out = in;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Copyright (C) 2000 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
|
||||
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; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "pbd/xml++.h"
|
||||
|
||||
#include "ardour/return.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/port.h"
|
||||
#include "ardour/audio_port.h"
|
||||
#include "ardour/buffer_set.h"
|
||||
#include "ardour/meter.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/io.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
Return::Return (Session& s)
|
||||
: IOProcessor (s, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
|
||||
{
|
||||
ProcessorCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
Return::Return (Session& s, const XMLNode& node)
|
||||
: IOProcessor (s, "return")
|
||||
{
|
||||
if (set_state (node)) {
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
ProcessorCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
Return::~Return ()
|
||||
{
|
||||
GoingAway ();
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Return::get_state(void)
|
||||
{
|
||||
return state (true);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Return::state(bool full)
|
||||
{
|
||||
XMLNode& node = IOProcessor::state(full);
|
||||
char buf[32];
|
||||
node.add_property ("type", "return");
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
|
||||
node.add_property ("bitslot", buf);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
Return::set_state(const XMLNode& node)
|
||||
{
|
||||
XMLNodeList nlist = node.children();
|
||||
XMLNodeIterator niter;
|
||||
const XMLProperty* prop;
|
||||
|
||||
if ((prop = node.property ("bitslot")) == 0) {
|
||||
_bitslot = _session.next_return_id();
|
||||
} else {
|
||||
sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot);
|
||||
_session.mark_return_id (_bitslot);
|
||||
}
|
||||
|
||||
const XMLNode* insert_node = &node;
|
||||
|
||||
/* Return has regular IO automation (gain, pan) */
|
||||
|
||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
if ((*niter)->name() == "IOProcessor") {
|
||||
insert_node = *niter;
|
||||
} else if ((*niter)->name() == X_("Automation")) {
|
||||
// _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
|
||||
}
|
||||
}
|
||||
|
||||
IOProcessor::set_state (*insert_node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Return::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
|
||||
{
|
||||
if (active()) {
|
||||
_io->collect_input (bufs, nframes, _configured_input);
|
||||
bufs.set_count(_configured_output);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
|
||||
{
|
||||
out = in + _io->n_inputs();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Return::configure_io (ChanCount in, ChanCount out)
|
||||
{
|
||||
if (out != in + _io->n_inputs()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure there are enough buffers (since we add some)
|
||||
if (_session.get_scratch_buffers(in).count() < out) {
|
||||
Glib::Mutex::Lock em (_session.engine().process_lock());
|
||||
IO::PortCountChanged(out);
|
||||
}
|
||||
|
||||
Processor::configure_io(in, out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Set up the XML description of a return so that its name is unique.
|
||||
* @param state XML return state.
|
||||
* @param session Session.
|
||||
*/
|
||||
void
|
||||
Return::make_unique (XMLNode &state, Session &session)
|
||||
{
|
||||
uint32_t const bitslot = session.next_return_id() + 1;
|
||||
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
|
||||
state.property("bitslot")->set_value (buf);
|
||||
|
||||
std::string const name = string_compose (_("return %1"), bitslot);
|
||||
|
||||
state.property("name")->set_value (name);
|
||||
|
||||
XMLNode* io = state.child ("IO");
|
||||
if (io) {
|
||||
io->property("name")->set_value (name);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ using namespace ARDOUR;
|
|||
using namespace PBD;
|
||||
|
||||
Send::Send (Session& s)
|
||||
: IOProcessor (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1))
|
||||
: IOProcessor (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1))
|
||||
{
|
||||
_metering = false;
|
||||
ProcessorCreated (this); /* EMIT SIGNAL */
|
||||
|
@ -71,7 +71,7 @@ Send::state(bool full)
|
|||
XMLNode& node = IOProcessor::state(full);
|
||||
char buf[32];
|
||||
node.add_property ("type", "send");
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
|
||||
node.add_property ("bitslot", buf);
|
||||
|
||||
return node;
|
||||
|
@ -85,10 +85,10 @@ Send::set_state(const XMLNode& node)
|
|||
const XMLProperty* prop;
|
||||
|
||||
if ((prop = node.property ("bitslot")) == 0) {
|
||||
bitslot = _session.next_send_id();
|
||||
_bitslot = _session.next_send_id();
|
||||
} else {
|
||||
sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
|
||||
_session.mark_send_id (bitslot);
|
||||
sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot);
|
||||
_session.mark_send_id (_bitslot);
|
||||
}
|
||||
|
||||
const XMLNode* insert_node = &node;
|
||||
|
@ -113,15 +113,7 @@ Send::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
|
|||
{
|
||||
if (active()) {
|
||||
|
||||
// we have to copy the input, because IO::deliver_output may alter the buffers
|
||||
// in-place, which a send must never do.
|
||||
|
||||
BufferSet& sendbufs = _session.get_mix_buffers(bufs.count());
|
||||
|
||||
sendbufs.read_from(bufs, nframes);
|
||||
assert(sendbufs.count() == bufs.count());
|
||||
|
||||
_io->deliver_output (sendbufs, start_frame, end_frame, nframes);
|
||||
_io->deliver_output (bufs, start_frame, end_frame, nframes);
|
||||
|
||||
if (_metering) {
|
||||
if (_io->effective_gain() == 0) {
|
||||
|
@ -152,26 +144,27 @@ Send::set_metering (bool yn)
|
|||
}
|
||||
|
||||
bool
|
||||
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out_is_ignored) const
|
||||
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
|
||||
{
|
||||
if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) {
|
||||
if (_io->input_maximum() == ChanCount::INFINITE
|
||||
&& _io->output_maximum() == ChanCount::INFINITE) {
|
||||
|
||||
/* not configured yet */
|
||||
/* not configured yet, we can support anything */
|
||||
|
||||
return 1; /* we can support anything the first time we're asked */
|
||||
out = in;
|
||||
return true; /* we can support anything the first time we're asked */
|
||||
|
||||
} else {
|
||||
|
||||
/* the "input" config for a port insert corresponds to how
|
||||
many output ports it will have.
|
||||
*/
|
||||
/* for a send, processor input corresponds to IO output */
|
||||
|
||||
if (_io->output_maximum() == in) {
|
||||
return 1;
|
||||
out = in;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -198,32 +191,6 @@ Send::configure_io (ChanCount in, ChanCount out)
|
|||
return true;
|
||||
}
|
||||
|
||||
ChanCount
|
||||
Send::output_streams() const
|
||||
{
|
||||
// this method reflects the idea that from the perspective of the Route's ProcessorList,
|
||||
// a send is just a passthrough. that doesn't match what the Send actually does with its
|
||||
// data, but since what it does is invisible to the Route, it appears to be a passthrough.
|
||||
|
||||
return _configured_input;
|
||||
}
|
||||
|
||||
ChanCount
|
||||
Send::input_streams() const
|
||||
{
|
||||
return _configured_input;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Send::expect_inputs (const ChanCount& expected)
|
||||
{
|
||||
if (expected != expected_inputs) {
|
||||
expected_inputs = expected;
|
||||
_io->reset_panner ();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set up the XML description of a send so that its name is unique.
|
||||
* @param state XML send state.
|
||||
* @param session Session.
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "ardour/processor.h"
|
||||
#include "ardour/recent_sessions.h"
|
||||
#include "ardour/region_factory.h"
|
||||
#include "ardour/return.h"
|
||||
#include "ardour/route_group.h"
|
||||
#include "ardour/send.h"
|
||||
#include "ardour/session.h"
|
||||
|
@ -3666,6 +3667,7 @@ void
|
|||
Session::add_processor (Processor* processor)
|
||||
{
|
||||
Send* send;
|
||||
Return* retrn;
|
||||
PortInsert* port_insert;
|
||||
PluginInsert* plugin_insert;
|
||||
|
||||
|
@ -3675,6 +3677,8 @@ Session::add_processor (Processor* processor)
|
|||
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
|
||||
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
|
||||
_sends.insert (_sends.begin(), send);
|
||||
} else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
|
||||
_returns.insert (_returns.begin(), retrn);
|
||||
} else {
|
||||
fatal << _("programming error: unknown type of Insert created!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
|
@ -3689,6 +3693,7 @@ void
|
|||
Session::remove_processor (Processor* processor)
|
||||
{
|
||||
Send* send;
|
||||
Return* retrn;
|
||||
PortInsert* port_insert;
|
||||
PluginInsert* plugin_insert;
|
||||
|
||||
|
@ -3706,6 +3711,12 @@ Session::remove_processor (Processor* processor)
|
|||
send_bitset[send->bit_slot()] = false;
|
||||
_sends.erase (x);
|
||||
}
|
||||
} else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
|
||||
list<Return*>::iterator x = find (_returns.begin(), _returns.end(), retrn);
|
||||
if (x != _returns.end()) {
|
||||
return_bitset[send->bit_slot()] = false;
|
||||
_returns.erase (x);
|
||||
}
|
||||
} else {
|
||||
fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
|
@ -3884,6 +3895,26 @@ Session::next_send_id ()
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Session::next_return_id ()
|
||||
{
|
||||
/* this doesn't really loop forever. just think about it */
|
||||
|
||||
while (true) {
|
||||
for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < return_bitset.size(); ++n) {
|
||||
if (!return_bitset[n]) {
|
||||
return_bitset[n] = true;
|
||||
return n;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* none available, so resize and try again */
|
||||
|
||||
return_bitset.resize (return_bitset.size() + 16, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::mark_send_id (uint32_t id)
|
||||
{
|
||||
|
@ -3896,6 +3927,18 @@ Session::mark_send_id (uint32_t id)
|
|||
send_bitset[id] = true;
|
||||
}
|
||||
|
||||
void
|
||||
Session::mark_return_id (uint32_t id)
|
||||
{
|
||||
if (id >= return_bitset.size()) {
|
||||
return_bitset.resize (id+16, false);
|
||||
}
|
||||
if (return_bitset[id]) {
|
||||
warning << string_compose (_("return ID %1 appears to be in use already"), id) << endmsg;
|
||||
}
|
||||
return_bitset[id] = true;
|
||||
}
|
||||
|
||||
void
|
||||
Session::mark_insert_id (uint32_t id)
|
||||
{
|
||||
|
|
|
@ -175,6 +175,7 @@ def build(bld):
|
|||
region.cc
|
||||
region_factory.cc
|
||||
resampled_source.cc
|
||||
return.cc
|
||||
reverse.cc
|
||||
route.cc
|
||||
route_group.cc
|
||||
|
|
Loading…
Reference in New Issue