summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-06-05 16:39:23 +0000
committerDavid Robillard <d@drobilla.net>2007-06-05 16:39:23 +0000
commit7852cc219cddcc86f747fed6616195f5a7642041 (patch)
treecaf501536c5947406f21607e4ad72046f7ee2032
parente9de0dec8a96d42ff0fd1ba406dfaba5f76ba2a0 (diff)
Save MIDI files to interchange/sessionname/midifiles (instead of audiofiles).
Fix some uninitialized variables in Streamview. Tempo-based SMF source (internally only). Horrible crash on MIDI record finish. git-svn-id: svn://localhost/ardour2/trunk@1955 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/midi_region_view.cc13
-rw-r--r--gtk2_ardour/streamview.cc2
-rw-r--r--gtk2_ardour/time_axis_view.cc2
-rw-r--r--libs/ardour/ardour/directory_names.h1
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/ardour/session_directory.h7
-rw-r--r--libs/ardour/ardour/smf_source.h4
-rw-r--r--libs/ardour/ardour/tempo.h2
-rw-r--r--libs/ardour/directory_names.cc1
-rw-r--r--libs/ardour/session_directory.cc13
-rw-r--r--libs/ardour/session_state.cc27
-rw-r--r--libs/ardour/smf_source.cc44
12 files changed, 96 insertions, 21 deletions
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index c3a7e1830d..2282752b6e 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -87,13 +87,14 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
set_colors ();
- boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion> (_region);
- mr->midi_source(0)->load_model();
+ if (wfd) {
+ midi_region()->midi_source(0)->load_model();
- begin_write();
- for (size_t i=0; i < mr->midi_source(0)->model().n_events(); ++i)
- add_event(mr->midi_source(0)->model().event_at(i));
- end_write();
+ begin_write();
+ for (size_t i=0; i < midi_region()->midi_source(0)->model().n_events(); ++i)
+ add_event(midi_region()->midi_source(0)->model().event_at(i));
+ end_write();
+ }
}
MidiRegionView::~MidiRegionView ()
diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc
index 2997661848..34b0238769 100644
--- a/gtk2_ardour/streamview.cc
+++ b/gtk2_ardour/streamview.cc
@@ -57,6 +57,8 @@ StreamView::StreamView (RouteTimeAxisView& tv)
, region_color(_trackview.color())
, stream_base_color(0xFFFFFFFF)
, layers(1)
+ , height(tv.height)
+ , layer_display(Overlaid)
, last_rec_data_frame(0)
{
/* set_position() will position the group */
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 1351ef9105..fdacf1178b 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -71,6 +71,8 @@ bool TimeAxisView::need_size_info = true;
TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Canvas& canvas)
: AxisView (sess),
editor (ed),
+ y_position(0),
+ order(0),
controls_table (2, 8)
{
if (need_size_info) {
diff --git a/libs/ardour/ardour/directory_names.h b/libs/ardour/ardour/directory_names.h
index ff327e6ad9..c0f1831718 100644
--- a/libs/ardour/ardour/directory_names.h
+++ b/libs/ardour/ardour/directory_names.h
@@ -8,6 +8,7 @@ namespace ARDOUR {
extern const char* const old_sound_dir_name;
extern const char* const sound_dir_name;
+extern const char* const midi_dir_name;
extern const char* const dead_sound_dir_name;
extern const char* const interchange_dir_name;
extern const char* const peak_dir_name;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 80362e45b5..6cf7f9530b 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -256,6 +256,7 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void> DirtyChanged;
std::string sound_dir (bool with_path = true) const;
+ std::string midi_dir (bool with_path = true) const;
std::string peak_dir () const;
std::string dead_sound_dir () const;
std::string automation_dir () const;
diff --git a/libs/ardour/ardour/session_directory.h b/libs/ardour/ardour/session_directory.h
index d23c135e0b..7662894042 100644
--- a/libs/ardour/ardour/session_directory.h
+++ b/libs/ardour/ardour/session_directory.h
@@ -53,6 +53,13 @@ public:
* of root_path()/interchange/session_name/audiofiles
*/
const path sound_path () const;
+
+ /**
+ * @return the absolute path to the directory in which
+ * the session stores MIDI files, ie
+ * root_path()/interchange/session_name/midifiles
+ */
+ const path midi_path () const;
/**
* @return The absolute path to the directory in which all
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index ed1a0edb76..b4a0ada555 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -91,6 +91,8 @@ class SMFSource : public MidiSource {
void load_model(bool lock=true);
void destroy_model();
+ uint16_t ppqn() const { return _ppqn; }
+
private:
int init (string idstr, bool must_exist);
@@ -110,6 +112,8 @@ class SMFSource : public MidiSource {
uint32_t read_var_len() const;
int read_event(MidiEvent& ev) const;
+ static const uint16_t _ppqn = 19200;
+
uint16_t _channel;
string _path;
Flag _flags;
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index 5e3e93e48b..2d8462a751 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -195,7 +195,7 @@ class TempoMap : public PBD::StatefulDestructible
BBTPointList *get_points (nframes_t start, nframes_t end) const;
- void bbt_time (nframes_t when, BBT_Time&) const;
+ void bbt_time (nframes_t when, BBT_Time&) const;
nframes_t frame_time (const BBT_Time&) const;
nframes_t bbt_duration_at (nframes_t, const BBT_Time&, int dir) const;
diff --git a/libs/ardour/directory_names.cc b/libs/ardour/directory_names.cc
index 82f420a144..becef7c519 100644
--- a/libs/ardour/directory_names.cc
+++ b/libs/ardour/directory_names.cc
@@ -6,6 +6,7 @@ namespace ARDOUR {
const char* const old_sound_dir_name = X_("sounds");
const char* const sound_dir_name = X_("audiofiles");
+const char* const midi_dir_name = X_("audiofiles");
const char* const peak_dir_name = X_("peaks");
const char* const dead_sound_dir_name = X_("dead_sounds");
const char* const interchange_dir_name = X_("interchange");
diff --git a/libs/ardour/session_directory.cc b/libs/ardour/session_directory.cc
index 91b2587eb7..4a9ff1b988 100644
--- a/libs/ardour/session_directory.cc
+++ b/libs/ardour/session_directory.cc
@@ -106,6 +106,19 @@ SessionDirectory::sound_path () const
}
const path
+SessionDirectory::midi_path () const
+{
+ // the new style sound directory
+ path l_midi_path(m_root_path);
+
+ l_midi_path /= interchange_dir_name;
+ l_midi_path /= basename(m_root_path);
+ l_midi_path /= midi_dir_name;
+
+ return l_midi_path;
+}
+
+const path
SessionDirectory::peak_path () const
{
return path(m_root_path) /= peak_dir_name;
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 285e3fd4c4..7f53f9c5b1 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -2037,6 +2037,33 @@ Session::sound_dir (bool with_path) const
}
string
+Session::midi_dir (bool with_path) const
+{
+ string res;
+ string full;
+
+ if (with_path) {
+ res = _path;
+ } else {
+ full = _path;
+ }
+
+ res += interchange_dir_name;
+ res += '/';
+ res += legalize_for_path (_name);
+ res += '/';
+ res += midi_dir_name;
+
+ if (with_path) {
+ full = res;
+ } else {
+ full += res;
+ }
+
+ return res;
+}
+
+string
Session::peak_dir () const
{
string res = _path;
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index e48e89a6e5..0bc02f3998 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -36,6 +36,8 @@
#include <ardour/session.h>
#include <ardour/midi_ring_buffer.h>
#include <ardour/midi_util.h>
+#include <ardour/tempo.h>
+#include <ardour/audioengine.h>
#include "i18n.h"
@@ -178,9 +180,9 @@ SMFSource::flush_header ()
assert(_fd);
- const uint16_t type = GUINT16_TO_BE(0); // SMF Type 0 (single track)
- const uint16_t ntracks = GUINT16_TO_BE(1); // Number of tracks (always 1 for Type 0)
- const uint16_t division = GUINT16_TO_BE(1920); // FIXME FIXME FIXME PPQN
+ const uint16_t type = GUINT16_TO_BE(0); // SMF Type 0 (single track)
+ const uint16_t ntracks = GUINT16_TO_BE(1); // Number of tracks (always 1 for Type 0)
+ const uint16_t division = GUINT16_TO_BE(_ppqn); // Pulses per beat
char data[6];
memcpy(data, &type, 2);
@@ -241,8 +243,8 @@ SMFSource::find_first_event_after(nframes_t start)
*
* File position MUST be at the beginning of a delta time, or this will die very messily.
* ev.buffer must be of size ev.size, and large enough for the event. The returned event
- * will have it's time field set to it's delta time (so it's the caller's responsibility
- * to calculate a real time for the event).
+ * will have it's time field set to it's delta time, in SMF tempo-based ticks, using the
+ * rate given by ppqn() (it is the caller's responsibility to calculate a real time).
*
* Returns event length (including status byte) on success, 0 if event was
* skipped (eg a meta event), or -1 on EOF (or end of track).
@@ -287,12 +289,14 @@ SMFSource::read_event(MidiEvent& ev) const
return ev.size;
}
+/** All stamps in audio frames */
nframes_t
SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const
{
//cerr << "SMF - read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl;
- nframes_t time = 0;
+ // 64 bits ought to be enough for anybody
+ uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
_read_data_count = 0;
@@ -307,6 +311,12 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
fseek(_fd, _header_size, 0);
+ // FIXME: assumes tempo never changes after start
+ const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
+ _session.engine().frame_rate());
+
+ uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * _ppqn);
+
while (!feof(_fd)) {
int ret = read_event(ev);
if (ret == -1) { // EOF
@@ -323,11 +333,12 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
time += ev.time; // accumulate delta time
ev.time = time; // set ev.time to actual time (relative to source start)
- if (ev.time >= start) {
- if (ev.time > start + cnt) {
+ if (ev.time >= start_ticks) {
+ if (ev.time < start_ticks + (cnt / frames_per_beat)) {
break;
} else {
- ev.time += stamp_offset;
+ ev.time = (nframes_t)(((ev.time / (double)_ppqn) * frames_per_beat)) + stamp_offset;
+ // write event time in absolute frames
dst.write(ev.time, ev.size, ev.buffer);
}
}
@@ -338,6 +349,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
return cnt;
}
+/** All stamps in audio frames */
nframes_t
SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
{
@@ -349,13 +361,16 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
fseek(_fd, 0, SEEK_END);
- // FIXME: start of source time?
+ // FIXME: assumes tempo never changes after start
+ const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
+ _session.engine().frame_rate());
for (size_t i=0; i < buf.size(); ++i) {
MidiEvent& ev = buf[i];
assert(ev.time >= _timeline_position);
ev.time -= _timeline_position;
- uint32_t delta_time = ev.time - _last_ev_time;
+ assert(ev.time >= _last_ev_time);
+ const uint32_t delta_time = (uint32_t)(ev.time - _last_ev_time) / frames_per_beat * _ppqn;
/*printf("SMF - writing event, delta = %u, size = %zu, data = ",
delta_time, ev.size);
@@ -366,10 +381,11 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
*/
size_t stamp_size = write_var_len(delta_time);
fwrite(ev.buffer, 1, ev.size, _fd);
- _last_ev_time += delta_time;
- _track_size += stamp_size + ev.size;
+ _track_size += stamp_size + ev.size;
_write_data_count += ev.size;
+
+ _last_ev_time = ev.time;
}
fflush(_fd);
@@ -765,7 +781,7 @@ SMFSource::load_model(bool lock)
fseek(_fd, _header_size, 0);
- nframes_t time = 0;
+ double time = 0;
MidiEvent ev;
int ret;