Genericificationalizeified AudioFilter (now Filter).
authorDavid Robillard <d@drobilla.net>
Mon, 6 Aug 2007 05:30:18 +0000 (05:30 +0000)
committerDavid Robillard <d@drobilla.net>
Mon, 6 Aug 2007 05:30:18 +0000 (05:30 +0000)
Added primitive (non-undoable, placeholder, etc) quantization.

git-svn-id: svn://localhost/ardour2/trunk@2254 d708f5d6-7413-0410-9779-e7cbd77b26cf

22 files changed:
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_region_view.h
gtk2_ardour/public_editor.h
gtk2_ardour/region_view.h
libs/ardour/SConscript
libs/ardour/ardour/audiofilter.h [deleted file]
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/filter.h [new file with mode: 0644]
libs/ardour/ardour/region.h
libs/ardour/ardour/reverse.h
libs/ardour/ardour/session.h
libs/ardour/audiofilter.cc [deleted file]
libs/ardour/audioregion.cc
libs/ardour/filter.cc [new file with mode: 0644]
libs/ardour/region.cc
libs/ardour/reverse.cc
libs/ardour/session_state.cc
libs/ardour/session_timefx.cc

index bb7ae142ecc8b76022294d96c94e14f5cc520dfb..8b087e70965691ee1812de628a8a4c48cde7cb84 100644 (file)
@@ -50,7 +50,7 @@
 #include <ardour/location.h>
 #include <ardour/audioplaylist.h>
 #include <ardour/audioregion.h>
-#include <ardour/region.h>
+#include <ardour/midi_region.h>
 #include <ardour/session_route.h>
 #include <ardour/tempo.h>
 #include <ardour/utils.h>
@@ -1531,7 +1531,7 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
        while (i != selection->regions.end() && boost::dynamic_pointer_cast<AudioRegion>((*i)->region()) == 0) {
                ++i;
        }
-       bool const have_selected_audio_region = (i != selection->regions.end());
+       const bool have_selected_audio_region = (i != selection->regions.end());
 
        if (have_selected_audio_region) {
 
@@ -1551,9 +1551,19 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
                items.push_back (MenuElem (_("Normalize"), mem_fun (*this, &Editor::normalize_regions)));
        }
        
-       items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_regions)));
-       items.push_back (SeparatorElem());
+       /* Find out if we have a selected MIDI region */
+       i = selection->regions.begin();
+       while (i != selection->regions.end() && boost::dynamic_pointer_cast<MidiRegion>((*i)->region()) == 0) {
+               ++i;
+       }
+       const bool have_selected_midi_region = (i != selection->regions.end());
+       
+       if (have_selected_midi_region) {
+
+               items.push_back (MenuElem (_("Quantize"), mem_fun(*this, &Editor::quantize_regions)));
+               items.push_back (SeparatorElem());
 
+       }
 
        /* range related stuff */
        
@@ -2200,24 +2210,24 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
                break;
 
        case SnapToAThirtysecondBeat:
-                start = session->tempo_map().round_to_beat_subdivision (start, 32);
-                break;
+               start = session->tempo_map().round_to_beat_subdivision (start, 32);
+               break;
 
        case SnapToASixteenthBeat:
-                start = session->tempo_map().round_to_beat_subdivision (start, 16);
-                break;
+               start = session->tempo_map().round_to_beat_subdivision (start, 16);
+               break;
 
        case SnapToAEighthBeat:
-                start = session->tempo_map().round_to_beat_subdivision (start, 8);
-                break;
+               start = session->tempo_map().round_to_beat_subdivision (start, 8);
+               break;
 
        case SnapToAQuarterBeat:
-                start = session->tempo_map().round_to_beat_subdivision (start, 4);
-                break;
+               start = session->tempo_map().round_to_beat_subdivision (start, 4);
+               break;
 
-        case SnapToAThirdBeat:
-                start = session->tempo_map().round_to_beat_subdivision (start, 3);
-                break;
+       case SnapToAThirdBeat:
+               start = session->tempo_map().round_to_beat_subdivision (start, 3);
+               break;
 
        case SnapToEditCursor:
                start = edit_cursor->current_frame;
@@ -2308,6 +2318,52 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
        }
 }
 
