diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-03-17 17:39:21 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-03-17 17:39:21 +0000 |
commit | 5e836403adcb62a59141226baa32515ae7789661 (patch) | |
tree | 40e47327306f1328f504ce16b81981206572af5d | |
parent | 6097ce578b9dc4d51f421c2e4cca2de64948aa66 (diff) |
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
-rw-r--r-- | gtk2_ardour/SConscript | 10 | ||||
-rw-r--r-- | gtk2_ardour/ardour.colors | 8 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 49 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_canvas.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/main.cc | 15 | ||||
-rw-r--r-- | libs/ardour/ardour/diskstream.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/filesource.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/source.h | 6 | ||||
-rw-r--r-- | libs/ardour/audio_track.cc | 14 | ||||
-rw-r--r-- | libs/ardour/destructive_filesource.cc | 2 | ||||
-rw-r--r-- | libs/ardour/diskstream.cc | 59 | ||||
-rw-r--r-- | libs/ardour/externalsource.cc | 6 | ||||
-rw-r--r-- | libs/ardour/filesource.cc | 57 | ||||
-rw-r--r-- | libs/ardour/route.cc | 1 | ||||
-rw-r--r-- | libs/ardour/session.cc | 224 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 60 | ||||
-rw-r--r-- | libs/ardour/sndfilesource.cc | 2 | ||||
-rw-r--r-- | libs/ardour/source.cc | 112 |
20 files changed, 456 insertions, 186 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 53576302cf..09e5b7f7eb 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -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 diff --git a/gtk2_ardour/ardour.colors b/gtk2_ardour/ardour.colors index db01ef384b..cc514890fc 100644 --- a/gtk2_ardour/ardour.colors +++ b/gtk2_ardour/ardour.colors @@ -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 diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 88f1d05f3b..b68c1d3f6a 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -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, 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 (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 (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_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_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))); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index ecf9da747d..7312c5d596 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -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; diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 8db3ce7556..c18bf867cd 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -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); diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index 14330e2009..028c38ac74 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -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; diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index a163c125d7..a0436696b0 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -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 (); diff --git a/libs/ardour/ardour/filesource.h b/libs/ardour/ardour/filesource.h index af46596ec5..c7ae97c281 100644 --- a/libs/ardour/ardour/filesource.h +++ b/libs/ardour/ardour/filesource.h @@ -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]; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index d0da2fef26..24f15e97f5 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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&); diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 7a5e2eb23a..88a478a420 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -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; diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 85cd86632c..ae3d1719c7 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -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 diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc index 1ca6b5be5a..40138405b6 100644 --- a/libs/ardour/destructive_filesource.cc +++ b/libs/ardour/destructive_filesource.cc @@ -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); } diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index cd67659290..28da6c9c31 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -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*>(®ion->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) { diff --git a/libs/ardour/externalsource.cc b/libs/ardour/externalsource.cc index 568100ca44..4fb102a4a0 100644 --- a/libs/ardour/externalsource.cc +++ b/libs/ardour/externalsource.cc @@ -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* diff --git a/libs/ardour/filesource.cc b/libs/ardour/filesource.cc index b2fcc3d36d..ad8979173e 100644 --- a/libs/ardour/filesource.cc +++ b/libs/ardour/filesource.cc @@ -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; } + diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 18ce52dd43..84979fce6a 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -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()))) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 9b61b5d816..fd54981908 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -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) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 5bb7ad01e4..3bfcb97c70 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -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; + } } } diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 5db5f95c35..522f94b5c2 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -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 (); diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index fb09293fd5..ffb067733d 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -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& @@ -320,6 +315,25 @@ Source::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const } 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) { struct stat statbuf; @@ -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) { + off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData); + + /* 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"; - off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData); + nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte); + close (peakfile); - if ((nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte)) != sizeof (PeakData) * npeaks) { + 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; } + |