i/o button naming patch and imported file BWF timecode retention patch from nickm, both reworked for 3.0
git-svn-id: svn://localhost/ardour2/branches/3.0@5711 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -695,8 +695,11 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
|
||||
ustring region_name;
|
||||
uint32_t input_chan = 0;
|
||||
uint32_t output_chan = 0;
|
||||
bool use_timestamp;
|
||||
|
||||
use_timestamp = (pos == -1);
|
||||
|
||||
if (pos == -1) { // "use timestamp"
|
||||
if (use_timestamp) {
|
||||
if (sources[0]->natural_position() != 0) {
|
||||
pos = sources[0]->natural_position();
|
||||
} else {
|
||||
@@ -714,8 +717,15 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
|
||||
|
||||
region_name = region_name_from_path (paths.front(), (sources.size() > 1), false);
|
||||
|
||||
regions.push_back (RegionFactory::create (sources, 0, sources[0]->length(pos), region_name, 0,
|
||||
Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)));
|
||||
boost::shared_ptr<Region> r = RegionFactory::create (sources, 0, sources[0]->length(pos), region_name, 0,
|
||||
Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
|
||||
|
||||
if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
|
||||
boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position(sources[0]->natural_position());
|
||||
}
|
||||
|
||||
regions.push_back (r);
|
||||
|
||||
|
||||
} else if (target_regions == -1 || target_regions > 1) {
|
||||
|
||||
@@ -732,9 +742,14 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
|
||||
|
||||
region_name = region_name_from_path ((*x)->path(), false, false, sources.size(), n);
|
||||
|
||||
regions.push_back (RegionFactory::create (just_one, 0, (*x)->length(pos), region_name, 0,
|
||||
Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)));
|
||||
|
||||
boost::shared_ptr<Region> r = RegionFactory::create (just_one, 0, (*x)->length(pos), region_name, 0,
|
||||
Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
|
||||
|
||||
if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
|
||||
boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position((*x)->natural_position());
|
||||
}
|
||||
|
||||
regions.push_back (r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ void LV2PluginUI::on_external_ui_closed(LV2UI_Controller controller)
|
||||
me->_screen_update_connection.disconnect();
|
||||
//me->insert->set_gui(0);
|
||||
|
||||
for (vector<struct lv2_external_ui*>::iterator it = g_external_uis.begin() ; it < g_external_uis.end(); it++) {
|
||||
for (std::vector<struct lv2_external_ui*>::iterator it = g_external_uis.begin() ; it < g_external_uis.end(); it++) {
|
||||
if (*it == me->_external_ui_ptr) {
|
||||
g_external_uis.erase(it);
|
||||
}
|
||||
|
||||
@@ -878,51 +878,226 @@ MixerStrip::connect_to_pan ()
|
||||
panners.pan_changed (this);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output port labelling
|
||||
* =====================
|
||||
*
|
||||
* Case 1: Each output has one connection, all connections are to system:playback_%i
|
||||
* out 1 -> system:playback_1
|
||||
* out 2 -> system:playback_2
|
||||
* out 3 -> system:playback_3
|
||||
* Display as: 1/2/3
|
||||
*
|
||||
* Case 2: Each output has one connection, all connections are to ardour:track_x/in 1
|
||||
* out 1 -> ardour:track_x/in 1
|
||||
* out 2 -> ardour:track_x/in 2
|
||||
* Display as: track_x
|
||||
*
|
||||
* Case 3: Each output has one connection, all connections are to Jack client "program x"
|
||||
* out 1 -> program x:foo
|
||||
* out 2 -> program x:foo
|
||||
* Display as: program x
|
||||
*
|
||||
* Case 4: No connections (Disconnected)
|
||||
* Display as: -
|
||||
*
|
||||
* Default case (unusual routing):
|
||||
* Display as: *number of connections*
|
||||
*
|
||||
* Tooltips
|
||||
* ========
|
||||
* .-----------------------------------------------.
|
||||
* | Mixdown |
|
||||
* | out 1 -> ardour:master/in 1, jamin:input/in 1 |
|
||||
* | out 2 -> ardour:master/in 2, jamin:input/in 2 |
|
||||
* '-----------------------------------------------'
|
||||
* .-----------------------------------------------.
|
||||
* | Guitar SM58 |
|
||||
* | Disconnected |
|
||||
* '-----------------------------------------------'
|
||||
*/
|
||||
|
||||
void
|
||||
MixerStrip::update_io_button (boost::shared_ptr<ARDOUR::Route> route, Width width, bool for_input)
|
||||
{
|
||||
uint32_t io_count;
|
||||
uint32_t io_index;
|
||||
Port *port;
|
||||
vector<string> connections;
|
||||
|
||||
uint32_t connection_index;
|
||||
uint32_t total_connection_count = 0;
|
||||
uint32_t io_connection_count = 0;
|
||||
uint32_t ardour_connection_count = 0;
|
||||
uint32_t system_connection_count = 0;
|
||||
uint32_t other_connection_count = 0;
|
||||
|
||||
ostringstream label;
|
||||
string label_string;
|
||||
char * label_cstr;
|
||||
|
||||
bool have_label = false;
|
||||
bool each_io_has_one_connection = true;
|
||||
|
||||
string connection_name;
|
||||
string ardour_track_name;
|
||||
string other_connection_type;
|
||||
string system_ports;
|
||||
string system_port;
|
||||
|
||||
ostringstream tooltip;
|
||||
char * tooltip_cstr;
|
||||
|
||||
tooltip << route->name();
|
||||
|
||||
if (for_input) {
|
||||
io_count = route->n_inputs().n_total();
|
||||
} else {
|
||||
io_count = route->n_outputs().n_total();
|
||||
}
|
||||
|
||||
for (io_index = 0; io_index < io_count; ++io_index) {
|
||||
if (for_input) {
|
||||
port = route->input()->nth (io_index);
|
||||
} else {
|
||||
port = route->output()->nth (io_index);
|
||||
}
|
||||
|
||||
port->get_connections(connections);
|
||||
io_connection_count = 0;
|
||||
|
||||
if (!connections.empty()) {
|
||||
for (vector<string>::iterator i = connections.begin(); i != connections.end(); ++i) {
|
||||
string& connection_name (*i);
|
||||
|
||||
if (connection_index == 0) {
|
||||
tooltip << endl << port->name().substr(port->name().find("/") + 1) << " -> " << connection_name;
|
||||
} else {
|
||||
tooltip << ", " << connection_name;
|
||||
}
|
||||
|
||||
if (connection_name.find("ardour:") == 0) {
|
||||
if (ardour_track_name.empty()) {
|
||||
// "ardour:Master/in 1" -> "ardour:Master/"
|
||||
ardour_track_name = connection_name.substr(0, connection_name.find("/") + 1);
|
||||
}
|
||||
|
||||
if (connection_name.find(ardour_track_name) == 0) {
|
||||
++ardour_connection_count;
|
||||
}
|
||||
} else if (connection_name.find("system:") == 0) {
|
||||
if (for_input) {
|
||||
// "system:capture_123" -> "123"
|
||||
system_port = connection_name.substr(15);
|
||||
} else {
|
||||
// "system:playback_123" -> "123"
|
||||
system_port = connection_name.substr(16);
|
||||
}
|
||||
|
||||
if (system_ports.empty()) {
|
||||
system_ports += system_port;
|
||||
} else {
|
||||
system_ports += "/" + system_port;
|
||||
}
|
||||
|
||||
++system_connection_count;
|
||||
} else {
|
||||
if (other_connection_type.empty()) {
|
||||
// "jamin:in 1" -> "jamin:"
|
||||
other_connection_type = connection_name.substr(0, connection_name.find(":") + 1);
|
||||
}
|
||||
|
||||
if (connection_name.find(other_connection_type) == 0) {
|
||||
++other_connection_count;
|
||||
}
|
||||
}
|
||||
|
||||
++total_connection_count;
|
||||
++io_connection_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (io_connection_count != 1) {
|
||||
each_io_has_one_connection = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (total_connection_count == 0) {
|
||||
tooltip << endl << _("Disconnected");
|
||||
}
|
||||
|
||||
tooltip_cstr = new char[tooltip.str().size() + 1];
|
||||
strcpy(tooltip_cstr, tooltip.str().c_str());
|
||||
|
||||
if (for_input) {
|
||||
ARDOUR_UI::instance()->set_tip (&input_button, tooltip_cstr, "");
|
||||
} else {
|
||||
ARDOUR_UI::instance()->set_tip (&output_button, tooltip_cstr, "");
|
||||
}
|
||||
|
||||
if (each_io_has_one_connection) {
|
||||
if ((total_connection_count == ardour_connection_count)) {
|
||||
// all connections are to the same track in ardour
|
||||
// "ardour:Master/" -> "Master"
|
||||
label << ardour_track_name.substr(7, ardour_track_name.find("/") - 7);
|
||||
have_label = true;
|
||||
}
|
||||
else if (total_connection_count == system_connection_count) {
|
||||
// all connections are to system ports
|
||||
label << system_ports;
|
||||
have_label = true;
|
||||
}
|
||||
else if (total_connection_count == other_connection_count) {
|
||||
// all connections are to the same external program eg jamin
|
||||
// "jamin:" -> "jamin"
|
||||
label << other_connection_type.substr(0, other_connection_type.size() - 1);
|
||||
have_label = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_label) {
|
||||
if (total_connection_count == 0) {
|
||||
// Disconnected
|
||||
label << "-";
|
||||
} else {
|
||||
// Odd configuration
|
||||
label << "*" << total_connection_count << "*";
|
||||
}
|
||||
}
|
||||
|
||||
switch (width) {
|
||||
case Wide:
|
||||
label_string = label.str().substr(0, 6);
|
||||
break;
|
||||
case Narrow:
|
||||
label_string = label.str().substr(0, 3);
|
||||
break;
|
||||
}
|
||||
|
||||
label_cstr = new char[label_string.size() + 1];
|
||||
strcpy(label_cstr, label_string.c_str());
|
||||
|
||||
if (for_input) {
|
||||
input_label.set_text (label_cstr);
|
||||
} else {
|
||||
output_label.set_text (label_cstr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MixerStrip::update_input_display ()
|
||||
{
|
||||
ARDOUR::BundleList const c = _route->input()->bundles_connected();
|
||||
|
||||
if (c.size() > 1) {
|
||||
input_label.set_text (_("Inputs"));
|
||||
} else if (c.size() == 1) {
|
||||
input_label.set_text (c[0]->name ());
|
||||
} else {
|
||||
switch (_width) {
|
||||
case Wide:
|
||||
input_label.set_text (_(" Input"));
|
||||
break;
|
||||
case Narrow:
|
||||
input_label.set_text (_("I"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
panners.setup_pan ();
|
||||
update_io_button (_route, _width, true);
|
||||
panners.setup_pan ();
|
||||
}
|
||||
|
||||
void
|
||||
MixerStrip::update_output_display ()
|
||||
{
|
||||
ARDOUR::BundleList const c = _route->output()->bundles_connected ();
|
||||
|
||||
/* XXX: how do we represent >1 connected bundle? */
|
||||
if (c.size() > 1) {
|
||||
output_label.set_text (_("Outputs"));
|
||||
} else if (c.size() == 1) {
|
||||
output_label.set_text (c[0]->name());
|
||||
} else {
|
||||
switch (_width) {
|
||||
case Wide:
|
||||
output_label.set_text (_("Output"));
|
||||
break;
|
||||
case Narrow:
|
||||
output_label.set_text (_("O"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gpm.setup_meters ();
|
||||
panners.setup_pan ();
|
||||
update_io_button (_route, _width, false);
|
||||
gpm.setup_meters ();
|
||||
panners.setup_pan ();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -38,6 +38,7 @@ class CAImportableSource : public ImportableSource {
|
||||
nframes_t length() const;
|
||||
nframes_t samplerate() const;
|
||||
void seek (nframes_t pos);
|
||||
nframes64_t natural_position() const { return 0; }
|
||||
|
||||
protected:
|
||||
mutable CAAudioFile af;
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
virtual nframes_t length() const = 0;
|
||||
virtual nframes_t samplerate() const = 0;
|
||||
virtual void seek (nframes_t pos) = 0;
|
||||
virtual nframes64_t natural_position() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -176,6 +176,7 @@ struct LV2World {
|
||||
SLV2Value srate;
|
||||
SLV2Value gtk_gui;
|
||||
SLV2Value external_gui;
|
||||
SLV2Value logarithmic;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ class ResampledImportableSource : public ImportableSource
|
||||
nframes_t length() const { return source->length(); }
|
||||
nframes_t samplerate() const { return source->samplerate(); }
|
||||
void seek (nframes_t pos) { source->seek (pos); }
|
||||
nframes64_t natural_position() const { return source->natural_position(); }
|
||||
|
||||
static const uint32_t blocksize;
|
||||
|
||||
|
||||
@@ -38,11 +38,13 @@ class SndFileImportableSource : public ImportableSource {
|
||||
nframes_t length() const;
|
||||
nframes_t samplerate() const;
|
||||
void seek (nframes_t pos);
|
||||
nframes64_t natural_position() const;
|
||||
|
||||
protected:
|
||||
SF_INFO sf_info;
|
||||
boost::shared_ptr<SNDFILE> in;
|
||||
|
||||
nframes_t timecode;
|
||||
int64_t get_timecode_info (SNDFILE*, SF_BROADCAST_INFO*, bool&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class SndFileSource : public AudioFileSource {
|
||||
int update_header (sframes_t when, struct tm&, time_t);
|
||||
int flush_header ();
|
||||
|
||||
sframes_t natural_position () const;
|
||||
nframes64_t natural_position () const;
|
||||
|
||||
sframes_t last_capture_start_frame() const;
|
||||
void mark_capture_start (sframes_t);
|
||||
|
||||
@@ -66,7 +66,7 @@ class Source : public SessionObject, public boost::noncopyable
|
||||
|
||||
virtual const Glib::ustring& path() const = 0;
|
||||
|
||||
virtual sframes_t natural_position() const { return 0; }
|
||||
virtual nframes64_t natural_position() const { return 0; }
|
||||
|
||||
void mark_for_remove();
|
||||
|
||||
|
||||
@@ -211,7 +211,8 @@ map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
|
||||
|
||||
static bool
|
||||
create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
|
||||
uint samplerate, vector<boost::shared_ptr<Source> >& newfiles)
|
||||
uint samplerate, vector<boost::shared_ptr<Source> >& newfiles,
|
||||
nframes64_t timeline_position)
|
||||
{
|
||||
for (vector<string>::const_iterator i = new_paths.begin();
|
||||
i != new_paths.end(); ++i)
|
||||
@@ -436,7 +437,7 @@ Session::import_audiofiles (ImportStatus& status)
|
||||
fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endl;
|
||||
status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
|
||||
} else {
|
||||
status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles);
|
||||
status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, source->natural_position());
|
||||
}
|
||||
|
||||
// copy on cancel/failure so that any files that were created will be removed below
|
||||
|
||||
@@ -1,14 +1,42 @@
|
||||
#include "ardour/sndfileimportable.h"
|
||||
#include <sndfile.h>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
|
||||
SndFileImportableSource::SndFileImportableSource (const string& path)
|
||||
: in (sf_open (path.c_str(), SFM_READ, &sf_info), sf_close)
|
||||
/* FIXME: this was copied from sndfilesource.cc, at some point these should be merged */
|
||||
int64_t
|
||||
SndFileImportableSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists)
|
||||
{
|
||||
if (sf_command (sf, SFC_GET_BROADCAST_INFO, binfo, sizeof (*binfo)) != SF_TRUE) {
|
||||
exists = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
exists = true;
|
||||
int64_t ret = (uint32_t) binfo->time_reference_high;
|
||||
ret <<= 32;
|
||||
ret |= (uint32_t) binfo->time_reference_low;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SndFileImportableSource::SndFileImportableSource (const string& path)
|
||||
{
|
||||
memset(&sf_info, 0 , sizeof(sf_info));
|
||||
in.reset( sf_open(path.c_str(), SFM_READ, &sf_info), sf_close);
|
||||
if (!in) throw failed_constructor();
|
||||
|
||||
SF_BROADCAST_INFO binfo;
|
||||
bool timecode_exists;
|
||||
|
||||
memset (&binfo, 0, sizeof (binfo));
|
||||
timecode = get_timecode_info (in.get(), &binfo, timecode_exists);
|
||||
|
||||
if (!timecode_exists) {
|
||||
timecode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SndFileImportableSource::~SndFileImportableSource ()
|
||||
@@ -46,3 +74,9 @@ SndFileImportableSource::seek (nframes_t /*pos*/)
|
||||
{
|
||||
sf_seek (in.get(), 0, SEEK_SET);
|
||||
}
|
||||
|
||||
nframes64_t
|
||||
SndFileImportableSource::natural_position () const
|
||||
{
|
||||
return timecode;
|
||||
}
|
||||
|
||||
@@ -87,8 +87,6 @@ class BarController : public Gtk::Frame
|
||||
virtual bool expose (GdkEventExpose *);
|
||||
virtual bool scroll (GdkEventScroll *);
|
||||
virtual bool entry_focus_out (GdkEventFocus*);
|
||||
virtual bool entry_input (double *);
|
||||
virtual bool entry_output ();
|
||||
|
||||
gint mouse_control (double x, GdkWindow* w, double scaling);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user