+double
+Editor::snap_length_beats (nframes_t start)
+{
+       if (!session) {
+               return 1.0;
+       }
+
+       const nframes64_t one_second = session->frame_rate();
+       const nframes64_t one_minute = session->frame_rate() * 60;
+       const nframes64_t one_smpte_second = (nframes64_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame());
+       nframes64_t one_smpte_minute = (nframes64_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame() * 60);
+       nframes64_t presnap = start;
+
+       /* FIXME: This could/should also work with non-tempo based snap settings (ie seconds) */
+
+       switch (snap_type) {
+       case SnapToBar:
+               return session->tempo_map().meter_at(start).beats_per_bar();
+
+       case SnapToBeat:
+               return 1.0;
+
+       case SnapToAThirtysecondBeat:
+               return 1.0 / (double)32.0;
+               break;
+
+       case SnapToASixteenthBeat:
+               return 1.0 / (double)16.0;
+               break;
+
+       case SnapToAEighthBeat:
+               return 1.0 / (double)8.0;
+               break;
+
+       case SnapToAQuarterBeat:
+               return 1.0 / (double)4.0;
+               break;
+
+       case SnapToAThirdBeat:
+               return 1.0 / (double)3.0;
+
+       default:
+               return 1.0;
+       }
+}
+
 void
 Editor::setup_toolbar ()
 {
index 62d25cb5e520edf1dbcfdf0439ac6b15966d43ae..8bf814a47242eedb78a867c99d71e291a6ea5874 100644 (file)
@@ -71,7 +71,7 @@ namespace ARDOUR {
        class TempoSection;
        class NamedSelection;
        class Session;
-       class AudioFilter;
+       class Filter;
        class Crossfade;
        class ChanCount;
 }
@@ -746,7 +746,7 @@ class Editor : public PublicEditor
 
        /* snapshots */
 
-       Gtk::ScrolledWindow      snapshot_display_scroller;
+       Gtk::ScrolledWindow snapshot_display_scroller;
        struct SnapshotDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
            SnapshotDisplayModelColumns() { 
                    add (visible_name);
@@ -892,6 +892,7 @@ class Editor : public PublicEditor
        void reverse_regions ();
        void normalize_regions ();
        void denormalize_regions ();
+       void quantize_regions ();
 
        void audition_region_from_region_list ();
        void hide_region_from_region_list ();
@@ -1288,6 +1289,8 @@ class Editor : public PublicEditor
                snap_to (first64, direction, for_mark);
                first = (nframes_t) first64;
        }
+       
+       double snap_length_beats (nframes_t start);
 
        uint32_t bbt_beat_subdivision;
 
@@ -1805,7 +1808,7 @@ class Editor : public PublicEditor
        
        /* audio filters */
 
-       void apply_filter (ARDOUR::AudioFilter&, string cmd);
+       void apply_filter (ARDOUR::Filter&, string cmd);
 
        /* handling cleanup */
 
index 86778fa11f2438b03f399793fd2f31349f5fcaa7..ee99ff6892ecb0dc763a3146347f69e1b3101476 100644 (file)
@@ -254,6 +254,8 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "normalize-region", _("Normalize Regions"), mem_fun(*this, &Editor::normalize_regions));
        ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "quantize-region", _("Quantize Regions"), mem_fun(*this, &Editor::quantize_regions));
+       ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "crop", _("crop"), mem_fun(*this, &Editor::crop_region_to_selection));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "insert-chunk", _("Insert Chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f));
index ccfcdbd6c55e81cc276d1049edecfdcdc44bb8c1..a82ca0260a98d6989a5efd457f08d4e0abb688de 100644 (file)
@@ -48,6 +48,7 @@
 #include <ardour/region_factory.h>
 #include <ardour/playlist_factory.h>
 #include <ardour/reverse.h>
+#include <ardour/quantize.h>
 
 #include "ardour_ui.h"
 #include "editor.h"
@@ -56,6 +57,7 @@
 #include "automation_time_axis.h"
 #include "streamview.h"
 #include "audio_region_view.h"
+#include "midi_region_view.h"
 #include "rgb_macros.h"
 #include "selection_templates.h"
 #include "selection.h"
@@ -3281,8 +3283,21 @@ Editor::reverse_regions ()
        apply_filter (rev, _("reverse regions"));
 }
 
+
+void
+Editor::quantize_regions ()
+{
+       if (!session) {
+               return;
+       }
+
+       // FIXME: varying meter?
+       Quantize quant (*session, snap_length_beats(0));
+       apply_filter (quant, _("quantize regions"));
+}
+
 void
