Fix note delete crash bug.
[ardour.git] / libs / ardour / midi_source.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3         Written by Dave Robillard, 2006
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <poll.h>
24 #include <float.h>
25 #include <cerrno>
26 #include <ctime>
27 #include <cmath>
28 #include <iomanip>
29 #include <algorithm>
30
31 #include <pbd/xml++.h>
32 #include <pbd/pthread_utils.h>
33
34 #include <ardour/midi_source.h>
35 #include <ardour/midi_ring_buffer.h>
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace ARDOUR;
41 using namespace PBD;
42
43 sigc::signal<void,MidiSource *> MidiSource::MidiSourceCreated;
44
45 MidiSource::MidiSource (Session& s, string name)
46         : Source (s, name, DataType::MIDI)
47         , _model(new MidiModel(s))
48         , _model_loaded (false)
49         , _writing (false)
50 {
51         _read_data_count = 0;
52         _write_data_count = 0;
53 }
54
55 MidiSource::MidiSource (Session& s, const XMLNode& node) 
56         : Source (s, node)
57         , _model(new MidiModel(s))
58         , _model_loaded (false)
59         , _writing (false)
60 {
61         _read_data_count = 0;
62         _write_data_count = 0;
63
64         if (set_state (node)) {
65                 throw failed_constructor();
66         }
67 }
68
69 MidiSource::~MidiSource ()
70 {
71 }
72
73 XMLNode&
74 MidiSource::get_state ()
75 {
76         XMLNode& node (Source::get_state());
77
78         if (_captured_for.length()) {
79                 node.add_property ("captured-for", _captured_for);
80         }
81
82         return node;
83 }
84
85 int
86 MidiSource::set_state (const XMLNode& node)
87 {
88         const XMLProperty* prop;
89
90         Source::set_state (node);
91
92         if ((prop = node.property ("captured-for")) != 0) {
93                 _captured_for = prop->value();
94         }
95
96         return 0;
97 }
98
99 nframes_t
100 MidiSource::read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const
101 {
102         Glib::Mutex::Lock lm (_lock);
103         if (_model_loaded && _model) {
104                 /*const size_t n_events = */_model->read(dst, start, cnt, stamp_offset);
105                 //cout << "Read " << n_events << " events from model." << endl;
106                 return cnt;
107         } else {
108                 return read_unlocked (dst, start, cnt, stamp_offset);
109         }
110 }
111
112 nframes_t
113 MidiSource::write (MidiRingBuffer& dst, nframes_t cnt)
114 {
115         Glib::Mutex::Lock lm (_lock);
116         return write_unlocked (dst, cnt);
117 }
118
119 bool
120 MidiSource::file_changed (string path)
121 {
122         struct stat stat_file;
123
124         int e1 = stat (path.c_str(), &stat_file);
125         
126         return ( !e1 );
127 }
128
129 void
130 MidiSource::mark_streaming_midi_write_started (NoteMode mode)
131 {
132         if (_model) {
133                 _model->set_note_mode(mode);
134                 _model->start_write();
135         }
136         
137         _writing = true;
138 }
139
140 void
141 MidiSource::mark_streaming_write_started ()
142 {
143         if (_model)
144                 _model->start_write();
145
146         _writing = true;
147 }
148
149 void
150 MidiSource::mark_streaming_write_completed ()
151 {
152         if (_model)
153                 _model->end_write(false); // FIXME: param?
154
155         _writing = false;
156 }
157