Split pretty much the entire GUI in 3. Audio and Midi "editor strips" and
[ardour.git] / libs / ardour / midi_region.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 <cmath>
21 #include <climits>
22 #include <cfloat>
23
24 #include <set>
25
26 #include <sigc++/bind.h>
27 #include <sigc++/class_slot.h>
28
29 #include <glibmm/thread.h>
30
31 #include <pbd/basename.h>
32 #include <pbd/xml++.h>
33
34 #include <ardour/midi_region.h>
35 #include <ardour/session.h>
36 #include <ardour/gain.h>
37 #include <ardour/dB.h>
38 #include <ardour/playlist.h>
39 #include <ardour/midi_source.h>
40
41 #include "i18n.h"
42 #include <locale.h>
43
44 using namespace std;
45 using namespace ARDOUR;
46
47 MidiRegionState::MidiRegionState (string why)
48         : RegionState (why)
49 {
50 }
51
52 MidiRegion::MidiRegion (MidiSource& src, jack_nframes_t start, jack_nframes_t length, bool announce)
53         : Region (start, length, PBD::basename_nosuffix(src.name()), 0,  Region::Flag(Region::DefaultFlags|Region::External))
54 {
55         /* basic MidiRegion constructor */
56
57         sources.push_back (&src);
58         master_sources.push_back (&src);
59         src.GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
60
61         save_state ("initial state");
62
63         if (announce) {
64                  CheckNewRegion (this); /* EMIT SIGNAL */
65         }
66 }
67
68 MidiRegion::MidiRegion (MidiSource& src, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t layer, Flag flags, bool announce)
69         : Region (start, length, name, layer, flags)
70 {
71         /* basic MidiRegion constructor */
72
73         sources.push_back (&src);
74         master_sources.push_back (&src);
75         src.GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
76
77         save_state ("initial state");
78
79         if (announce) {
80                  CheckNewRegion (this); /* EMIT SIGNAL */
81         }
82 }
83
84 MidiRegion::MidiRegion (SourceList& srcs, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t layer, Flag flags, bool announce)
85         : Region (start, length, name, layer, flags)
86 {
87         /* basic MidiRegion constructor */
88 #if 0
89         for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
90                 sources.push_back (*i);
91                 master_sources.push_back (*i);
92                 (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
93         }
94
95 {
96         /* create a new MidiRegion, that is part of an existing one */
97         
98         set<MidiSource*> unique_srcs;
99
100         for (SourceList::const_iterator i= other.sources.begin(); i != other.sources.end(); ++i) {
101                 sources.push_back (*i);
102                 (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
103                 unique_srcs.insert (*i);
104         }
105
106         for (SourceList::const_iterator i = other.master_sources.begin(); i != other.master_sources.end(); ++i) {
107                 if (unique_srcs.find (*i) == unique_srcs.end()) {
108                         (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
109                 }
110                 master_sources.push_back (*i);
111         }
112
113         save_state ("initial state");
114
115         if (announce) {
116                 CheckNewRegion (this); /* EMIT SIGNAL */
117         }
118 #endif
119 }
120
121 MidiRegion::MidiRegion (const MidiRegion &other)
122         : Region (other)
123 {
124         /* Pure copy constructor */
125
126         set<MidiSource*> unique_srcs;
127
128         for (SourceList::const_iterator i = other.sources.begin(); i != other.sources.end(); ++i) {
129                 sources.push_back (*i);
130                 (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
131                 unique_srcs.insert (*i);
132         }
133
134         for (SourceList::const_iterator i = other.master_sources.begin(); i != other.master_sources.end(); ++i) {
135                 master_sources.push_back (*i);
136                 if (unique_srcs.find (*i) == unique_srcs.end()) {
137                         (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
138                 }
139         }
140
141         save_state ("initial state");
142
143         /* NOTE: no CheckNewRegion signal emitted here. This is the copy constructor */
144 }
145
146 MidiRegion::MidiRegion (MidiSource& src, const XMLNode& node)
147         : Region (node)
148 {
149         sources.push_back (&src);
150         master_sources.push_back (&src);
151         src.GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
152
153         if (set_state (node)) {
154                 throw failed_constructor();
155         }
156
157         save_state ("initial state");
158
159         CheckNewRegion (this); /* EMIT SIGNAL */
160 }
161
162 MidiRegion::MidiRegion (SourceList& srcs, const XMLNode& node)
163         : Region (node)
164 {
165         /* basic MidiRegion constructor */
166
167         set<MidiSource*> unique_srcs;
168
169         for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
170                 sources.push_back (*i);
171                 (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
172                 unique_srcs.insert (*i);
173         }
174
175         for (SourceList::iterator i = srcs.begin(); i != srcs.end(); ++i) {
176                 master_sources.push_back (*i);
177                 if (unique_srcs.find (*i) == unique_srcs.end()) {
178                         (*i)->GoingAway.connect (mem_fun (*this, &MidiRegion::source_deleted));
179                 }
180         }
181
182         if (set_state (node)) {
183                 throw failed_constructor();
184         }
185
186         save_state ("initial state");
187
188         CheckNewRegion (this); /* EMIT SIGNAL */
189 }
190
191 MidiRegion::~MidiRegion ()
192 {
193         GoingAway (this);
194 }
195
196 StateManager::State*
197 MidiRegion::state_factory (std::string why) const
198 {
199         MidiRegionState* state = new MidiRegionState (why);
200
201         Region::store_state (*state);
202
203         return state;
204 }       
205
206 Change
207 MidiRegion::restore_state (StateManager::State& sstate) 
208 {
209         MidiRegionState* state = dynamic_cast<MidiRegionState*> (&sstate);
210
211         Change what_changed = Region::restore_and_return_flags (*state);
212         
213         if (_flags != Flag (state->_flags)) {
214                 
215                 //uint32_t old_flags = _flags;
216                 
217                 _flags = Flag (state->_flags);
218                 
219         }
220                 
221         /* XXX need a way to test stored state versus current for envelopes */
222
223         what_changed = Change (what_changed);
224
225         return what_changed;
226 }
227
228 UndoAction
229 MidiRegion::get_memento() const
230 {
231         return sigc::bind (mem_fun (*(const_cast<MidiRegion *> (this)), &StateManager::use_state), _current_state_id);
232 }
233
234 bool
235 MidiRegion::verify_length (jack_nframes_t len)
236 {
237         for (uint32_t n=0; n < sources.size(); ++n) {
238                 if (_start > sources[n]->length() - len) {
239                         return false;
240                 }
241         }
242         return true;
243 }
244
245 bool
246 MidiRegion::verify_start_and_length (jack_nframes_t new_start, jack_nframes_t new_length)
247 {
248         for (uint32_t n=0; n < sources.size(); ++n) {
249                 if (new_length > sources[n]->length() - new_start) {
250                         return false;
251                 }
252         }
253         return true;
254 }
255 bool
256 MidiRegion::verify_start (jack_nframes_t pos)
257 {
258         for (uint32_t n=0; n < sources.size(); ++n) {
259                 if (pos > sources[n]->length() - _length) {
260                         return false;
261                 }
262         }
263         return true;
264 }
265
266 bool
267 MidiRegion::verify_start_mutable (jack_nframes_t& new_start)
268 {
269         for (uint32_t n=0; n < sources.size(); ++n) {
270                 if (new_start > sources[n]->length() - _length) {
271                         new_start = sources[n]->length() - _length;
272                 }
273         }
274         return true;
275 }
276
277 jack_nframes_t
278 MidiRegion::read_at (unsigned char *buf, unsigned char *mixdown_buffer, char * workbuf, jack_nframes_t position, 
279                       jack_nframes_t cnt, 
280                       uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const
281 {
282         return _read_at (sources, buf, mixdown_buffer, workbuf, position, cnt, chan_n, read_frames, skip_frames);
283 }
284
285 jack_nframes_t
286 MidiRegion::master_read_at (unsigned char *buf, unsigned char *mixdown_buffer, char * workbuf, jack_nframes_t position, 
287                              jack_nframes_t cnt, uint32_t chan_n) const
288 {
289         return _read_at (master_sources, buf, mixdown_buffer, workbuf, position, cnt, chan_n, 0, 0);
290 }
291
292 jack_nframes_t
293 MidiRegion::_read_at (const SourceList& srcs, unsigned char *buf, unsigned char *mixdown_buffer, char * workbuf,
294                        jack_nframes_t position, jack_nframes_t cnt, 
295                        uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const
296 {
297         jack_nframes_t internal_offset;
298         jack_nframes_t buf_offset;
299         jack_nframes_t to_read;
300         
301         /* precondition: caller has verified that we cover the desired section */
302
303         if (chan_n >= sources.size()) {
304                 return 0; /* read nothing */
305         }
306         
307         if (position < _position) {
308                 internal_offset = 0;
309                 buf_offset = _position - position;
310                 cnt -= buf_offset;
311         } else {
312                 internal_offset = position - _position;
313                 buf_offset = 0;
314         }
315
316         if (internal_offset >= _length) {
317                 return 0; /* read nothing */
318         }
319         
320
321         if ((to_read = min (cnt, _length - internal_offset)) == 0) {
322                 return 0; /* read nothing */
323         }
324
325         if (opaque()) {
326                 /* overwrite whatever is there */
327                 mixdown_buffer = buf + buf_offset;
328         } else {
329                 mixdown_buffer += buf_offset;
330         }
331
332         if (muted()) {
333                 return 0; /* read nothing */
334         }
335
336         _read_data_count = 0;
337
338         if (srcs[chan_n]->read (mixdown_buffer, _start + internal_offset, to_read, workbuf) != to_read) {
339                 return 0; /* "read nothing" */
340         }
341
342         _read_data_count += srcs[chan_n]->read_data_count();
343
344         if (!opaque()) {
345
346                 /* gack. the things we do for users.
347                  */
348
349                 buf += buf_offset;
350
351                 for (jack_nframes_t n = 0; n < to_read; ++n) {
352                         buf[n] += mixdown_buffer[n];
353                 }
354         } 
355         
356         return to_read;
357 }
358         
359 XMLNode&
360 MidiRegion::get_state ()
361 {
362         return state (true);
363 }
364
365 XMLNode&
366 MidiRegion::state (bool full)
367 {
368         XMLNode& node (Region::state (full));
369 #if 0
370 //XMLNode *child;
371         char buf[64];
372         char buf2[64];
373         LocaleGuard lg (X_("POSIX"));
374         
375         snprintf (buf, sizeof (buf), "0x%x", (int) _flags);
376         node.add_property ("flags", buf);
377
378         for (uint32_t n=0; n < sources.size(); ++n) {
379                 snprintf (buf2, sizeof(buf2), "source-%d", n);
380                 snprintf (buf, sizeof(buf), "%" PRIu64, sources[n]->id());
381                 node.add_property (buf2, buf);
382         }
383
384         snprintf (buf, sizeof (buf), "%u", (uint32_t) sources.size());
385         node.add_property ("channels", buf);
386
387         if (full && _extra_xml) {
388                 node.add_child_copy (*_extra_xml);
389         }
390 #endif
391         return node;
392 }
393
394 int
395 MidiRegion::set_state (const XMLNode& node)
396 {
397         const XMLNodeList& nlist = node.children();
398         const XMLProperty *prop;
399         LocaleGuard lg (X_("POSIX"));
400
401         Region::set_state (node);
402
403         if ((prop = node.property ("flags")) != 0) {
404                 _flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
405
406                 _flags = Flag (_flags & ~Region::LeftOfSplit);
407                 _flags = Flag (_flags & ~Region::RightOfSplit);
408         }
409
410         /* Now find envelope description and other misc child items */
411                                 
412         for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
413                 
414                 XMLNode *child;
415                 //XMLProperty *prop;
416                 
417                 child = (*niter);
418         }
419
420         return 0;
421 }
422
423 int
424 MidiRegion::separate_by_channel (Session& session, vector<MidiRegion*>& v) const
425 {
426         SourceList srcs;
427         string new_name;
428
429         for (SourceList::const_iterator i = master_sources.begin(); i != master_sources.end(); ++i) {
430
431                 srcs.clear ();
432                 srcs.push_back (*i);
433
434                 /* generate a new name */
435                 
436                 if (session.region_name (new_name, _name)) {
437                         return -1;
438                 }
439
440                 /* create a copy with just one source */
441
442                 v.push_back (new MidiRegion (srcs, _start, _length, new_name, _layer, _flags));
443         }
444
445         return 0;
446 }
447
448 void
449 MidiRegion::source_deleted (Source* ignored)
450 {
451         delete this;
452 }
453
454 void
455 MidiRegion::lock_sources ()
456 {
457         SourceList::iterator i;
458         set<MidiSource*> unique_srcs;
459
460         for (i = sources.begin(); i != sources.end(); ++i) {
461                 unique_srcs.insert (*i);
462                 (*i)->use ();
463         }
464
465         for (i = master_sources.begin(); i != master_sources.end(); ++i) {
466                 if (unique_srcs.find (*i) == unique_srcs.end()) {
467                         (*i)->use ();
468                 }
469         }
470 }
471
472 void
473 MidiRegion::unlock_sources ()
474 {
475         SourceList::iterator i;
476         set<MidiSource*> unique_srcs;
477
478         for (i = sources.begin(); i != sources.end(); ++i) {
479                 unique_srcs.insert (*i);
480                 (*i)->release ();
481         }
482
483         for (i = master_sources.begin(); i != master_sources.end(); ++i) {
484                 if (unique_srcs.find (*i) == unique_srcs.end()) {
485                         (*i)->release ();
486                 }
487         }
488 }
489
490 vector<string>
491 MidiRegion::master_source_names ()
492 {
493         SourceList::iterator i;
494
495         vector<string> names;
496         for (i = master_sources.begin(); i != master_sources.end(); ++i) {
497                 names.push_back((*i)->name());
498         }
499
500         return names;
501 }
502
503 bool
504 MidiRegion::source_equivalent (const Region& o) const
505 {
506         const MidiRegion* other = dynamic_cast<const MidiRegion*>(&o);
507         if (!other)
508                 return false;
509
510         SourceList::const_iterator i;
511         SourceList::const_iterator io;
512
513         for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) {
514                 if ((*i)->id() != (*io)->id()) {
515                         return false;
516                 }
517         }
518
519         for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) {
520                 if ((*i)->id() != (*io)->id()) {
521                         return false;
522                 }
523         }
524
525         return true;
526 }
527
528 #if 0
529 int
530 MidiRegion::exportme (Session& session, AudioExportSpecification& spec)
531 {
532         const jack_nframes_t blocksize = 4096;
533         jack_nframes_t to_read;
534         int status = -1;
535
536         spec.channels = sources.size();
537
538         if (spec.prepare (blocksize, session.frame_rate())) {
539                 goto out;
540         }
541
542         spec.pos = 0;
543         spec.total_frames = _length;
544
545         while (spec.pos < _length && !spec.stop) {
546                 
547                 
548                 /* step 1: interleave */
549                 
550                 to_read = min (_length - spec.pos, blocksize);
551                 
552                 if (spec.channels == 1) {
553
554                         if (sources.front()->read (spec.dataF, _start + spec.pos, to_read, 0) != to_read) {
555                                 goto out;
556                         }
557
558                 } else {
559
560                         Sample buf[blocksize];
561
562                         for (uint32_t chan = 0; chan < spec.channels; ++chan) {
563                                 
564                                 if (sources[chan]->read (buf, _start + spec.pos, to_read, 0) != to_read) {
565                                         goto out;
566                                 }
567                                 
568                                 for (jack_nframes_t x = 0; x < to_read; ++x) {
569                                         spec.dataF[chan+(x*spec.channels)] = buf[x];
570                                 }
571                         }
572                 }
573                 
574                 if (spec.process (to_read)) {
575                         goto out;
576                 }
577                 
578                 spec.pos += to_read;
579                 spec.progress = (double) spec.pos /_length;
580                 
581         }
582         
583         status = 0;
584
585   out:  
586         spec.running = false;
587         spec.status = status;
588         spec.clear();
589         
590         return status;
591 }
592 #endif
593
594 Region*
595 MidiRegion::get_parent()
596 {
597 #if 0
598         Region* r = 0;
599
600         if (_playlist) {
601                 r = _playlist->session().find_whole_file_parent (*this);
602         }
603         
604         return r;
605 #endif
606         return NULL;
607 }
608
609
610 bool
611 MidiRegion::speed_mismatch (float sr) const
612 {
613 #if 0
614         if (sources.empty()) {
615                 /* impossible, but ... */
616                 return false;
617         }
618
619         float fsr = sources.front()->sample_rate();
620
621         return fsr == sr;
622 #endif
623         return false;
624 }
625