-Editor::apply_filter (AudioFilter& filter, string command)
+Editor::apply_filter (Filter& filter, string command)
 {
        if (selection->regions.empty()) {
                return;
@@ -3293,26 +3308,31 @@ Editor::apply_filter (AudioFilter& filter, string command)
        track_canvas.get_window()->set_cursor (*wait_cursor);
        gdk_flush ();
 
+       /* this is ugly. */
        for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
-               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
-               if (!arv)
-                       continue;
+               RegionSelection::iterator tmp = r;
+               ++tmp;
 
-               boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
+               MidiRegionView* const mrv = dynamic_cast<MidiRegionView*>(*r);
+               if (mrv) {
+                       if (mrv->midi_region()->apply(filter) == 0) {
+                               mrv->redisplay_model();
+                       }
+               }
 
-               RegionSelection::iterator tmp;
-               
-               tmp = r;
-               ++tmp;
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
+               if (arv) {
+                       boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
 
-               if (arv->audio_region()->apply (filter) == 0) {
+                       if (arv->audio_region()->apply (filter) == 0) {
 
-                        XMLNode &before = playlist->get_state();
-                       playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
-                        XMLNode &after = playlist->get_state();
-                       session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
-               } else {
-                       goto out;
+                               XMLNode &before = playlist->get_state();
+                               playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
+                               XMLNode &after = playlist->get_state();
+                               session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
+                       } else {
+                               goto out;
+                       }
                }
 
                r = tmp;
index 5937b12ad99ee583700fb2b5b8e9b9d4ef6192d0..64693c7e6fd14ed982fd8458c6874e7d1887e034 100644 (file)
@@ -423,12 +423,6 @@ MidiRegionView::set_y_position_and_height (double y, double h)
        }
 }
 
-void
-MidiRegionView::show_region_editor ()
-{
-       cerr << "No MIDI region editor." << endl;
-}
-
 GhostRegion*
 MidiRegionView::add_ghost (AutomationTimeAxisView& atv)
 {
index d8c62abfe5059ad6b65cce5f4c1c97a90008dc58..f74272a409fbcbe7ffc13ee89bdfbf08ba0fe202 100644 (file)
@@ -68,8 +68,8 @@ class MidiRegionView : public RegionView
                { return midi_view()->midi_view(); }
        
        void set_y_position_and_height (double, double);
-    
-    void show_region_editor ();
+       
+       void redisplay_model();
 
     GhostRegion* add_ghost (AutomationTimeAxisView&);
 
@@ -164,7 +164,6 @@ class MidiRegionView : public RegionView
 
   private:
 
-       void redisplay_model();
        void clear_events();
 
        bool canvas_event(GdkEvent* ev);
index 746df6aaa9fb3915436891c631714e0a111c135e..97618dcbc21ee89ceb44c4918cb529f3c3964735 100644 (file)
@@ -115,6 +115,9 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
        
        /** Snap a value according to the current snap setting. */
        virtual void snap_to (nframes_t& first, int32_t direction = 0, bool for_mark = false) = 0;
+       
+       /** Get the current snap value in beats */
+       virtual double snap_length_beats (nframes_t start) = 0;
 
        /** Undo some transactions.
         * @param n Number of transactions to undo.
index 426529c5286f32164b3fc8bfc8328e0aa1c4f72a..28a2b11c0cdd0964976114f31d688a87bb4466d2 100644 (file)
@@ -70,7 +70,7 @@ class RegionView : public TimeAxisViewItem
        bool set_position(nframes_t pos, void* src, double* delta = 0);
        void fake_set_opaque (bool yn);
        
-       virtual void show_region_editor () = 0;
+       virtual void show_region_editor () {}
        virtual void hide_region_editor();
        
        virtual void region_changed (ARDOUR::Change);
index 5d56e198fb2b9204c59ba51277009ee180a588ab..a0070117e107e6058d871dc00565b0acbe2d05e8 100644 (file)
@@ -52,8 +52,8 @@ buffer_set.cc
 meter.cc
 amp.cc
 panner.cc
+filter.cc
 audiofilesource.cc
-audiofilter.cc
 audioregion.cc
 audiosource.cc
 midi_source.cc
@@ -99,6 +99,7 @@ recent_sessions.cc
 region.cc
 region_factory.cc
 reverse.cc
+quantize.cc
 route.cc
 route_group.cc
 send.cc
diff --git a/libs/ardour/ardour/audiofilter.h b/libs/ardour/ardour/audiofilter.h
deleted file mode 100644 (file)
index 6b60544..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-    Copyright (C) 2004 Paul Davis 
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef __ardour_audiofilter_h__
-#define __ardour_audiofilter_h__
-
-#include <vector>
-#include <ardour/audioregion.h>
-
-namespace ARDOUR {
-
-class AudioRegion;
-class Session;
-
-class AudioFilter {
-
-  public:
-       AudioFilter (ARDOUR::Session& s)
-               : session (s){}
-       virtual ~AudioFilter() {}
-
-       virtual int run (boost::shared_ptr<ARDOUR::AudioRegion>) = 0;
-       std::vector<boost::shared_ptr<ARDOUR::AudioRegion> > results;
-
-  protected:
-       ARDOUR::Session& session;
-
-       int make_new_sources (boost::shared_ptr<ARDOUR::AudioRegion>, ARDOUR::SourceList&);
-       int finish (boost::shared_ptr<ARDOUR::AudioRegion>, ARDOUR::SourceList&);
-};
-
-} /* namespace */
-
-#endif /* __ardour_audiofilter_h__ */
index 52a07679afdfb8db74e386da637761239fee1617..ddda1f4321ffdedaa90aa9d159454451bfc40d65 100644 (file)
@@ -38,7 +38,7 @@ namespace ARDOUR {
 class Route;
 class Playlist;
 class Session;
-class AudioFilter;
+class Filter;
 class AudioSource;
 
 class AudioRegion : public Region
@@ -115,10 +115,6 @@ class AudioRegion : public Region
 
        int separate_by_channel (ARDOUR::Session&, vector<boost::shared_ptr<AudioRegion> >&) const;
 
-       /* filter */
-
-       int apply (AudioFilter&);
-
        /* export */
 
        int exportme (ARDOUR::Session&, ARDOUR::AudioExportSpecification&);
diff --git a/libs/ardour/ardour/filter.h b/libs/ardour/ardour/filter.h
new file mode 100644 (file)
index 0000000..0e4c6b3
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+    Copyright (C) 2007 Paul Davis 
+    Author: Dave Robillard
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_filter_h__
+#define __ardour_filter_h__
+
+#include <vector>
+#include <ardour/region.h>
+
+namespace ARDOUR {
+
+class Region;
+class Session;
+
+class Filter {
+
+  public:
+       virtual ~Filter() {}
+
+       virtual int run (boost::shared_ptr<ARDOUR::Region>) = 0;
+       std::vector<boost::shared_ptr<ARDOUR::Region> > results;
+
+  protected:
+       Filter (ARDOUR::Session& s) : session(s) {}
+
+       int make_new_sources (boost::shared_ptr<ARDOUR::Region>, ARDOUR::SourceList&);
+       int finish (boost::shared_ptr<ARDOUR::Region>, ARDOUR::SourceList&);
+       
+       ARDOUR::Session& session;
+};
+
+} /* namespace */
+
+#endif /* __ardour_filter_h__ */
index c3aac3dfa881959ad563911aaaa84c6525fc2594..e6b799fdcf0ae8c7bb39291e4d84e0bb2439dd3c 100644 (file)
@@ -35,6 +35,7 @@ class XMLNode;
 namespace ARDOUR {
 
 class Playlist;
+class Filter;
 
 enum RegionEditState {
        EditChangesNothing = 0,
@@ -165,6 +166,8 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro
        void set_opaque (bool yn);
        void set_locked (bool yn);
        void set_position_locked (bool yn);
+       
+       int apply (Filter&);
 
        virtual uint32_t read_data_count() const { return _read_data_count; }
 
index 3296c77c6219a3f62963171aeb0f0b575ca05a69..7870b5aa2e2d9298199d7d3b8f436be814f4c30e 100644 (file)
 #ifndef __ardour_reverse_h__
 #define __ardour_reverse_h__
 
-#include <ardour/audiofilter.h>
+#include <ardour/filter.h>
 
 namespace ARDOUR {
 
-class Reverse : public AudioFilter {
+class Reverse : public Filter {
   public:
        Reverse (ARDOUR::Session&);
        ~Reverse ();
 
-       int run (boost::shared_ptr<ARDOUR::AudioRegion>);
+       int run (boost::shared_ptr<ARDOUR::Region>);
 };
 
 } /* namespace */
index 05d87620f21b5c2a9d80881c5d1d48bf38833a4e..63be24d9f797b926afe1bc4568c8f97d9b36ac62 100644 (file)
@@ -553,7 +553,7 @@ class Session : public PBD::StatefulDestructible
 
        int region_name (string& result, string base = string(""), bool newlevel = false) const;
        string new_region_name (string);
-       string path_from_region_name (string name, string identifier);
+       string path_from_region_name (DataType type, string name, string identifier);
 
        boost::shared_ptr<Region> find_whole_file_parent (boost::shared_ptr<Region const>);
        
diff --git a/libs/ardour/audiofilter.cc b/libs/ardour/audiofilter.cc
deleted file mode 100644 (file)
index d4d59d4..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-    Copyright (C) 2004 Paul Davis 
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <time.h>
-#include <cerrno>
-
-#include <pbd/basename.h>
-#include <ardour/sndfilesource.h>
-#include <ardour/session.h>
-#include <ardour/audioregion.h>
-#include <ardour/audiofilter.h>
-#include <ardour/region_factory.h>
-#include <ardour/source_factory.h>
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-
-int
-AudioFilter::make_new_sources (boost::shared_ptr<AudioRegion> region, SourceList& nsrcs)
-{
-       vector<string> names = region->master_source_names();
-
-       for (uint32_t i = 0; i < region->n_channels(); ++i) {
-
-               string path = session.path_from_region_name (PBD::basename_nosuffix (names[i]), string (""));
-
-               if (path.length() == 0) {
-                       error << string_compose (_("audiofilter: error creating name for new audio file based on %1"), region->name()) 
-                             << endmsg;
-                       return -1;
-               }
-
-               try {
-                       nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (
-                               SourceFactory::createWritable (DataType::AUDIO, session, path, false, session.frame_rate())));
-               } 
-
-               catch (failed_constructor& err) {
-                       error << string_compose (_("audiofilter: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-int
-AudioFilter::finish (boost::shared_ptr<AudioRegion> region, SourceList& nsrcs)
-{
-       string region_name;
-
-       /* update headers on new sources */
-
-       time_t xnow;
-       struct tm* now;
-
-       time (&xnow);
-       now = localtime (&xnow);
-
-       for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
-               boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*si);
-               if (afs) {
-                       afs->update_header (region->position(), *now, xnow);
-                       afs->mark_immutable ();
-               }
-       }
-
-       /* create a new region */
-
-       region_name = session.new_region_name (region->name());
-       results.clear ();
-       results.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (nsrcs, 0, region->length(), region_name, 0, 
-                                                                                           Region::Flag (Region::WholeFile|Region::DefaultFlags))));
-       
-       return 0;
-}
index dcf17ba2ea657d43de7a35ff509d6bbae1893176..58ece331c3f426d1609fe833f4e5a638115c8fef 100644 (file)
@@ -38,7 +38,6 @@
 #include <ardour/gain.h>
 #include <ardour/dB.h>
 #include <ardour/playlist.h>
-#include <ardour/audiofilter.h>
 #include <ardour/audiofilesource.h>
 #include <ardour/region_factory.h>
 #include <ardour/runtime_functions.h>
@@ -977,13 +976,6 @@ AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<Aud
        return 0;
 }
 
-int
-AudioRegion::apply (AudioFilter& filter)
-{
-       boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (shared_from_this());
-       return filter.run (ar);
-}
-
 nframes_t
 AudioRegion::read_raw_internal (Sample* buf, nframes_t pos, nframes_t cnt) const
 {
diff --git a/libs/ardour/filter.cc b/libs/ardour/filter.cc
new file mode 100644 (file)
index 0000000..f655f71
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+    Copyright (C) 2004-2007 Paul Davis 
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <time.h>
+#include <cerrno>
+
+#include <pbd/basename.h>
+#include <ardour/sndfilesource.h>
+#include <ardour/smf_source.h>
+#include <ardour/session.h>
+#include <ardour/region.h>
+#include <ardour/filter.h>
+#include <ardour/region_factory.h>
+#include <ardour/source_factory.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+int
+Filter::make_new_sources (boost::shared_ptr<Region> region, SourceList& nsrcs)
+{
+       vector<string> names = region->master_source_names();
+
+       for (uint32_t i = 0; i < region->n_channels(); ++i) {
+
+               string path = session.path_from_region_name (region->data_type(),
+                               PBD::basename_nosuffix (names[i]), string (""));
+
+               if (path.length() == 0) {
+                       error << string_compose (_("filter: error creating name for new file based on %1"), region->name()) 
+                             << endmsg;
+                       return -1;
+               }
+
+               try {
+                       nsrcs.push_back (boost::dynamic_pointer_cast<Source> (
+                               SourceFactory::createWritable (region->data_type(), session, path, false, session.frame_rate())));
+               } 
+
+               catch (failed_constructor& err) {
+                       error << string_compose (_("filter: error creating new file %1 (%2)"), path, strerror (errno)) << endmsg;
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int
+Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs)
+{
+       string region_name;
+
+       /* update headers on new sources */
+
+       time_t xnow;
+       struct tm* now;
+
+       time (&xnow);
+       now = localtime (&xnow);
+
+       /* this is ugly. */
+       for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
+               boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*si);
+               if (afs) {
+                       afs->update_header (region->position(), *now, xnow);
+                       afs->mark_immutable ();
+               }
+               
+               boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(*si);
+               if (smfs) {
+                       smfs->update_header (region->position(), *now, xnow);
+                       smfs->flush_footer ();
+               }
+       }
+
+       /* create a new region */
+
+       region_name = session.new_region_name (region->name());
+       results.clear ();
+       results.push_back (RegionFactory::create (nsrcs, 0, region->length(), region_name, 0, 
+                       Region::Flag (Region::WholeFile|Region::DefaultFlags)));
+       
+       return 0;
+}
+
+
index 8ac101282d3f09732c6becfc905550e9a8c4fdad..a828460bce39f8250e3b79314698bdb14a412e51 100644 (file)
@@ -34,6 +34,7 @@
 #include <ardour/session.h>
 #include <ardour/source.h>
 #include <ardour/region_factory.h>
+#include <ardour/filter.h>
 
 #include "i18n.h"
 
@@ -1265,3 +1266,10 @@ Region::get_parent() const
        return boost::shared_ptr<Region>();
 }
 
+int
+Region::apply (Filter& filter)
+{
+       return filter.run (shared_from_this());
+}
+
+
index c7ebecea317029172a8d927a7cb005421861b3ab..02ec2924b00025369100eb280d1135c808f5bebb 100644 (file)
@@ -33,7 +33,7 @@ using namespace std;
 using namespace ARDOUR;
 
 Reverse::Reverse (Session& s)
-       : AudioFilter (s)
+       : Filter (s)
 {
 }
 
@@ -42,7 +42,7 @@ Reverse::~Reverse ()
 }
 
 int
-Reverse::run (boost::shared_ptr<AudioRegion> region)
+Reverse::run (boost::shared_ptr<Region> r)
 {
        SourceList nsrcs;
        SourceList::iterator si;
@@ -53,6 +53,10 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
        nframes_t to_read;
        int ret = -1;
 
+       boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(r);
+       if (!region)
+               return ret;
+
        /* create new sources */
 
        if (make_new_sources (region, nsrcs)) {
index f6debff12350660d131f712ee72684fbfe03ae47..a7c8dc0200dc458209b39b3b1fd94901cadad0c8 100644 (file)
@@ -1502,19 +1502,24 @@ Session::get_sources_as_xml ()
 }
 
 string
-Session::path_from_region_name (string name, string identifier)
+Session::path_from_region_name (DataType type, string name, string identifier)
 {
        char buf[PATH_MAX+1];
        uint32_t n;
        SessionDirectory sdir(get_best_session_directory_for_new_source());
-       string sound_dir = sdir.sound_path().to_string();
+       string sound_dir = ((type == DataType::AUDIO)
+               ? sdir.sound_path().to_string()
+               : sdir.midi_path().to_string());
+
+       string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
 
        for (n = 0; n < 999999; ++n) {
                if (identifier.length()) {
-                       snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", sound_dir.c_str(), name.c_str(), 
-                                 identifier.c_str(), n);
+                       snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 "%s", sound_dir.c_str(), name.c_str(), 
+                                 identifier.c_str(), n, ext.c_str());
                } else {
-                       snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", sound_dir.c_str(), name.c_str(), n);
+                       snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 "%s", sound_dir.c_str(), name.c_str(),
+                                       n, ext.c_str());
                }
 
                if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
index aac77a59c74e2f57189dc71283cd0e83aef0826e..115d3eeeec5b8321c2d13e93d098b18caf108751 100644 (file)
@@ -85,7 +85,7 @@ Session::tempoize_region (TimeStretchRequest& tsr)
                        rstr = names[i];
                }
 
-               string path = path_from_region_name (PBD::basename_nosuffix (rstr), ident);
+               string path = path_from_region_name (DataType::AUDIO, PBD::basename_nosuffix (rstr), ident);
                
                if (path.length() == 0) {
                        error << string_compose (_("tempoize: error creating name for new audio file based on %1"), tsr.region->name())