mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-24 07:27:44 +01:00
Merged with trunk R1393.
git-svn-id: svn://localhost/ardour2/branches/midi@1395 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
cd37c36326
commit
f9f5ec85fb
85 changed files with 5136 additions and 2848 deletions
|
|
@ -44,7 +44,6 @@ buffer_set.cc
|
|||
meter.cc
|
||||
amp.cc
|
||||
panner.cc
|
||||
destructive_filesource.cc
|
||||
audiofilesource.cc
|
||||
audiofilter.cc
|
||||
audioregion.cc
|
||||
|
|
|
|||
|
|
@ -101,6 +101,10 @@ class AudioFileSource : public AudioSource {
|
|||
bool destructive() const { return (_flags & Destructive); }
|
||||
virtual bool set_destructive (bool yn) { return false; }
|
||||
|
||||
Flag flags() const { return _flags; }
|
||||
|
||||
void mark_immutable ();
|
||||
|
||||
/* this should really be protected, but C++ is getting stricter
|
||||
and creating slots from protected member functions is starting
|
||||
to cause issues.
|
||||
|
|
@ -125,12 +129,12 @@ class AudioFileSource : public AudioSource {
|
|||
|
||||
int init (string idstr, bool must_exist);
|
||||
|
||||
uint16_t channel;
|
||||
string _path;
|
||||
Flag _flags;
|
||||
string _take_id;
|
||||
int64_t timeline_position;
|
||||
bool file_is_new;
|
||||
uint16_t channel;
|
||||
|
||||
bool _is_embedded;
|
||||
static bool determine_embeddedness(string path);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class AudioRegion : public Region
|
|||
void set_envelope_active (bool yn);
|
||||
void set_default_envelope ();
|
||||
|
||||
int separate_by_channel (ARDOUR::Session&, vector<AudioRegion*>&) const;
|
||||
int separate_by_channel (ARDOUR::Session&, vector<boost::shared_ptr<AudioRegion> >&) const;
|
||||
|
||||
/* filter */
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@ class ConfigVariableBase {
|
|||
virtual void add_to_node (XMLNode& node) = 0;
|
||||
virtual bool set_from_node (const XMLNode& node, Owner owner) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
Owner _owner;
|
||||
|
||||
void notify ();
|
||||
void miss ();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
|
@ -41,10 +45,12 @@ class ConfigVariable : public ConfigVariableBase
|
|||
|
||||
virtual bool set (T val, Owner owner) {
|
||||
if (val == value) {
|
||||
miss ();
|
||||
return false;
|
||||
}
|
||||
value = val;
|
||||
_owner = (ConfigVariableBase::Owner)(_owner |owner);
|
||||
notify ();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +61,7 @@ class ConfigVariable : public ConfigVariableBase
|
|||
void add_to_node (XMLNode& node) {
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
cerr << "Config variable " << _name << " stored as " << ss.str() << endl;
|
||||
XMLNode* child = new XMLNode ("Option");
|
||||
child->add_property ("name", _name);
|
||||
child->add_property ("value", ss.str());
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ CONFIG_VARIABLE (HeaderFormat, native_file_header_format, "native-file-header-f
|
|||
|
||||
CONFIG_VARIABLE (uint32_t, osc_port, "osc-port", 3819)
|
||||
CONFIG_VARIABLE (bool, use_osc, "use-osc", true)
|
||||
CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", true)
|
||||
|
||||
/* crossfades */
|
||||
|
||||
|
|
@ -115,6 +114,7 @@ CONFIG_VARIABLE (bool, no_new_session_dialog, "no-new-session-dialog", false)
|
|||
CONFIG_VARIABLE (bool, use_vst, "use-vst", true)
|
||||
CONFIG_VARIABLE (uint32_t, subframes_per_frame, "subframes-per-frame", 100)
|
||||
CONFIG_VARIABLE (uint32_t, saved_history_depth, "save-history-depth", 100)
|
||||
CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false)
|
||||
|
||||
/* BWAV */
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace ARDOUR {
|
|||
class CoreAudioSource : public AudioFileSource {
|
||||
public:
|
||||
CoreAudioSource (ARDOUR::Session&, const XMLNode&);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path_plus_channel, Flag);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path, int chn, Flag);
|
||||
~CoreAudioSource ();
|
||||
|
||||
float sample_rate() const;
|
||||
|
|
|
|||
|
|
@ -167,8 +167,6 @@ class Crossfade : public PBD::StatefulDestructible, public boost::enable_shared_
|
|||
void initialize ();
|
||||
int compute (boost::shared_ptr<ARDOUR::AudioRegion>, boost::shared_ptr<ARDOUR::AudioRegion>, CrossfadeModel);
|
||||
bool update ();
|
||||
|
||||
void member_changed (ARDOUR::Change);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1702,7 +1702,6 @@ class Session : public PBD::StatefulDestructible
|
|||
|
||||
void config_changed (const char*);
|
||||
|
||||
void add_control_protocol (const ControlProtocolInfo* const, XMLNode*);
|
||||
XMLNode& get_control_protocol_state ();
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class SndFileSource : public AudioFileSource {
|
|||
public:
|
||||
/* constructor to be called for existing external-to-session files */
|
||||
|
||||
SndFileSource (Session&, std::string path, Flag flags);
|
||||
SndFileSource (Session&, std::string path, int chn, Flag flags);
|
||||
|
||||
/* constructor to be called for new in-session files */
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ class SndFileSource : public AudioFileSource {
|
|||
mutable float *interleave_buf;
|
||||
mutable nframes_t interleave_bufsize;
|
||||
|
||||
void init (string str);
|
||||
void init ();
|
||||
int open();
|
||||
void close();
|
||||
int setup_broadcast_info (nframes_t when, struct tm&, time_t);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class SourceFactory {
|
|||
static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
|
||||
|
||||
// MIDI sources will have to be hacked in here somehow
|
||||
static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
|
||||
static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true);
|
||||
static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name, bool destructive, nframes_t rate, bool announce = true);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -63,20 +63,22 @@ uint64_t AudioFileSource::header_position_offset = 0;
|
|||
/* XXX maybe this too */
|
||||
char AudioFileSource::bwf_serial_number[13] = "000000000000";
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
|
||||
: AudioSource (s, idstr), _flags (flags)
|
||||
AudioFileSource::AudioFileSource (Session& s, string path, Flag flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
channel (0)
|
||||
{
|
||||
/* constructor used for existing external to session files. file must exist already */
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (idstr);
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (path);
|
||||
|
||||
if (init (idstr, true)) {
|
||||
if (init (path, true)) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
|
||||
: AudioSource (s, path), _flags (flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
channel (0)
|
||||
{
|
||||
/* constructor used for new internal-to-session files. file cannot exist */
|
||||
_is_embedded = false;
|
||||
|
|
@ -88,6 +90,7 @@ AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, Samp
|
|||
|
||||
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
|
||||
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
|
||||
/* channel is set in set_state() */
|
||||
{
|
||||
/* constructor used for existing internal-to-session files. file must exist */
|
||||
|
||||
|
|
@ -195,7 +198,10 @@ XMLNode&
|
|||
AudioFileSource::get_state ()
|
||||
{
|
||||
XMLNode& root (AudioSource::get_state());
|
||||
root.add_property ("flags", enum_2_string (_flags));
|
||||
char buf[32];
|
||||
root.add_property (X_("flags"), enum_2_string (_flags));
|
||||
snprintf (buf, sizeof (buf), "%d", channel);
|
||||
root.add_property (X_("channel"), buf);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
|
@ -209,15 +215,18 @@ AudioFileSource::set_state (const XMLNode& node)
|
|||
}
|
||||
|
||||
if ((prop = node.property (X_("flags"))) != 0) {
|
||||
|
||||
_flags = Flag (string_2_enum (prop->value(), _flags));
|
||||
|
||||
} else {
|
||||
|
||||
_flags = Flag (0);
|
||||
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("channel"))) != 0) {
|
||||
channel = atoi (prop->value());
|
||||
} else {
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("name"))) != 0) {
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (prop->value());
|
||||
} else {
|
||||
|
|
@ -537,8 +546,7 @@ AudioFileSource::is_empty (Session& s, string path)
|
|||
{
|
||||
bool ret = false;
|
||||
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createReadable (DataType::AUDIO, s, path, NoPeakFile, false));
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, s, path, 0, NoPeakFile, false));
|
||||
|
||||
if (afs) {
|
||||
ret = (afs->length() == 0);
|
||||
|
|
@ -579,3 +587,9 @@ AudioFileSource::safe_file_extension(string file)
|
|||
#endif // HAVE_COREAUDIO
|
||||
file.rfind(".voc") == string::npos);
|
||||
}
|
||||
|
||||
void
|
||||
AudioFileSource::mark_immutable ()
|
||||
{
|
||||
_flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <ardour/audiofilter.h>
|
||||
#include <ardour/audiofilesource.h>
|
||||
#include <ardour/destructive_filesource.h>
|
||||
#include <ardour/region_factory.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include <locale.h>
|
||||
|
|
@ -327,7 +328,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
|
|||
nframes_t position, nframes_t cnt,
|
||||
uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
|
||||
{
|
||||
//cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
|
||||
nframes_t internal_offset;
|
||||
nframes_t buf_offset;
|
||||
|
|
@ -901,25 +902,44 @@ AudioRegion::recompute_at_start ()
|
|||
}
|
||||
|
||||
int
|
||||
AudioRegion::separate_by_channel (Session& session, vector<AudioRegion*>& v) const
|
||||
AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<AudioRegion> >& v) const
|
||||
{
|
||||
SourceList srcs;
|
||||
string new_name;
|
||||
int n;
|
||||
|
||||
for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) {
|
||||
if (_sources.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
|
||||
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||
|
||||
srcs.clear ();
|
||||
srcs.push_back (*i);
|
||||
|
||||
/* generate a new name */
|
||||
|
||||
if (session.region_name (new_name, _name)) {
|
||||
return -1;
|
||||
new_name = _name;
|
||||
|
||||
if (_sources.size() == 2) {
|
||||
if (n == 0) {
|
||||
new_name += "-L";
|
||||
} else {
|
||||
new_name += "-R";
|
||||
}
|
||||
} else {
|
||||
new_name += '-';
|
||||
new_name += ('0' + n + 1);
|
||||
}
|
||||
|
||||
/* create a copy with just one source */
|
||||
|
||||
v.push_back (new AudioRegion (srcs, _start, _length, new_name, _layer, _flags));
|
||||
boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, _flags);
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
|
||||
|
||||
v.push_back (ar);
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -317,3 +317,16 @@ Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
|
|||
#undef CONFIG_VARIABLE
|
||||
#undef CONFIG_VARIABLE_SPECIAL
|
||||
}
|
||||
|
||||
void
|
||||
ConfigVariableBase::notify ()
|
||||
{
|
||||
// placeholder for any debugging desired when a config variable is modified
|
||||
}
|
||||
|
||||
void
|
||||
ConfigVariableBase::miss ()
|
||||
{
|
||||
// placeholder for any debugging desired when a config variable
|
||||
// is set but to the same value as it already has
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,10 +324,25 @@ ControlProtocolManager::get_state (void)
|
|||
Glib::Mutex::Lock lm (protocols_lock);
|
||||
|
||||
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
|
||||
XMLNode* child = new XMLNode (X_("Protocol"));
|
||||
child->add_property (X_("name"), (*i)->name);
|
||||
child->add_property (X_("active"), (*i)->protocol ? "yes" : "no");
|
||||
root->add_child_nocopy (*child);
|
||||
|
||||
XMLNode * child;
|
||||
|
||||
if ((*i)->protocol) {
|
||||
child = &((*i)->protocol->get_state());
|
||||
child->add_property (X_("active"), "yes");
|
||||
// should we update (*i)->state here? probably.
|
||||
root->add_child_nocopy (*child);
|
||||
}
|
||||
else if ((*i)->state) {
|
||||
// keep ownership clear
|
||||
root->add_child_copy (*(*i)->state);
|
||||
}
|
||||
else {
|
||||
child = new XMLNode (X_("Protocol"));
|
||||
child->add_property (X_("name"), (*i)->name);
|
||||
child->add_property (X_("active"), "no");
|
||||
root->add_child_nocopy (*child);
|
||||
}
|
||||
}
|
||||
|
||||
return *root;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <pbd/error.h>
|
||||
#include <ardour/coreaudiosource.h>
|
||||
#include <ardour/utils.h>
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
#include <appleutility/CAStreamBasicDescription.h>
|
||||
|
|
@ -33,33 +34,22 @@ using namespace PBD;
|
|||
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
init ();
|
||||
}
|
||||
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& idstr, Flag flags)
|
||||
: AudioFileSource(s, idstr, flags)
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags)
|
||||
: AudioFileSource(s, path, flags),
|
||||
{
|
||||
init (idstr);
|
||||
channel = chn;
|
||||
init ();
|
||||
}
|
||||
|
||||
void
|
||||
CoreAudioSource::init (string idstr)
|
||||
CoreAudioSource::init ()
|
||||
{
|
||||
string::size_type pos;
|
||||
|
||||
tmpbuf = 0;
|
||||
tmpbufsize = 0;
|
||||
|
||||
_name = idstr;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
_path = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
_path = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
cerr << "CoreAudioSource::init() " << name() << endl;
|
||||
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
|
|
|
|||
|
|
@ -225,9 +225,6 @@ Crossfade::initialize ()
|
|||
_fade_in.add (_length, 1.0);
|
||||
_fade_in.thaw ();
|
||||
|
||||
// _in->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
|
||||
// _out->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
|
||||
|
||||
overlap_type = _in->coverage (_out->position(), _out->last_frame());
|
||||
layer_relation = (int32_t) (_in->layer() - _out->layer());
|
||||
}
|
||||
|
|
@ -597,26 +594,6 @@ Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioReg
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::member_changed (Change what_changed)
|
||||
{
|
||||
Change what_we_care_about = Change (Region::MuteChanged|
|
||||
Region::LayerChanged|
|
||||
BoundsChanged);
|
||||
|
||||
if (what_changed & what_we_care_about) {
|
||||
try {
|
||||
if (what_changed & what_we_care_about) {
|
||||
refresh ();
|
||||
}
|
||||
}
|
||||
|
||||
catch (NoCrossfadeHere& err) {
|
||||
// relax, Invalidated inside refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Crossfade::get_state ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -410,7 +410,7 @@ DestructiveFileSource::handle_header_position_change ()
|
|||
}
|
||||
|
||||
void
|
||||
DestructiveFileSource::set_timeline_position (int64_t)
|
||||
DestructiveFileSource::set_timeline_position (int64_t pos)
|
||||
{
|
||||
//destructive track timeline postion does not change except at instantion or when header_position_offset (session start) changes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1354,8 +1354,10 @@ IO::set_state (const XMLNode& node)
|
|||
set_automation_state (*(*iter)->children().front());
|
||||
}
|
||||
|
||||
if ((*iter)->name() == X_("gaincontrol")) {
|
||||
_gain_control.set_state (**iter);
|
||||
if ((*iter)->name() == X_("controllable")) {
|
||||
if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
|
||||
_gain_control.set_state (**iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst,
|
|||
uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const
|
||||
{
|
||||
|
||||
//cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
|
||||
jack_nframes_t internal_offset = 0;
|
||||
jack_nframes_t src_offset = 0;
|
||||
|
|
|
|||
|
|
@ -545,9 +545,10 @@ EqualPowerStereoPanner::set_state (const XMLNode& node)
|
|||
|
||||
for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) {
|
||||
|
||||
if ((*iter)->name() == X_("panner")) {
|
||||
|
||||
_control.set_state (**iter);
|
||||
if ((*iter)->name() == X_("controllable")) {
|
||||
if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") {
|
||||
_control.set_state (**iter);
|
||||
}
|
||||
|
||||
} else if ((*iter)->name() == X_("Automation")) {
|
||||
|
||||
|
|
|
|||
|
|
@ -606,11 +606,15 @@ Playlist::remove_region_internal (boost::shared_ptr<Region>region)
|
|||
void
|
||||
Playlist::get_equivalent_regions (boost::shared_ptr<Region> other, vector<boost::shared_ptr<Region> >& results)
|
||||
{
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if (Config->get_use_overlap_equivalency()) {
|
||||
if (Config->get_use_overlap_equivalency()) {
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if ((*i)->overlap_equivalent (other)) {
|
||||
results.push_back ((*i));
|
||||
} else if ((*i)->equivalent (other)) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if ((*i)->equivalent (other)) {
|
||||
results.push_back ((*i));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1647,13 +1647,19 @@ Route::_set_state (const XMLNode& node, bool call_base)
|
|||
_comment = cmt->content();
|
||||
|
||||
} else if (child->name() == X_("extra")) {
|
||||
|
||||
_extra_xml = new XMLNode (*child);
|
||||
} else if (child->name() == X_("solo")) {
|
||||
_solo_control.set_state (*child);
|
||||
_session.add_controllable (&_solo_control);
|
||||
} else if (child->name() == X_("mute")) {
|
||||
_mute_control.set_state (*child);
|
||||
_session.add_controllable (&_mute_control);
|
||||
|
||||
} else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) {
|
||||
|
||||
if (prop->value() == "solo") {
|
||||
_solo_control.set_state (*child);
|
||||
_session.add_controllable (&_solo_control);
|
||||
}
|
||||
else if (prop->value() == "mute") {
|
||||
_mute_control.set_state (*child);
|
||||
_session.add_controllable (&_mute_control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,7 +382,6 @@ Session::Session (AudioEngine &eng,
|
|||
if (master_out_channels) {
|
||||
shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
|
||||
r->set_remote_control_id (control_id);
|
||||
cerr << "master bus has remote control ID " << r->remote_control_id() << endl;
|
||||
|
||||
rl.push_back (r);
|
||||
} else {
|
||||
|
|
@ -410,6 +409,8 @@ Session::Session (AudioEngine &eng,
|
|||
|
||||
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
|
||||
|
||||
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
|
||||
|
||||
if (was_dirty) {
|
||||
DirtyChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
@ -1793,6 +1794,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
|
|||
|
||||
track->set_control_outs (cports);
|
||||
}
|
||||
|
||||
// assert (current_thread != RT_thread)
|
||||
|
||||
track->audio_diskstream()->non_realtime_input_change();
|
||||
|
||||
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
|
||||
track->set_remote_control_id (control_id);
|
||||
|
|
@ -3163,14 +3168,16 @@ Session::midi_path_from_name (string name)
|
|||
|
||||
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||
|
||||
spath = (*i).path;
|
||||
|
||||
// FIXME: different directory from audio?
|
||||
spath = (*i).path + sound_dir_name + "/" + legalized;
|
||||
spath += sound_dir(false) + "/" + legalized;
|
||||
|
||||
snprintf (buf, sizeof(buf), "%s-%u.mid", spath.c_str(), cnt);
|
||||
|
||||
if (access (buf, F_OK) == 0) {
|
||||
if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
|
||||
existing++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (existing == 0) {
|
||||
|
|
@ -3191,6 +3198,7 @@ Session::midi_path_from_name (string name)
|
|||
|
||||
// FIXME: different directory than audio?
|
||||
spath = discover_best_sound_dir ();
|
||||
spath += '/';
|
||||
|
||||
string::size_type pos = foo.find_last_of ('/');
|
||||
|
||||
|
|
@ -3618,7 +3626,7 @@ Session::remove_redirect (Redirect* redirect)
|
|||
nframes_t
|
||||
Session::available_capture_duration ()
|
||||
{
|
||||
float sample_bytes_on_disk;
|
||||
float sample_bytes_on_disk = 4.0; // keep gcc happy
|
||||
|
||||
switch (Config->get_native_file_data_format()) {
|
||||
case FormatFloat:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Session::memento_command_factory(XMLNode *n)
|
|||
{
|
||||
PBD::ID id;
|
||||
XMLNode *before = 0, *after = 0;
|
||||
XMLNode *child;
|
||||
XMLNode *child = 0;
|
||||
|
||||
/* get id */
|
||||
id = PBD::ID(n->property("obj_id")->value());
|
||||
|
|
|
|||
|
|
@ -1059,19 +1059,7 @@ XMLNode&
|
|||
Session::get_control_protocol_state ()
|
||||
{
|
||||
ControlProtocolManager& cpm (ControlProtocolManager::instance());
|
||||
XMLNode* node = new XMLNode (X_("ControlProtocols"));
|
||||
|
||||
cpm.foreach_known_protocol (bind (mem_fun (*this, &Session::add_control_protocol), node));
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
void
|
||||
Session::add_control_protocol (const ControlProtocolInfo* const cpi, XMLNode* node)
|
||||
{
|
||||
if (cpi->protocol) {
|
||||
node->add_child_nocopy (cpi->protocol->get_state());
|
||||
}
|
||||
return cpm.get_state();
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -48,30 +48,34 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou
|
|||
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
init ();
|
||||
|
||||
cerr << "SndFileSource @ " << _path << " channel = " << channel << endl;
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
SndFileSource::SndFileSource (Session& s, string path, int chn, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
{
|
||||
init (idstr);
|
||||
channel = chn;
|
||||
|
||||
init ();
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, idstr, flags, sfmt, hf)
|
||||
SndFileSource::SndFileSource (Session& s, string path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, path, flags, sfmt, hf)
|
||||
{
|
||||
int fmt = 0;
|
||||
|
||||
init (idstr);
|
||||
init ();
|
||||
|
||||
/* this constructor is used to construct new files, not open
|
||||
existing ones.
|
||||
|
|
@ -174,9 +178,8 @@ SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, Heade
|
|||
}
|
||||
|
||||
void
|
||||
SndFileSource::init (string idstr)
|
||||
SndFileSource::init ()
|
||||
{
|
||||
string::size_type pos;
|
||||
string file;
|
||||
|
||||
// lets try to keep the object initalizations here at the top
|
||||
|
|
@ -186,20 +189,10 @@ SndFileSource::init (string idstr)
|
|||
sf = 0;
|
||||
_broadcast_info = 0;
|
||||
|
||||
string tmp_name;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
tmp_name = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
tmp_name = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
if (is_embedded()) {
|
||||
_name = tmp_name;
|
||||
_name = _path;
|
||||
} else {
|
||||
_name = Glib::path_get_basename (tmp_name);
|
||||
_name = Glib::path_get_basename (_path);
|
||||
}
|
||||
|
||||
/* although libsndfile says we don't need to set this,
|
||||
|
|
@ -385,6 +378,7 @@ nframes_t
|
|||
SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
|
||||
{
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -440,6 +434,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
|
|||
nframes_t old_file_pos;
|
||||
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -563,6 +558,7 @@ int
|
|||
SndFileSource::flush_header ()
|
||||
{
|
||||
if (!writable() || (sf == 0)) {
|
||||
warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
|
||||
|
|
@ -572,6 +568,7 @@ int
|
|||
SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
|
||||
{
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,14 +131,13 @@ SourceFactory::create (Session& s, const XMLNode& node)
|
|||
|
||||
#ifdef HAVE_COREAUDIO
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (DataType type, Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (type == DataType::AUDIO) {
|
||||
|
||||
if (!(flags & Destructive)) {
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -149,7 +148,7 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -161,7 +160,7 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
|
||||
} else {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -171,6 +170,7 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
return ret;
|
||||
}
|
||||
|
||||
return boost::shared_ptr<Source>();
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, node));
|
||||
|
|
@ -187,11 +187,11 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (DataType type, Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (type == DataType::AUDIO) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
|
|
@ -203,10 +203,11 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
|
||||
return ret;
|
||||
|
||||
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
// FIXME: flags?
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, idstr, SMFSource::Flag(0)));
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, path, SMFSource::Flag(0)));
|
||||
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#include <pbd/failed_constructor.h>
|
||||
#include <pbd/error.h>
|
||||
|
||||
#include <midi++/types.h>
|
||||
#include <midi++/alsa_sequencer.h>
|
||||
#include <midi++/port_request.h>
|
||||
|
|
@ -35,42 +38,54 @@
|
|||
#define TR_VAL(v)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace MIDI;
|
||||
using namespace PBD;
|
||||
|
||||
snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
|
||||
|
||||
ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (PortRequest &req)
|
||||
: Port (req)
|
||||
, seq (0)
|
||||
, decoder (0)
|
||||
, encoder (0)
|
||||
, port_id (-1)
|
||||
{
|
||||
TR_FN();
|
||||
int err;
|
||||
if (0 <= (err = CreatePorts (req)) &&
|
||||
0 <= (err = snd_midi_event_new (1024, &decoder)) && // Length taken from ARDOUR::Session::midi_read ()
|
||||
0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
|
||||
snd_midi_event_init (decoder);
|
||||
snd_midi_event_init (encoder);
|
||||
_ok = true;
|
||||
req.status = PortRequest::OK;
|
||||
} else
|
||||
req.status = PortRequest::Unknown;
|
||||
|
||||
if (!seq && init_client (req.devname) < 0) {
|
||||
_ok = false;
|
||||
|
||||
} else {
|
||||
|
||||
if (0 <= (err = CreatePorts (req)) &&
|
||||
0 <= (err = snd_midi_event_new (1024, &decoder)) && // Length taken from ARDOUR::Session::midi_read ()
|
||||
0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
|
||||
snd_midi_event_init (decoder);
|
||||
snd_midi_event_init (encoder);
|
||||
_ok = true;
|
||||
req.status = PortRequest::OK;
|
||||
} else {
|
||||
req.status = PortRequest::Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
|
||||
{
|
||||
if (decoder)
|
||||
if (decoder) {
|
||||
snd_midi_event_free (decoder);
|
||||
if (encoder)
|
||||
}
|
||||
if (encoder) {
|
||||
snd_midi_event_free (encoder);
|
||||
if (seq)
|
||||
snd_seq_close (seq);
|
||||
}
|
||||
if (port_id >= 0) {
|
||||
snd_seq_delete_port (seq, port_id);
|
||||
}
|
||||
}
|
||||
|
||||
int ALSA_SequencerMidiPort::selectable () const
|
||||
int
|
||||
ALSA_SequencerMidiPort::selectable () const
|
||||
{
|
||||
struct pollfd pfd[1];
|
||||
if (0 <= snd_seq_poll_descriptors (seq, pfd, 1, POLLIN | POLLOUT)) {
|
||||
|
|
@ -118,7 +133,12 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timesta
|
|||
return totwritten;
|
||||
}
|
||||
|
||||
<<<<<<< .working
|
||||
int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
|
||||
=======
|
||||
int
|
||||
ALSA_SequencerMidiPort::read (byte *buf, size_t max)
|
||||
>>>>>>> .merge-right.r1393
|
||||
{
|
||||
TR_FN();
|
||||
int err;
|
||||
|
|
@ -142,27 +162,49 @@ int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
|
|||
return -ENOENT == err ? 0 : err;
|
||||
}
|
||||
|
||||
int ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
|
||||
int
|
||||
ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
|
||||
{
|
||||
int err;
|
||||
if (0 <= (err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX,
|
||||
(req.mode & O_NONBLOCK) ? SND_SEQ_NONBLOCK : 0))) {
|
||||
snd_seq_set_client_name (seq, req.devname);
|
||||
unsigned int caps = 0;
|
||||
if (req.mode == O_WRONLY || req.mode == O_RDWR)
|
||||
caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
|
||||
if (req.mode == O_RDONLY || req.mode == O_RDWR)
|
||||
caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
|
||||
err = snd_seq_create_simple_port (seq, req.tagname, caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
|
||||
if (err >= 0) {
|
||||
port_id = err;
|
||||
snd_seq_ev_clear (&SEv);
|
||||
snd_seq_ev_set_source (&SEv, port_id);
|
||||
snd_seq_ev_set_subs (&SEv);
|
||||
snd_seq_ev_set_direct (&SEv);
|
||||
} else
|
||||
snd_seq_close (seq);
|
||||
unsigned int caps = 0;
|
||||
|
||||
if (req.mode == O_WRONLY || req.mode == O_RDWR)
|
||||
caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
|
||||
if (req.mode == O_RDONLY || req.mode == O_RDWR)
|
||||
caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
|
||||
|
||||
if (0 <= (err = snd_seq_create_simple_port (seq, req.tagname, caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC))) {
|
||||
|
||||
port_id = err;
|
||||
|
||||
snd_seq_ev_clear (&SEv);
|
||||
snd_seq_ev_set_source (&SEv, port_id);
|
||||
snd_seq_ev_set_subs (&SEv);
|
||||
snd_seq_ev_set_direct (&SEv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
ALSA_SequencerMidiPort::init_client (std::string name)
|
||||
{
|
||||
static bool called = false;
|
||||
|
||||
if (called) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
called = true;
|
||||
|
||||
if (snd_seq_open (&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) >= 0) {
|
||||
snd_seq_set_client_name (seq, name.c_str());
|
||||
return 0;
|
||||
} else {
|
||||
warning << "The ALSA MIDI system is not available. No ports based on it will be created"
|
||||
<< endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,14 @@ class ALSA_SequencerMidiPort : public Port
|
|||
int read (byte *buf, size_t max, timestamp_t timestamp);
|
||||
|
||||
private:
|
||||
snd_seq_t *seq;
|
||||
snd_midi_event_t *decoder, *encoder;
|
||||
int port_id;
|
||||
snd_seq_event_t SEv;
|
||||
|
||||
int CreatePorts(PortRequest &req);
|
||||
|
||||
static int init_client (std::string name);
|
||||
static snd_seq_t* seq;
|
||||
};
|
||||
|
||||
}; /* namespace MIDI */
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ strip_whitespace_edges (string& str)
|
|||
{
|
||||
string::size_type i;
|
||||
string::size_type len;
|
||||
string::size_type s;
|
||||
string::size_type s = 0;
|
||||
|
||||
len = str.length();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue