lots of fidgety work to get track renaming to work correctly now that we have to rename audio files too; some GUI tweaks

git-svn-id: svn://localhost/trunk/ardour2@404 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-03-17 17:39:21 +00:00
parent 6097ce578b
commit 5e836403ad
20 changed files with 457 additions and 187 deletions

View File

@ -188,6 +188,7 @@ fft_result.cc
""")
glade_files=glob.glob('glade/*.glade')
pixmap_files=glob.glob('pixmaps/*.xpm')
intl_files = gtkardour_files + glade_files + glob.glob('*.h')
@ -244,19 +245,20 @@ env.Alias('install', env.InstallAs(os.path.join(install_prefix, 'bin')+'/ardour'
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour2_ui.rc'))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.menus'))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.bindings'))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.colors'))
env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour'), 'splash.ppm'))
env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour/pixmaps'), pixmap_files))
env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour/glade'), glade_files))
#dist
env.Alias ('tarball', env.Distribute (env['DISTTREE'],
[ 'SConscript',
'i18n.h', 'gettext.h',
'editor_xpms', 'misc_xpms',
'crossfade_xpms.h', 'meter_xpms.h',
'ardour2_ui.rc', 'splash.ppm',
'ardour.menus', 'ardour.bindings'
'ardour.menus', 'ardour.bindings', 'ardour.colors',
'editor_xpms'
] +
gtkardour_files + vst_files + glade_files +
gtkardour_files + vst_files + glade_files + pixmap_files +
glob.glob('po/*.po') + glob.glob('*.h')))
# generate a prototype full-featured ardour_ui.rc file

View File

@ -1,8 +1,8 @@
cWaveForm 0.50 1.0 1.0 0.90
cWaveForm 0.0 0.0 0.0 0.80
cMutedWaveForm 0.35 0.35 0.35 1.0
cSelectedFrameBase 0.63 0.13 0.94 0.2
cFrameBase 0.0 0.0 0.0 0.25
cAudioTrackBase 0.30 0.30 0.30 0.25
cSelectedFrameBase 0.71 0.57 0.66 1.0
cFrameBase 0.75 0.75 0.76 1.0
cAudioTrackBase 0.79 0.80 0.85 0.41
cAudioTrackOutline 0.00 0.00 0.00 1.00
cAudioBusBase 0.90 0.82 0.90 0.41
cTempoBar 0.64 0.64 0.66 1.0

View File

@ -427,20 +427,18 @@ Editor::Editor (AudioEngine& eng)
edit_packer.set_col_spacings (0);
edit_packer.set_row_spacings (0);
edit_packer.set_homogeneous (false);
edit_packer.set_border_width (0);
edit_packer.set_name ("EditorWindow");
edit_packer.attach (edit_vscrollbar, 0, 1, 1, 3, FILL, FILL|EXPAND, 0, 0);
edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
edit_packer.attach (time_button_event_box, 1, 2, 0, 1, FILL, FILL, 0, 0);
edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0);
edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
edit_packer.attach (controls_layout, 1, 2, 1, 2, FILL, FILL|EXPAND, 0, 0);
edit_packer.attach (track_canvas_event_box, 2, 3, 1, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
edit_packer.attach (controls_layout, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
edit_frame.set_name ("BaseFrame");
edit_frame.set_shadow_type (SHADOW_IN);
edit_frame.add (edit_packer);
edit_packer.attach (edit_hscrollbar, 2, 3, 2, 3, FILL|EXPAND, FILL, 0, 0);
zoom_in_button.set_name ("EditorTimeButton");
zoom_out_button.set_name ("EditorTimeButton");
@ -637,20 +635,31 @@ Editor::Editor (AudioEngine& eng)
snapshot_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::snapshot_display_selection_changed));
snapshot_display.signal_button_press_event().connect (mem_fun (*this, &Editor::snapshot_display_button_press), false);
the_notebook.append_page (region_list_scroller, _("Regions"));
the_notebook.append_page (route_list_scroller, _("Tracks/Busses"));
the_notebook.append_page (snapshot_display_scroller, _("Snapshots"));
the_notebook.append_page (*edit_group_display_packer, _("Edit Groups"));
the_notebook.append_page (named_selection_scroller, _("Chunks"));
Gtk::Label* nlabel;
nlabel = manage (new Label (_("Regions")));
nlabel->set_angle (-90);
the_notebook.append_page (region_list_scroller, *nlabel);
nlabel = manage (new Label (_("Tracks/Busses")));
nlabel->set_angle (-90);
the_notebook.append_page (route_list_scroller, *nlabel);
nlabel = manage (new Label (_("Snapshots")));
nlabel->set_angle (-90);
the_notebook.append_page (snapshot_display_scroller, *nlabel);
nlabel = manage (new Label (_("Edit Groups")));
nlabel->set_angle (-90);
the_notebook.append_page (*edit_group_display_packer, *nlabel);
nlabel = manage (new Label (_("Chunks")));
nlabel->set_angle (-90);
the_notebook.append_page (named_selection_scroller, *nlabel);
the_notebook.set_show_tabs (true);
the_notebook.set_scrollable (true);
the_notebook.popup_enable ();
the_notebook.set_tab_pos (Gtk::POS_RIGHT);
TearOff *notebook_tearoff = manage (new TearOff (the_notebook, true));
notebook_tearoff->tearoff_window().set_size_request (200, 400);
edit_pane.pack1 (edit_frame, true, true);
edit_pane.pack2 (*notebook_tearoff, false, true);
edit_pane.pack1 (edit_packer, true, true);
edit_pane.pack2 (the_notebook, false, true);
edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));

View File

@ -672,7 +672,6 @@ class Editor : public PublicEditor
Gtk::HBox bottom_hbox;
Gtk::Table edit_packer;
Gtk::Frame edit_frame;
Gtk::VScrollbar edit_vscrollbar;
Gtk::Adjustment vertical_adjustment;

View File

@ -130,6 +130,7 @@ Editor::initialize_canvas ()
time_canvas.set_name ("EditorTimeCanvas");
time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
time_canvas.set_flags (CAN_FOCUS);
time_canvas.set_center_scroll_region (false);
meter_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, 0.0);
tempo_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height);

View File

@ -239,11 +239,18 @@ string
which_ui_rcfile ()
{
string rcfile;
char* env;
if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
rcfile = env;
} else {
rcfile = "ardour2_ui.rc";
}
rcfile = find_config_file (rcfile);
rcfile = find_config_file ("ardour2_ui.rc");
if (rcfile.length() == 0) {
warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR_UI_RC to point to a valid UI style file") << endmsg;
if (rcfile.empty()) {
warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR2_UI_RC to point to a valid UI style file") << endmsg;
}
return rcfile;

View File

@ -100,7 +100,7 @@ class DiskStream : public Stateful, public sigc::trackable
jack_nframes_t roll_delay() const { return _roll_delay; }
void set_roll_delay (jack_nframes_t);
void set_name (string str, void* src);
int set_name (string str, void* src);
string input_source (uint32_t n=0) const {
if (n < channels.size()) {
@ -244,6 +244,7 @@ class DiskStream : public Stateful, public sigc::trackable
void set_block_size (jack_nframes_t);
int internal_playback_seek (jack_nframes_t distance);
int can_internal_playback_seek (jack_nframes_t distance);
int rename_write_sources ();
void reset_write_sources (bool, bool force = false);
void non_realtime_input_change ();

View File

@ -54,12 +54,15 @@ class FileSource : public Source {
FileSource (const XMLNode&, jack_nframes_t rate);
~FileSource ();
int set_name (std::string str, bool destructive);
void set_allow_remove_if_empty (bool yn);
jack_nframes_t length() const { return _length; }
jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf);
void mark_for_remove();
string peak_path(string audio_path);
string old_peak_path(string audio_path);
string path() const { return _path; }
virtual int seek (jack_nframes_t frame) {return 0; }
@ -93,7 +96,8 @@ class FileSource : public Source {
string _take_id;
SampleFormat _sample_format;
int _sample_size;
bool allow_remove_if_empty;
static char bwf_country_code[3];
static char bwf_organization_code[4];
static char bwf_serial_number[13];

View File

@ -253,8 +253,9 @@ class Session : public sigc::trackable, public Stateful
static string template_dir ();
static void get_template_list (list<string>&);
static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
static string peak_path_from_audio_path (string);
static string old_peak_path_from_audio_path (string);
string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
void process (jack_nframes_t nframes);
@ -1498,6 +1499,7 @@ class Session : public sigc::trackable, public Stateful
RouteList routes;
mutable PBD::NonBlockingRWLock route_lock;
void add_route (Route*);
uint32_t destructive_index;
int load_routes (const XMLNode&);
Route* XMLRouteFactory (const XMLNode&);

View File

@ -56,6 +56,7 @@ class Source : public Stateful, public sigc::trackable
virtual ~Source ();
const string& name() const { return _name; }
ARDOUR::id_t id() const { return _id; }
/* returns the number of items in this `source' */
@ -103,10 +104,11 @@ class Source : public Stateful, public sigc::trackable
XMLNode& get_state ();
int set_state (const XMLNode&);
static int start_peak_thread ();
static void stop_peak_thread ();
int rename_peakfile (std::string newpath);
static void set_build_missing_peakfiles (bool yn) {
_build_missing_peakfiles = yn;
}
@ -125,7 +127,6 @@ class Source : public Stateful, public sigc::trackable
jack_nframes_t _length;
bool next_peak_clear_should_notify;
string peakpath;
int peakfile; /* fd */
time_t _timestamp;
string _captured_for;
@ -138,7 +139,6 @@ class Source : public Stateful, public sigc::trackable
int do_build_peak (jack_nframes_t, jack_nframes_t);
virtual jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const = 0;
virtual string peak_path(string audio_path) = 0;
virtual string old_peak_path(string audio_path) = 0;
static pthread_t peak_thread;
static bool have_peak_thread;

View File

@ -755,13 +755,23 @@ AudioTrack::toggle_monitor_input ()
int
AudioTrack::set_name (string str, void *src)
{
int ret;
if (record_enabled() && _session.actively_recording()) {
/* this messes things up if done while recording */
return -1;
}
diskstream->set_name (str, src);
return IO::set_name (str, src);
if (diskstream->set_name (str, src)) {
return -1;
}
/* save state so that the statefile fully reflects any filename changes */
if ((ret = IO::set_name (str, src)) == 0) {
_session.save_state ("");
}
return ret;
}
int

View File

@ -69,7 +69,6 @@ jack_nframes_t DestructiveFileSource::xfade_frames = 64;
DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format)
: FileSource (path, rate, repair_first, samp_format)
{
cerr << "DESTRUCTO DISK STREAM, " << _name << endl;
if (out_coefficient == 0) {
setup_standard_crossfades (rate);
}
@ -84,7 +83,6 @@ DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate,
DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate)
: FileSource (node, rate)
{
cerr << "from XML, DESTRUCTO DISK STREAM, " << _name << endl;
if (out_coefficient == 0) {
setup_standard_crossfades (rate);
}

View File

@ -69,6 +69,9 @@ DiskStream::DiskStream (Session &sess, const string &name, Flag flag)
/* prevent any write sources from being created */
in_set_state = true;
init (flag);
use_new_playlist ();
in_set_state = false;
@ -472,13 +475,27 @@ void
DiskStream::use_destructive_playlist ()
{
/* use the sources associated with the single full-extent region */
Playlist::RegionList* rl = _playlist->regions_at (0);
if (rl->empty()) {
throw failed_constructor();
}
AudioRegion* region = dynamic_cast<AudioRegion*> (rl->front());
if (region == 0) {
throw failed_constructor();
}
delete rl;
AudioRegion* region = dynamic_cast<AudioRegion*> (_playlist->regions_at (0)->front());
uint32_t n;
ChannelList::iterator chan;
for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
(*chan).write_source = dynamic_cast<FileSource*>(&region->source (n));
(*chan).write_source->set_allow_remove_if_empty (false);
}
/* the source list will never be reset for a destructive track */
@ -491,7 +508,7 @@ DiskStream::set_io (IO& io)
set_align_style_from_io ();
}
void
int
DiskStream::set_name (string str, void *src)
{
if (str != _name) {
@ -499,12 +516,14 @@ DiskStream::set_name (string str, void *src)
_name = str;
if (!in_set_state && recordable()) {
/* open new capture files so that they have the correct name */
reset_write_sources (false);
/* rename existing capture files so that they have the correct name */
return rename_write_sources ();
} else {
return -1;
}
}
return 0;
}
void
@ -2097,8 +2116,12 @@ DiskStream::set_state (const XMLNode& node)
if (!had_playlist) {
_playlist->set_orig_diskstream_id (_id);
}
if (capture_pending_node) {
if (!destructive() && capture_pending_node) {
/* destructive streams have one and only one source per channel,
and so they never end up in pending capture in any useful
sense.
*/
use_pending_capture_data (*capture_pending_node);
}
@ -2170,6 +2193,10 @@ DiskStream::use_new_write_source (uint32_t n)
chan.write_source->use ();
/* do not remove destructive files even if they are empty */
chan.write_source->set_allow_remove_if_empty (!destructive());
return 0;
}
@ -2213,6 +2240,22 @@ DiskStream::reset_write_sources (bool mark_write_complete, bool force)
}
}
int
DiskStream::rename_write_sources ()
{
ChannelList::iterator chan;
uint32_t n;
for (chan = channels.begin(), n = 0; chan != channels.end(); ++chan, ++n) {
if ((*chan).write_source != 0) {
(*chan).write_source->set_name (_name, destructive());
/* XXX what to do if one of them fails ? */
}
}
return 0;
}
void
DiskStream::set_block_size (jack_nframes_t nframes)
{

View File

@ -84,12 +84,6 @@ ExternalSource::peak_path (string audio_path)
return res;
}
string
ExternalSource::old_peak_path (string audio_path)
{
return peak_path (audio_path);
}
#ifdef HAVE_COREAUDIO
ExternalSource*

View File

@ -165,6 +165,7 @@ FileSource::init (string pathstr, bool must_exist, jack_nframes_t rate)
fd = -1;
remove_at_unref = false;
next_peak_clear_should_notify = false;
allow_remove_if_empty = true;
if (pathstr[0] != '/') {
@ -300,7 +301,7 @@ FileSource::init (string pathstr, bool must_exist, jack_nframes_t rate)
}
if ((ret = initialize_peakfile (new_file, _path))) {
error << string_compose (_("FileSource: cannot initialize peakfile for %1"), _path) << endmsg;
error << string_compose (_("FileSource: cannot initialize peakfile for %1 as %2"), _path, peakpath) << endmsg;
}
out:
@ -325,7 +326,7 @@ FileSource::~FileSource ()
if (fd >= 0) {
if (remove_at_unref || is_empty (_path)) {
if (remove_at_unref || (is_empty (_path) && allow_remove_if_empty)) {
unlink (_path.c_str());
unlink (peakpath.c_str());
}
@ -334,6 +335,41 @@ FileSource::~FileSource ()
}
}
void
FileSource::set_allow_remove_if_empty (bool yn)
{
allow_remove_if_empty = yn;
}
int
FileSource::set_name (string newname, bool destructive)
{
LockMonitor lm (_lock, __LINE__, __FILE__);
string oldpath = _path;
string newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
if (newpath.empty()) {
error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg;
return -1;
}
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
error << string_compose (_("cannot rename audio file for %1 to %2"), _name, newpath) << endmsg;
return -1;
}
_name = basename (newpath);
_path = newpath;
return rename_peakfile (peak_path (_path));
}
string
FileSource::peak_path (string audio_path)
{
return Session::peak_path_from_audio_path (audio_path);
}
int
FileSource::discover_chunks (bool silent)
{
@ -1230,9 +1266,9 @@ FileSource::is_empty (string path)
less than 1msec at typical sample rates.
*/
/* NOTE: 700 bytes is the size of a BWF header structure *plus* our minimal coding history */
/* NOTE: 698 bytes is the size of a BWF header structure *plus* our minimal coding history */
return (statbuf.st_size == 0 || statbuf.st_size == wave_header_size || statbuf.st_size == 700);
return (statbuf.st_size == 0 || statbuf.st_size == wave_header_size || statbuf.st_size == 698);
}
void
@ -1248,18 +1284,6 @@ FileSource::mark_streaming_write_completed ()
}
}
string
FileSource::peak_path(string audio_path)
{
return Session::peak_path_from_audio_path (audio_path);
}
string
FileSource::old_peak_path(string audio_path)
{
return Session::old_peak_path_from_audio_path (audio_path);
}
void
FileSource::mark_take (string id)
{
@ -1470,3 +1494,4 @@ FileSource::repair (string path, jack_nframes_t rate)
fclose (in);
return ret;
}

View File

@ -622,6 +622,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
pan (bufs, nbufs, nframes, offset, speed_quietning);
} else {
// cerr << "panner state = " << _panner->automation_state() << endl;
if (!_panner->empty() &&
(_panner->automation_state() & Play ||
((_panner->automation_state() & Touch) && !_panner->touching()))) {

View File

@ -1881,6 +1881,11 @@ Session::add_route (Route* route)
_control_out = route;
}
AudioTrack* at = dynamic_cast<AudioTrack*>(route);
if (at && at->mode() == Destructive) {
destructive_index++;
}
set_dirty();
save_state (_current_snapshot_name);
@ -2601,7 +2606,7 @@ void
Session::add_source (Source* source)
{
pair<SourceList::key_type, SourceList::mapped_type> entry;
{
LockMonitor lm (source_lock, __LINE__, __FILE__);
entry.first = source->id();
@ -2654,8 +2659,109 @@ Session::get_source (ARDOUR::id_t id)
return source;
}
FileSource *
Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
string
Session::peak_path_from_audio_path (string audio_path)
{
/* XXX hardly bombproof! fix me */
string res;
res = PBD::dirname (audio_path);
res = PBD::dirname (res);
res += '/';
res += peak_dir_name;
res += '/';
res += PBD::basename_nosuffix (audio_path);
res += ".peak";
return res;
}
string
Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
{
string look_for;
string old_basename = basename_nosuffix (oldname);
string new_legalized = legalize_for_path (newname);
/* note: we know (or assume) the old path is already valid */
if (destructive) {
/* destructive file sources have a name of the form:
/path/to/Tnnnn-NAME(%[LR])?.wav
the task here is to replace NAME with the new name.
*/
/* find last slash */
string dir;
string prefix;
string::size_type slash;
string::size_type dash;
if ((slash = path.find_last_of ('/')) == string::npos) {
return "";
}
dir = path.substr (0, slash+1);
/* '-' is not a legal character for the NAME part of the path */
if ((dash = path.find_last_of ('-')) == string::npos) {
return "";
}
prefix = path.substr (slash+1, dash-(slash+1));
path = dir;
path += prefix;
path += '-';
path += new_legalized;
path += ".wav"; /* XXX gag me with a spoon */
} else {
/* non-destructive file sources have a name of the form:
/path/to/NAME-nnnnn(%[LR])?.wav
the task here is to replace NAME with the new name.
*/
/* find last slash */
string dir;
string suffix;
string::size_type slash;
string::size_type dash;
if ((slash = path.find_last_of ('/')) == string::npos) {
return "";
}
dir = path.substr (0, slash+1);
/* '-' is not a legal character for the NAME part of the path */
if ((dash = path.find_last_of ('-')) == string::npos) {
return "";
}
suffix = path.substr (dash);
path = dir;
path += new_legalized;
path += suffix;
}
return path;
}
string
Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
{
string spath;
uint32_t cnt;
@ -2664,56 +2770,74 @@ Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
string legalized;
buf[0] = '\0';
legalized = legalize_for_path (ds.name());
legalized = legalize_for_path (name);
/* find a "version" of the file name that doesn't exist in
any of the possible directories.
*/
for (cnt = 1; cnt <= limit; ++cnt) {
for (cnt = (destructive ? destructive_index + 1 : 1); cnt <= limit; ++cnt) {
vector<space_and_path>::iterator i;
uint32_t existing = 0;
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
spath = (*i).path;
if (destructive) {
spath += tape_dir_name;
} else {
spath += sound_dir_name;
}
spath += '/';
spath += legalized;
if (ds.n_channels() < 2) {
snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
} else if (ds.n_channels() == 2) {
if (chan == 0) {
snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
if (destructive) {
if (nchan < 2) {
snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
} else if (nchan == 2) {
if (nchan == 0) {
snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
} else {
snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
}
} else if (nchan < 26) {
snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
} else {
snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
}
} else if (ds.n_channels() < 26) {
snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
} else {
snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
spath += '/';
spath += legalized;
if (nchan < 2) {
snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
} else if (nchan == 2) {
if (chan == 0) {
snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
} else {
snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
}
} else if (nchan < 26) {
snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
} else {
snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
}
}
if (access (buf, F_OK) == 0) {
existing++;
}
}
if (existing == 0) {
break;
}
}
if (cnt > limit) {
error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, ds.name()) << endmsg;
throw failed_constructor();
if (cnt > limit) {
error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
throw failed_constructor();
}
}
/* we now have a unique name for the file, but figure out where to
@ -2722,7 +2846,11 @@ Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
string foo = buf;
spath = discover_best_sound_dir ();
if (destructive) {
spath = tape_dir ();
} else {
spath = discover_best_sound_dir ();
}
string::size_type pos = foo.find_last_of ('/');
@ -2732,6 +2860,14 @@ Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
spath += foo.substr (pos + 1);
}
return spath;
}
FileSource *
Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
{
string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
/* this might throw failed_constructor(), which is OK */
if (destructive) {
@ -2944,40 +3080,6 @@ Session::is_auditioning () const
}
}
string
Session::peak_path_from_audio_path (string audio_path)
{
/* XXX hardly bombproof! fix me */
string res;
res = PBD::dirname (audio_path);
res = PBD::dirname (res);
res += '/';
res += peak_dir_name;
res += '/';
res += PBD::basename_nosuffix (audio_path);
res += ".peak";
return res;
}
string
Session::old_peak_path_from_audio_path (string audio_path)
{
/* This is a hangover from when audio and peak files
lived in the same directory. We need it to to
be able to open old sessions.
*/
/* XXX hardly bombproof! fix me */
string res = audio_path.substr (0, audio_path.find_last_of ('.'));
res += ".peak";
return res;
}
void
Session::set_all_solo (bool yn)
{

View File

@ -192,6 +192,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
pending_abort = false;
layer_model = MoveAddHigher;
xfade_model = ShortCrossfade;
destructive_index = 0;
/* allocate conversion buffers */
_conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4];
@ -401,13 +402,32 @@ Session::setup_raid_path (string path)
if (colons == 0) {
/* no multiple search path, just one directory (common case) */
/* no multiple search path, just one location (common case) */
sp.path = path;
sp.blocks = 0;
session_dirs.push_back (sp);
string fspath;
/* sounds dir */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += sound_dir_name;
fspath += ':';
/* tape dir */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
FileSource::set_search_path (path + sound_dir_name);
FileSource::set_search_path (fspath);
return;
}
@ -418,6 +438,9 @@ Session::setup_raid_path (string path)
sp.blocks = 0;
sp.path = remaining.substr (0, colon);
session_dirs.push_back (sp);
/* add sounds to file search path */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
@ -426,7 +449,14 @@ Session::setup_raid_path (string path)
fspath += sound_dir_name;
fspath += ':';
session_dirs.push_back (sp);
/* add tape dir to file search path */
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
fspath += ':';
remaining = remaining.substr (colon+1);
}
@ -436,11 +466,19 @@ Session::setup_raid_path (string path)
sp.blocks = 0;
sp.path = remaining;
fspath += ':';
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += sound_dir_name;
fspath += ':';
fspath += sp.path;
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
fspath += tape_dir_name;
session_dirs.push_back (sp);
}
@ -681,7 +719,7 @@ Session::save_state (string snapshot_name, bool pending)
if (!pending) {
bool was_dirty = dirty();
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
if (was_dirty) {
@ -1298,10 +1336,18 @@ Session::state(bool full_state)
/* Don't save information about FileSources that are empty */
FileSource* fs;
if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
if (fs->length() == 0) {
continue;
DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
/* destructive file sources are OK if they are empty, because
we will re-use them every time.
*/
if (!dfs) {
if (fs->length() == 0) {
continue;
}
}
}

View File

@ -87,7 +87,7 @@ SndFileSource::init (const string& idstr, bool build_peak)
_path = file;
if (build_peak) {
if (initialize_peakfile (false, file)) {
if (initialize_peakfile (false, _path)) {
sf_close (sf);
sf = 0;
throw failed_constructor ();

View File

@ -59,7 +59,6 @@ Source::Source (bool announce)
_use_cnt = 0;
_peaks_built = false;
next_peak_clear_should_notify = true;
peakfile = -1;
_timestamp = 0;
_read_data_count = 0;
_write_data_count = 0;
@ -70,7 +69,6 @@ Source::Source (const XMLNode& node)
_use_cnt = 0;
_peaks_built = false;
next_peak_clear_should_notify = true;
peakfile = -1;
_timestamp = 0;
_read_data_count = 0;
_write_data_count = 0;
@ -82,9 +80,6 @@ Source::Source (const XMLNode& node)
Source::~Source ()
{
if (peakfile >= 0) {
close (peakfile);
}
}
XMLNode&
@ -319,6 +314,25 @@ Source::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
return ret;
}
int
Source::rename_peakfile (string newpath)
{
/* caller must hold _lock */
string oldpath = peakpath;
if (access (oldpath.c_str(), F_OK) == 0) {
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
return -1;
}
}
peakpath = newpath;
return 0;
}
int
Source::initialize_peakfile (bool newfile, string audio_path)
{
@ -344,33 +358,6 @@ Source::initialize_peakfile (bool newfile, string audio_path)
return -1;
}
/* older sessions stored peaks in the same directory
as the audio. so check there as well.
*/
string oldpeakpath = old_peak_path (audio_path);
if (stat (oldpeakpath.c_str(), &statbuf)) {
if (errno == ENOENT) {
statbuf.st_size = 0;
} else {
/* it exists in the audio dir , but there is some kind of error */
error << string_compose(_("Source: cannot stat peakfile \"%1\" or \"%2\""), peakpath, oldpeakpath) << endmsg;
return -1;
}
} else {
/* we found it in the sound dir, where they lived once upon a time, in a land ... etc. */
peakpath = oldpeakpath;
}
} else {
/* we found it in the peaks dir */
@ -391,11 +378,6 @@ Source::initialize_peakfile (bool newfile, string audio_path)
}
}
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
build_peaks_from_scratch ();
}
@ -418,7 +400,8 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
PeakData* staging = 0;
Sample* raw_staging = 0;
char * workbuf = 0;
int peakfile = -1;
expected_peaks = (cnt / (double) frames_per_peak);
scale = npeaks/expected_peaks;
@ -474,11 +457,21 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
if (scale == 1.0) {
// cerr << "DIRECT PEAKS\n";
off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
if ((nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte)) != sizeof (PeakData) * npeaks) {
/* open, read, close */
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
// cerr << "DIRECT PEAKS\n";
nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
close (peakfile);
if (nread != sizeof (PeakData) * npeaks) {
cerr << "Source["
<< _name
<< "]: cannot read peaks from peakfile! (read only "
@ -537,6 +530,13 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
/* open ... close during out: handling */
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return 0;
}
while (nvisual_peaks < npeaks) {
if (i == stored_peaks_read) {
@ -669,6 +669,10 @@ Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start
}
out:
if (peakfile >= 0) {
close (peakfile);
}
if (staging) {
delete [] staging;
}
@ -734,7 +738,6 @@ Source::build_peaks ()
}
if (pr_signal) {
off_t fend = lseek (peakfile, 0, SEEK_END);
PeaksReady (); /* EMIT SIGNAL */
}
}
@ -754,6 +757,7 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
jack_nframes_t frames_read;
jack_nframes_t frames_to_read;
off_t first_peak_byte;
int peakfile = -1;
int ret = -1;
#ifdef DEBUG_PEAK_BUILD
@ -772,6 +776,11 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
workbuf = new char[max(frames_per_peak, cnt) * 4];
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
while (cnt) {
frames_to_read = min (frames_per_peak, cnt);
@ -810,6 +819,9 @@ Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
out:
delete [] peakbuf;
if (peakfile >= 0) {
close (peakfile);
}
if (workbuf)
delete [] workbuf;
return ret;
@ -856,13 +868,27 @@ Source::release ()
jack_nframes_t
Source::available_peaks (double zoom_factor) const
{
int peakfile;
off_t end;
if (zoom_factor < frames_per_peak) {
return length(); // peak data will come from the audio file
}
/* peak data comes from peakfile */
LockMonitor lm (_lock, __LINE__, __FILE__);
off_t end = lseek (peakfile, 0, SEEK_END);
if ((peakfile = ::open (peakpath.c_str(), O_RDONLY)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return 0;
}
{
LockMonitor lm (_lock, __LINE__, __FILE__);
end = lseek (peakfile, 0, SEEK_END);
}
close (peakfile);
return (end/sizeof(PeakData)) * frames_per_peak;
}