totally untested initial code for MidiPlaylistSource, to provide for compound MIDI...
authorPaul Davis <paul@linuxaudiosystems.com>
Sun, 29 May 2011 01:54:19 +0000 (01:54 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sun, 29 May 2011 01:54:19 +0000 (01:54 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@9626 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/midi_playlist.h
libs/ardour/ardour/midi_playlist_source.h [new file with mode: 0644]
libs/ardour/midi_playlist.cc
libs/ardour/midi_playlist_source.cc [new file with mode: 0644]
libs/ardour/source_factory.cc
libs/ardour/wscript

index 8116faedb2f71329ca911005478154e3d4686304..339e07faa1868a21b1d504e646db27a7dad8f555 100644 (file)
@@ -48,7 +48,7 @@ public:
 
        ~MidiPlaylist ();
 
-       framecnt_t read (MidiRingBuffer<framepos_t>& buf,
+       framecnt_t read (Evoral::EventSink<framepos_t>& buf,
                         framepos_t start, framecnt_t cnt, uint32_t chan_n = 0);
 
        int set_state (const XMLNode&, int version);
diff --git a/libs/ardour/ardour/midi_playlist_source.h b/libs/ardour/ardour/midi_playlist_source.h
new file mode 100644 (file)
index 0000000..85f7a96
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+    Copyright (C) 2011 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_midi_playlist_source_h__
+#define __ardour_midi_playlist_source_h__
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include "ardour/ardour.h"
+#include "ardour/midi_source.h"
+#include "ardour/playlist_source.h"
+
+namespace ARDOUR {
+
+class MidiPlaylist;
+
+class MidiPlaylistSource : public MidiSource, public PlaylistSource {
+  public:
+    virtual ~MidiPlaylistSource ();
+
+    bool empty() const;
+    framecnt_t length (framepos_t) const;
+
+    framecnt_t read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const;
+    framecnt_t write_unlocked (Sample *src, framecnt_t cnt);
+    
+    XMLNode& get_state ();
+    int set_state (const XMLNode&, int version);
+
+    void append_event_unlocked_beats(const Evoral::Event<Evoral::MusicalTime>& ev);
+    void append_event_unlocked_frames(const Evoral::Event<framepos_t>& ev, framepos_t source_start);
+    void load_model(bool lock=true, bool force_reload=false);
+    void destroy_model();
+
+    static void ensure_buffers_for_level (uint32_t);
+
+  protected:
+    friend class SourceFactory;
+
+    MidiPlaylistSource (Session&, const PBD::ID& orig, const std::string& name, boost::shared_ptr<MidiPlaylist>, uint32_t chn,
+                       frameoffset_t begin, framecnt_t len, Source::Flag flags);
+    MidiPlaylistSource (Session&, const XMLNode&);
+    
+    
+    void flush_midi();
+
+    framepos_t read_unlocked (Evoral::EventSink<framepos_t>& dst,
+                                     framepos_t position,
+                                     framepos_t start, framecnt_t cnt,
+                                     MidiStateTracker* tracker) const;
+    
+    framepos_t write_unlocked (MidiRingBuffer<framepos_t>& dst,
+                                          framepos_t position,
+                                          framecnt_t cnt);
+  private:
+    int set_state (const XMLNode&, int version, bool with_descendants);
+    framecnt_t _length;
+};
+        
+} /* namespace */
+
+#endif /* __ardour_midi_playlist_source_h__ */
index 0d2243da0fdc008edd0043973ff3959a4acae76d..aa58ea2446bdb928e8d9af0e0d97bca8113797da 100644 (file)
@@ -88,7 +88,7 @@ struct EventsSortByTime {
 
 /** Returns the number of frames in time duration read (eg could be large when 0 events are read) */
 framecnt_t
-MidiPlaylist::read (MidiRingBuffer<framepos_t>& dst, framepos_t start, framecnt_t dur, unsigned chan_n)
+MidiPlaylist::read (Evoral::EventSink<framepos_t>& dst, framepos_t start, framecnt_t dur, unsigned chan_n)
 {
        /* this function is never called from a realtime thread, so
           its OK to block (for short intervals).
diff --git a/libs/ardour/midi_playlist_source.cc b/libs/ardour/midi_playlist_source.cc
new file mode 100644 (file)
index 0000000..c39d5e2
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+    Copyright (C) 2011 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.
+*/
+
+#ifdef WAF_BUILD
+#include "libardour-config.h"
+#endif
+
+#include <vector>
+#include <cstdio>
+
+#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+
+#include "pbd/error.h"
+#include "pbd/convert.h"
+#include "pbd/enumwriter.h"
+
+#include "ardour/midi_playlist.h"
+#include "ardour/midi_playlist_source.h"
+#include "ardour/midi_region.h"
+#include "ardour/debug.h"
+#include "ardour/filename_extensions.h"
+#include "ardour/session.h"
+#include "ardour/session_directory.h"
+#include "ardour/session_playlists.h"
+#include "ardour/source_factory.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+MidiPlaylistSource::MidiPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<MidiPlaylist> p, 
+                                       uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags)
+       : Source (s, DataType::AUDIO, name)
+       , MidiSource (s, name, flags)
+       , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
+{
+       ensure_buffers_for_level (_level);
+}
+
+MidiPlaylistSource::MidiPlaylistSource (Session& s, const XMLNode& node)
+       : Source (s, node)
+       , MidiSource (s, node)
+       , PlaylistSource (s, node)
+{
+       /* PlaylistSources are never writable, renameable, removable or destructive */
+       _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
+
+       /* ancestors have already called ::set_state() in their XML-based
+          constructors.
+       */
+       
+       if (set_state (node, Stateful::loading_state_version, false)) {
+               throw failed_constructor ();
+       }
+}
+
+MidiPlaylistSource::~MidiPlaylistSource ()
+{
+}
+
+XMLNode&
+MidiPlaylistSource::get_state ()
+{
+       XMLNode& node (MidiSource::get_state ());
+
+       /* merge PlaylistSource state */
+
+       PlaylistSource::add_state (node);
+
+       return node;
+}
+
+       
+int
+MidiPlaylistSource::set_state (const XMLNode& node, int version) 
+{
+       return set_state (node, version, true);
+}
+
+int
+MidiPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants) 
+{
+       if (with_descendants) {
+               if (Source::set_state (node, version) || 
+                   MidiSource::set_state (node, version) ||
+                   PlaylistSource::set_state (node, version)) {
+                       return -1;
+               }
+       }
+
+       ensure_buffers_for_level (_level);
+
+       return 0;
+}
+
+framecnt_t
+MidiPlaylistSource::length (framepos_t)  const
+{
+       pair<framepos_t,framepos_t> extent = _playlist->get_extent();
+       return extent.second - extent.first;
+}
+
+framepos_t 
+MidiPlaylistSource::read_unlocked (Evoral::EventSink<framepos_t>& dst,
+                                  framepos_t position,
+                                  framepos_t start, framecnt_t cnt,
+                                  MidiStateTracker* tracker) const 
+{
+       boost::shared_ptr<MidiPlaylist> mp = boost::dynamic_pointer_cast<MidiPlaylist> (_playlist);
+
+       if (!mp) {
+               return 0;
+       }
+
+       return mp->read (dst, start, cnt);
+}
+
+framepos_t 
+MidiPlaylistSource::write_unlocked (MidiRingBuffer<framepos_t>& dst,
+                                   framepos_t position,
+                                   framecnt_t cnt) 
+{
+       fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::write_unlocked() called - should be impossible") << endmsg;
+       /*NOTREACHED*/
+       return 0;
+}
+
+void 
+MidiPlaylistSource::append_event_unlocked_beats(const Evoral::Event<Evoral::MusicalTime>& /*ev*/)
+{
+       fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_unlocked_beats() called - should be impossible") << endmsg;
+       /*NOTREACHED*/
+}
+
+void 
+MidiPlaylistSource::append_event_unlocked_frames(const Evoral::Event<framepos_t>& ev, framepos_t source_start)
+{
+       fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::append_event_unlocked_frames() called - should be impossible") << endmsg;
+       /*NOTREACHED*/
+}
+
+void
+MidiPlaylistSource::load_model (bool, bool) 
+{
+       fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::load_model() called - should be impossible") << endmsg;
+       /*NOTREACHED*/
+}
+
+void
+MidiPlaylistSource::destroy_model () 
+{
+       fatal << string_compose (_("programming error: %1"), "MidiPlaylistSource::destroy_model() called - should be impossible") << endmsg;
+       /*NOTREACHED*/
+}
+
+void
+MidiPlaylistSource::flush_midi ()
+{
+}
+
+
+bool
+MidiPlaylistSource::empty () const
+{
+       return !_playlist || _playlist->empty();
+}
+
+void
+MidiPlaylistSource::ensure_buffers_for_level (uint32_t level)
+{
+}
+
+
index afc92c450cc0105cc0e361341a1577eb061dce3e..5ff2a6f4e4363cfa6ff0ccbd2a31d46c865143be 100644 (file)
@@ -30,6 +30,8 @@
 
 #include "ardour/audioplaylist.h"
 #include "ardour/audio_playlist_source.h"
+#include "ardour/midi_playlist.h"
+#include "ardour/midi_playlist_source.h"
 #include "ardour/source_factory.h"
 #include "ardour/sndfilesource.h"
 #include "ardour/silentfilesource.h"
@@ -380,6 +382,29 @@ SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<
                }
 
        } else if (type == DataType::MIDI) {
+               
+               try {
+
+                       boost::shared_ptr<MidiPlaylist> ap = boost::dynamic_pointer_cast<MidiPlaylist>(p);
+                       
+                       if (ap) {
+                               
+                               if (copy) {
+                                       ap.reset (new MidiPlaylist (ap, start, len, name, true));
+                                       start = 0;
+                               }
+                               
+                               Source* src = new MidiPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
+                               boost::shared_ptr<Source> ret (src);
+                               
+                               SourceCreated (ret);
+                               return ret;
+                       }
+               }
+
+               catch (failed_constructor& err) {
+                       /* relax - return at function scope */
+               }
 
        }
 
index 97be5140f221bb2dd8871a97e0e10edbc3731d1a..2b1bf67b070cc500e0a447d313b5a4fb927fde52 100644 (file)
@@ -124,6 +124,7 @@ libardour_sources = [
         'midi_model.cc',
         'midi_patch_manager.cc',
         'midi_playlist.cc',
+        'midi_playlist_source.cc',
         'midi_port.cc',
         'midi_region.cc',
         'midi_ring_buffer.cc',