ardour/libs/evoral/src/Event.cpp
David Robillard a8aae56d92 Handle edits while playing precisely.
This avoids stuck notes if active notes are edited, but without stopping all
active notes in the region on any edit as before.

This implementation injects note ons in places that aren't actually note
starts.  Depending on how percussive the instrument is, this may not be
desired.  In the future, an option for this would be an improvement, but there
are other places where "start notes in the middle" is a reasonable option.  I
think that should be handled universally if we're to do it at all, so not
considering it a part of this fix for now.
2015-03-05 17:30:31 -05:00

179 lines
3.8 KiB
C++

/* This file is part of Evoral.
* Copyright (C) 2008 David Robillard <http://drobilla.net>
* Copyright (C) 2000-2008 Paul Davis
*
* Evoral 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.
*
* Evoral 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 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.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <glib.h>
#include "evoral/Event.hpp"
namespace Evoral {
static event_id_t _event_id_counter = 0;
event_id_t
event_id_counter()
{
return g_atomic_int_get (&_event_id_counter);
}
void
init_event_id_counter(event_id_t n)
{
g_atomic_int_set (&_event_id_counter, n);
}
event_id_t
next_event_id ()
{
return g_atomic_int_add (&_event_id_counter, 1);
}
#ifdef EVORAL_EVENT_ALLOC
template<typename Timestamp>
Event<Timestamp>::Event(EventType type, Timestamp time, uint32_t size, uint8_t* buf, bool alloc)
: _type(type)
, _original_time(time)
, _nominal_time(time)
, _size(size)
, _buf(buf)
, _id(-1)
, _owns_buf(alloc)
{
if (alloc) {
_buf = (uint8_t*)malloc(_size);
if (buf) {
memcpy(_buf, buf, _size);
} else {
memset(_buf, 0, _size);
}
}
}
template<typename Timestamp>
Event<Timestamp>::Event(EventType type,
Timestamp time,
uint32_t size,
const uint8_t* buf)
: _type(type)
, _original_time(time)
, _nominal_time(time)
, _size(size)
, _buf((uint8_t*)malloc(size))
, _id(-1)
, _owns_buf(true)
{
memcpy(_buf, buf, _size);
}
template<typename Timestamp>
Event<Timestamp>::Event(const Event& copy, bool owns_buf)
: _type(copy._type)
, _original_time(copy._original_time)
, _nominal_time(copy._nominal_time)
, _size(copy._size)
, _buf(copy._buf)
, _id(copy.id())
, _owns_buf(owns_buf)
{
if (owns_buf) {
_buf = (uint8_t*)malloc(_size);
if (copy._buf) {
memcpy(_buf, copy._buf, _size);
} else {
memset(_buf, 0, _size);
}
}
}
template<typename Timestamp>
Event<Timestamp>::~Event() {
if (_owns_buf) {
free(_buf);
}
}
template<typename Timestamp>
const Event<Timestamp>&
Event<Timestamp>::operator=(const Event& copy)
{
_id = copy.id(); // XXX is this right? do we want ID copy semantics?
_type = copy._type;
_original_time = copy._original_time;
_nominal_time = copy._nominal_time;
_owns_buf = copy._owns_buf;
if (_owns_buf) {
if (copy._buf) {
if (copy._size > _size) {
_buf = (uint8_t*)::realloc(_buf, copy._size);
}
memcpy(_buf, copy._buf, copy._size);
} else {
free(_buf);
_buf = NULL;
}
} else {
_buf = copy._buf;
}
_size = copy._size;
return *this;
}
template<typename Timestamp>
void
Event<Timestamp>::set (const uint8_t* buf, uint32_t size, Timestamp t)
{
if (_owns_buf) {
if (_size < size) {
_buf = (uint8_t*) ::realloc(_buf, size);
}
memcpy (_buf, buf, size);
} else {
/* XXX this is really dangerous given the
const-ness of buf. The API should really
intervene here.
*/
_buf = const_cast<uint8_t*> (buf);
}
_original_time = t;
_nominal_time = t;
_size = size;
}
template<typename Timestamp>
void
Event<Timestamp>::set_time (Timestamp t)
{
_nominal_time = t;
}
template<typename Timestamp>
void
Event<Timestamp>::set_original_time (Timestamp t)
{
_original_time = t;
}
#endif // EVORAL_EVENT_ALLOC
template class Event<Evoral::Beats>;
template class Event<double>;
template class Event<int64_t>;
} // namespace Evoral