diff options
Diffstat (limited to 'libs/ardour/test/playlist_layering_test.cc')
-rw-r--r-- | libs/ardour/test/playlist_layering_test.cc | 384 |
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 ()); } |