summaryrefslogtreecommitdiff
path: root/libs/ardour/test/playlist_layering_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/test/playlist_layering_test.cc')
-rw-r--r--libs/ardour/test/playlist_layering_test.cc384
1 files changed, 290 insertions, 94 deletions
diff --git a/libs/ardour/test/playlist_layering_test.cc b/libs/ardour/test/playlist_layering_test.cc
index 1371b0cfae..23b22f9d90 100644
--- a/libs/ardour/test/playlist_layering_test.cc
+++ b/libs/ardour/test/playlist_layering_test.cc
@@ -1,13 +1,14 @@
-#include "midi++/manager.h"
-#include "pbd/textreceiver.h"
#include "pbd/compose.h"
-#include "ardour/session.h"
-#include "ardour/audioengine.h"
+#include "midi++/manager.h"
#include "ardour/playlist_factory.h"
#include "ardour/source_factory.h"
#include "ardour/region.h"
#include "ardour/region_factory.h"
+#include "ardour/session.h"
+#include "ardour/audiosource.h"
+#include "ardour/audioengine.h"
#include "playlist_layering_test.h"
+#include "test_receiver.h"
CPPUNIT_TEST_SUITE_REGISTRATION (PlaylistLayeringTest);
@@ -15,68 +16,28 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-class TestReceiver : public Receiver
-{
-protected:
- void receive (Transmitter::Channel chn, const char * str) {
- const char *prefix = "";
-
- switch (chn) {
- case Transmitter::Error:
- prefix = ": [ERROR]: ";
- break;
- case Transmitter::Info:
- /* ignore */
- return;
- case Transmitter::Warning:
- prefix = ": [WARNING]: ";
- break;
- case Transmitter::Fatal:
- prefix = ": [FATAL]: ";
- break;
- case Transmitter::Throw:
- /* this isn't supposed to happen */
- abort ();
- }
-
- /* note: iostreams are already thread-safe: no external
- lock required.
- */
-
- cout << prefix << str << endl;
-
- if (chn == Transmitter::Fatal) {
- exit (9);
- }
- }
-};
-
-TestReceiver test_receiver;
+int const PlaylistLayeringTest::num_regions = 6;
void
PlaylistLayeringTest::setUp ()
{
- string const test_session_path = "libs/ardour/test/playlist_layering_test";
- string const test_wav_path = "libs/ardour/test/playlist_layering_test/playlist_layering_test.wav";
- system (string_compose ("rm -rf %1", test_session_path).c_str());
+ TestNeedingSession::setUp ();
+ string const test_wav_path = "libs/ardour/test/test.wav";
- init (false, true);
- SessionEvent::create_per_thread_pool ("test", 512);
-
- test_receiver.listen_to (error);
- test_receiver.listen_to (info);
- test_receiver.listen_to (fatal);
- test_receiver.listen_to (warning);
-
- AudioEngine* engine = new AudioEngine ("test", "");
- MIDI::Manager::create (engine->jack ());
- CPPUNIT_ASSERT (engine->start () == 0);
-
- _session = new Session (*engine, test_session_path, "playlist_layering_test");
- engine->set_session (_session);
-
_playlist = PlaylistFactory::create (DataType::AUDIO, *_session, "test");
_source = SourceFactory::createWritable (DataType::AUDIO, *_session, test_wav_path, "", false, 44100);
+
+ system ("pwd");
+
+ /* Must write some data to our source, otherwise regions which use it will
+ be limited in whether they can be trimmed or not.
+ */
+ boost::shared_ptr<AudioSource> a = boost::dynamic_pointer_cast<AudioSource> (_source);
+ Sample silence[512];
+ memset (silence, 0, 512 * sizeof (Sample));
+ a->write (silence, 512);
+
+ _region = new boost::shared_ptr<Region>[num_regions];
}
void
@@ -84,68 +45,303 @@ PlaylistLayeringTest::tearDown ()
{
_playlist.reset ();
_source.reset ();
- for (int i = 0; i < 16; ++i) {
+ for (int i = 0; i < num_regions; ++i) {
_region[i].reset ();
}
- AudioEngine::instance()->remove_session ();
- delete _session;
- EnumWriter::destroy ();
- MIDI::Manager::destroy ();
- AudioEngine::destroy ();
+ delete[] _region;
+
+ TestNeedingSession::tearDown ();
}
void
-PlaylistLayeringTest::create_three_short_regions ()
+PlaylistLayeringTest::create_short_regions ()
{
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, 100);
- for (int i = 0; i < 3; ++i) {
+ for (int i = 0; i < num_regions; ++i) {
_region[i] = RegionFactory::create (_source, plist);
+ _region[i]->set_name (string_compose ("%1", char (int ('A') + i)));
}
}
void
-PlaylistLayeringTest::addHigherTest ()
+PlaylistLayeringTest::laterHigher_relayerOnAll_Test ()
+{
+ _session->config.set_layer_model (LaterHigher);
+ _session->config.set_relayer_on_all_edits (true);
+
+ create_short_regions ();
+
+ /* three overlapping regions */
+ _playlist->add_region (_region[A], 0);
+ _playlist->add_region (_region[B], 10);
+ _playlist->add_region (_region[C], 20);
+ /* and another non-overlapping one */
+ _playlist->add_region (_region[D], 200);
+
+ /* LaterHigher means that they should be arranged thus */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ _region[A]->set_position (5);
+
+ /* Region move should have no effect in LaterHigher mode */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* C -> bottom should give C A B, not touching D */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* C -> top should go back to A B C, not touching D */
+ _region[C]->raise_to_top ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+}
+
+void
+PlaylistLayeringTest::addHigher_relayerOnAll_Test ()
{
_session->config.set_layer_model (AddHigher);
- create_three_short_regions ();
+ _session->config.set_relayer_on_all_edits (true);
+
+ create_short_regions ();
+
+ /* three overlapping regions */
+ _playlist->add_region (_region[A], 0);
+ _playlist->add_region (_region[B], 10);
+ _playlist->add_region (_region[C], 20);
+ /* and another non-overlapping one */
+ _playlist->add_region (_region[D], 200);
+
+ /* AddHigher means that they should be arranged thus */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
- _playlist->add_region (_region[0], 0);
- _playlist->add_region (_region[1], 10);
- _playlist->add_region (_region[2], 20);
+ _region[A]->set_position (5);
- CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[0]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[1]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[2]->layer ());
+ /* region move should have no effect in AddHigher mode */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
- _region[0]->set_position (5);
+ /* C -> bottom should give C A B, not touching D */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
- /* region move should have no effect */
- CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[0]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[1]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[2]->layer ());
+ /* C -> top should go back to A B C, not touching D */
+ _region[C]->raise_to_top ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
}
void
-PlaylistLayeringTest::moveAddHigherTest ()
+PlaylistLayeringTest::addOrBoundsHigher_relayerOnAll_Test ()
{
- _session->config.set_layer_model (MoveAddHigher);
- create_three_short_regions ();
+ _session->config.set_layer_model (AddOrBoundsChangeHigher);
+ _session->config.set_relayer_on_all_edits (true);
+
+ create_short_regions ();
+
+ /* three overlapping regions */
+ _playlist->add_region (_region[A], 0);
+ _playlist->add_region (_region[B], 10);
+ _playlist->add_region (_region[C], 20);
+ /* and another non-overlapping one */
+ _playlist->add_region (_region[D], 200);
+
+ /* AddOrBoundsHigher means that they should be arranged thus */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* region move should put A on top for B C A, not touching D */
+ _region[A]->set_position (5);
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* C -> bottom should give C B A, not touching D */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* C -> top should go back to B A C, not touching D */
+ _region[C]->raise_to_top ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Put C on the bottom */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Now move it slightly, and it should go back to the top again */
+ _region[C]->set_position (21);
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Put C back on the bottom */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Trim it slightly, and it should go back to the top again */
+ _region[C]->trim_front (23);
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Same with the end */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ _region[C]->trim_end (118);
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+}
+
+void
+PlaylistLayeringTest::addOrBoundsHigher_relayerWhenNecessary_Test ()
+{
+ _session->config.set_layer_model (AddOrBoundsChangeHigher);
+ _session->config.set_relayer_on_all_edits (false);
+
+ create_short_regions ();
+
+ /* three overlapping regions */
+ _playlist->add_region (_region[A], 0);
+ _playlist->add_region (_region[B], 10);
+ _playlist->add_region (_region[C], 20);
+ /* and another non-overlapping one */
+ _playlist->add_region (_region[D], 200);
+
+ /* AddOrBoundsHigher means that they should be arranged thus */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ _region[A]->set_position (5);
+
+ /* region move should not have changed anything, since in
+ this mode we only relayer when there is a new overlap
+ */
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* C -> bottom should give C A B, not touching D */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* C -> top should go back to A B C, not touching D */
+ _region[C]->raise_to_top ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Put C on the bottom */
+ _region[C]->lower_to_bottom ();
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+
+ /* Now move it slightly, and it should stay where it is */
+ _region[C]->set_position (21);
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+}
+
+void
+PlaylistLayeringTest::lastLayerOpTest ()
+{
+ create_short_regions ();
+
+ _playlist->add_region (_region[A], 0);
+ CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpAdd));
+ uint64_t const last_add = _region[A]->last_layer_op (LayerOpAdd);
+
+ _region[A]->set_position (42);
+ CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpBoundsChange));
+ CPPUNIT_ASSERT_EQUAL (last_add, _region[A]->last_layer_op (LayerOpAdd));
+
+ _region[A]->trim_front (46);
+ CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpBoundsChange));
+ CPPUNIT_ASSERT_EQUAL (last_add, _region[A]->last_layer_op (LayerOpAdd));
+
+ _region[A]->trim_end (102);
+ CPPUNIT_ASSERT_EQUAL (_playlist->layer_op_counter, _region[A]->last_layer_op (LayerOpBoundsChange));
+ CPPUNIT_ASSERT_EQUAL (last_add, _region[A]->last_layer_op (LayerOpAdd));
+}
+
+void
+PlaylistLayeringTest::recursiveRelayerTest ()
+{
+ _session->config.set_layer_model (AddOrBoundsChangeHigher);
+ _session->config.set_relayer_on_all_edits (false);
+
+ create_short_regions ();
- _playlist->add_region (_region[0], 0);
- _playlist->add_region (_region[1], 10);
- _playlist->add_region (_region[2], 20);
+ _playlist->add_region (_region[A], 100);
+ _playlist->add_region (_region[B], 125);
+ _playlist->add_region (_region[C], 50);
+ _playlist->add_region (_region[D], 250);
- CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[0]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[1]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[2]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[C]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
- _region[0]->set_position (5);
+ _region[A]->set_position (200);
- /* region move should have put 0 on top */
- CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[0]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[1]->layer ());
- CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[2]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (0), _region[D]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (1), _region[A]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (2), _region[B]->layer ());
+ CPPUNIT_ASSERT_EQUAL (layer_t (3), _region[C]->layer ());
}