From 3fdd16ff489efad767b5ab8e7a47be510287997c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 25 Sep 2007 23:39:46 +0200 Subject: [PATCH] draft adding clips and simple editing operations WIP: lots of tests, no implementation, doesn't compile... --- src/backend/mediaaccessfacade.hpp | 1 + src/common/test/suite.cpp | 9 +- src/common/util.hpp | 21 ++- src/proc/asset/media.cpp | 30 +++- src/proc/asset/media.hpp | 6 + tests/58proc-operate.tests | 4 + tests/components/backend/mediaaccessmock.cpp | 125 ++++++++++++++++ tests/components/backend/mediaaccessmock.hpp | 52 +++++++ .../backend/mediaaccessmocktest.cpp | 103 ++++++++++++++ .../components/proc/asset/createassettest.cpp | 1 + tests/components/proc/asset/makecliptest.cpp | 96 +++++++++++++ .../proc/mobject/session/addcliptest.cpp | 13 +- .../proc/mobject/session/deletecliptest.cpp | 18 ++- .../mobject/session/rebuildfixturetest.cpp | 28 +++- .../mobject/session/sessionmanagertest.cpp | 134 ++++++++++++++++++ .../mobject/session/sessionstructuretest.cpp | 79 +++++++++++ .../proc/mobject/session/testclip.cpp | 63 ++++++++ .../proc/mobject/session/testclip.hpp | 39 +++-- .../proc/mobject/session/testsession1.hpp | 23 ++- uml/cinelerra3/5.session | 12 +- wiki/renderengine.html | 42 +++++- 21 files changed, 867 insertions(+), 32 deletions(-) create mode 100644 tests/components/backend/mediaaccessmock.cpp create mode 100644 tests/components/backend/mediaaccessmock.hpp create mode 100644 tests/components/backend/mediaaccessmocktest.cpp create mode 100644 tests/components/proc/asset/makecliptest.cpp create mode 100644 tests/components/proc/mobject/session/sessionmanagertest.cpp create mode 100644 tests/components/proc/mobject/session/sessionstructuretest.cpp create mode 100644 tests/components/proc/mobject/session/testclip.cpp diff --git a/src/backend/mediaaccessfacade.hpp b/src/backend/mediaaccessfacade.hpp index ce994baa8..faac58b63 100644 --- a/src/backend/mediaaccessfacade.hpp +++ b/src/backend/mediaaccessfacade.hpp @@ -65,6 +65,7 @@ namespace backend_interface * of the file refered by FileHandle. * @return ChanDesc which may contain \c NULL values if * the file doesn't contain this much channels. + * @todo throw or return NULL-ChanDesc if Filehandle is invalid? */ virtual ChanDesc queryChannel (FileHandle, uint chanNo) throw(); diff --git a/src/common/test/suite.cpp b/src/common/test/suite.cpp index b2cfcfea8..8239141f6 100644 --- a/src/common/test/suite.cpp +++ b/src/common/test/suite.cpp @@ -203,7 +203,14 @@ namespace test std::cout << "TEST \""<second); VALID (test, i->first); - (*test)()->run(noCmdline); // run it to insert test generated output + try + { + (*test)()->run(noCmdline); // run it to insert test generated output + } + catch (...) + { + std::cout << "PLANNED ============= " << cinelerra_error() << "\n"; + } std::cout << "END\n"; } } diff --git a/src/common/util.hpp b/src/common/util.hpp index 82b29439e..0b8d03e56 100644 --- a/src/common/util.hpp +++ b/src/common/util.hpp @@ -24,8 +24,10 @@ #ifndef UTIL_HPP_ #define UTIL_HPP_ +#include #include #include +#include #include "nobugcfg.h" ///////////////////TODO: just temporarily!!!! @@ -59,7 +61,6 @@ namespace util return !pContainer || pContainer->empty(); } - template <> inline bool isnil (const char* pCStr) { @@ -83,6 +84,24 @@ namespace util return map.find(key) != map.end(); } + /** shortcut for set value containment test */ + template + inline bool + contains (std::set& set, const T& val) + { + return set.end() != set.find (val); + } + + /** shortcut for brute-force containment test + * in any sequencial container */ + template + inline bool + contains (SEQ& cont, typename SEQ::value_type& val) + { + SEQ::iterator end = cont.end(); + return end != std::find(cont.begin(),end, val); + } + /** shortcut for operating on all elements of a container. * Isn't this already defined somewhere? It's so obvious.. diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp index 437b30998..6be2d4f3b 100644 --- a/src/proc/asset/media.cpp +++ b/src/proc/asset/media.cpp @@ -25,6 +25,7 @@ #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" #include "proc/asset/unknown.hpp" +#include "proc/mobject/session/clip.hpp" #include "common/util.hpp" #include "nobugcfg.h" @@ -58,7 +59,34 @@ namespace asset } } - + + + + typedef shared_ptr PClip; + typedef shared_ptr PProcPatt; + + + PClip + Media::createClip () + { + UNIMPLEMENTED ("create clip from media asset"); + PClip clip; //TODO:null + + ENSURE (clip); + return clip; + } + + PProcPatt + Media::howtoProc () + { + UNIMPLEMENTED ("calculate and return processing pattern for media asset"); + PProcPatt ppatt; //TODO:null + + ENSURE (ppatt); + return ppatt; + } + + MediaFactory Media::create; ///< storage for the static MediaFactory instance diff --git a/src/proc/asset/media.hpp b/src/proc/asset/media.hpp index 66c21da04..d5593c514 100644 --- a/src/proc/asset/media.hpp +++ b/src/proc/asset/media.hpp @@ -40,9 +40,12 @@ +class mobject::session::Clip; + namespace asset { + class Clip; class Media; class MediaFactory; @@ -73,6 +76,9 @@ namespace asset return static_cast& > (Asset::getID()); } + shared_ptr createClip (); + shared_ptr howtoProc (); + protected: Media (const Asset::Ident& idi, const string& file) : Asset(idi), filename_(file) {} friend class MediaFactory; diff --git a/tests/58proc-operate.tests b/tests/58proc-operate.tests index 07bb240e6..e36aa3066 100644 --- a/tests/58proc-operate.tests +++ b/tests/58proc-operate.tests @@ -5,6 +5,10 @@ TESTING "Proc Layer combined operations Test Suite" ./test-components --group=op TEST "MediaAccessMock_test" MediaAccessMock_test < + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +/** @file mediaacessmock.cpp + ** Mock implementation of the Interface normally used to query media file + ** informations from the data backend. The Mock implementation instead holds + ** a map of fixed response which will be deliverd when querying some magic + ** filenames. + ** + ** @see mediaaccessmocktest.cpp validating the Mock + ** @see MediaAccessFactory the real thing + ** + */ + + +#include "backend/mediaaccessmock.hpp" + +#include "common/util.hpp" +#include "nobugcfg.h" + +#include +#include +#include + +using cinelerra::error::Invalid; +using util::for_each; +using util::isnil; +using std::cout; +using std::string; +using std::vector; +using std::map; + + +namespace backend_interface + { + namespace test + { + typedef MediaAccessFacade::FileHandle FileHandle; + typedef MediaAccessFacade::ChanHandle ChanHandle; + + + namespace // implementation deatils + { + typedef vector Response; + const ChanDesc NULLResponse; + + struct TestCases : map + { + TestCases () + { + // ------------------------------------------------------------------TESTCASES + (*this)["test-1"].push_back (ChanDesc ("video","ID", genH())); + + (*this)["test-2"].push_back (ChanDesc ("video","H264", genH())); + (*this)["test-2"].push_back (ChanDesc ("audio-L","PCM", genH())); + (*this)["test-2"].push_back (ChanDesc ("audio-R","PCM", genH())); + // ------------------------------------------------------------------TESTCASES + } + + bool known (string key) + { + const_iterator i = find (key); + return (i != end()); + } + private: + int _i_; + ChanHandle genH() + { + return reinterpret_cast (++_i_); + } + }; + + // instantiate TestCasses table + TestCases testCases; + + } // (end) implementation namespace + + + FileHandle + MediaAccessMock::queryFile (const char* name) throw(Invalid) + { + if (isnil (name)) + throw Invalid ("empty filename passed to MediaAccessFacade."); + + if (!testCases.known(name)) + return 0; + else + return reinterpret_cast (&testCases[name]); + } + + ChanDesc + MediaAccessMock::queryChannel (FileHandle h, uint chanNo) throw() + { + const Response* res (reinterpret_cast (h)); + + if (!res || res->size() <= chanNo) + return NULLResponse; + else + return (*res)[chanNo]; + } + + + } // namespace test + +} // namespace backend_interface diff --git a/tests/components/backend/mediaaccessmock.hpp b/tests/components/backend/mediaaccessmock.hpp new file mode 100644 index 000000000..9810773a5 --- /dev/null +++ b/tests/components/backend/mediaaccessmock.hpp @@ -0,0 +1,52 @@ +/* + MEDIAACCESSMOCK.hpp - a test (stub) target object for testing the factories + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef BACKEND_TEST_MEDIAACCESSMOCK_H +#define BACKEND_TEST_MEDIAACCESSMOCK_H + + +#include "backend/mediaaccessfacade.hpp" + + + + +namespace backend_interface + { + namespace test + { + /** + * Mock implementation of the MediaAccessFacade. + * Provides preconfigured responses for some Test-Filenames. + */ + class MediaAccessMock : public MediaAccessFacade + { + public: + FileHandle queryFile (const char* name) throw(cinelerra::error::Invalid); + ChanDesc queryChannel (FileHandle, uint chanNo) throw(); + }; + + + } // namespace test + +} // namespace backend_interface +#endif diff --git a/tests/components/backend/mediaaccessmocktest.cpp b/tests/components/backend/mediaaccessmocktest.cpp new file mode 100644 index 000000000..5e7ef4cc4 --- /dev/null +++ b/tests/components/backend/mediaaccessmocktest.cpp @@ -0,0 +1,103 @@ +/* + MediaAccessMock(Test) - checking our Test Mock replacing the MediaAccessFacade + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "backend/mediaaccessfacade.hpp" +#include "backend/mediaaccessmock.hpp" + +#include "common/test/run.hpp" +//#include "common/util.hpp" +#include "nobugcfg.h" + +//#include +#include + +//using boost::format; +//using util::isnil; +using std::string; +using std::cout; + + +namespace backend_interface + { + namespace test + { + + + + + + /******************************************************************************** + * @test inject a Mock object replacing the backend_interface::MediaAccessFacade. + * Verify if the Mock object behaves as expected when calling the Facade. + */ + class MediaAccessMock_test : public Test + { + typedef MediaAccessFacade MAF; + + virtual void run(Arg arg) + { + MAF::instance.injectSubclass (new MediaAccessMock); + + queryScenario ("test-1"); + queryScenario ("test-2"); + + MAF::instance.injectSubclass (0); + } + + + /** perform the test: query for an (alledged) file + * and retrieve the mock answer. + */ + void queryScenario (string filename) + { + MAF& maf (MAF::instance()); + MAF::FileHandle fhandle = maf.queryFile (filename.c_str()); + if (!fhandle) + cout << "File \""< + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +#include "common/util.hpp" + +#include "proc/assetmanager.hpp" +#include "proc/asset/media.hpp" +#include "proc/mobject/session/clip.hpp" + +//#include "proc/asset/assetdiagnostics.hpp" + +using util::contains; +using util::isnil; +using std::string; + + +namespace asset + { + namespace test + { + + + + + /*********************************************************************** + * @test creating a Clip MObject and an associated Clip Asset from + * a given asset::Media. + * @see asset::Media#createClip + */ + class MakeClip_test : public Test + { + typedef shared_ptr PM; + typedef shared_ptr PC; + + virtual void run (Arg arg) + { + + PM mm = asset::Media::create("test-1", VIDEO); + PC cc = mm->createClip(); + PM cm = cc->getMedia(); + + ASSERT (cm); + ASSERT (0 < cc->length); + ASSERT (cm->ident.category.hasKind (VIDEO)); + ASSERT (cm->getFilename() == mm->getFilename()); + ASSERT (cm->howtoProc() == mm->howtoProc()); + ASSERT (cm->ident.org == mm->ident.org); + ASSERT (dependencyCheck (mm,cm)); + + TRACE (assetmem, "leaving MakeClip_test::run()"); + TRACE (mobjectmem, "leaving MakeClip_test::run()"); + } + + bool dependencyCheck (PM media, PM clip) + { + TODO ("check asset dependencies, when this feature is implemented"); + return true; //TODO + + return (0 < clip->getParents().size()) + && (media == clip->getParents()[0]) + && (contains (media->getDependant(), clip)); + ; + } + + }; + + + /** Register this test class... */ + LAUNCHER (MakeClip_test, "function asset"); + + + + } // namespace test + +} // namespace asset diff --git a/tests/components/proc/mobject/session/addcliptest.cpp b/tests/components/proc/mobject/session/addcliptest.cpp index f6cc5def1..610e37445 100644 --- a/tests/components/proc/mobject/session/addcliptest.cpp +++ b/tests/components/proc/mobject/session/addcliptest.cpp @@ -22,13 +22,15 @@ #include "common/test/run.hpp" -//#include "common/factory.hpp" -//#include "common/util.hpp" +#include "proc/mobject/session/session.hpp" +#include "proc/mobject/session/testclip.hpp" +#include "common/util.hpp" //#include #include //using boost::format; +using util::contains; using std::string; using std::cout; @@ -52,6 +54,13 @@ namespace mobject { virtual void run(Arg arg) { + Session& sess = Session::getCurrent(); + PMO clip = TestClip::create(); + PPla pla = Placement::create(FIXED, Time(1), clip); + sess.add (pla); + + ASSERT (contains (sess.getEDL(), pla)); + // TODO: Clip-Asset and Placement magic?? } }; diff --git a/tests/components/proc/mobject/session/deletecliptest.cpp b/tests/components/proc/mobject/session/deletecliptest.cpp index 4a5c01567..167ef2577 100644 --- a/tests/components/proc/mobject/session/deletecliptest.cpp +++ b/tests/components/proc/mobject/session/deletecliptest.cpp @@ -22,7 +22,9 @@ #include "common/test/run.hpp" -//#include "common/factory.hpp" +#include "proc/assetmanager.hpp" +#include "proc/mobject/session/session.hpp" +#include "proc/mobject/session/testsession1.hpp" //#include "common/util.hpp" //#include @@ -52,6 +54,20 @@ namespace mobject { virtual void run(Arg arg) { + buildTestseesion1(); + Session& sess = Session::getCurrent(); + AssetManager& aMang = AssetManager::instance(); + + PPla clipPlacement = sess.getEDL().find(SESSION1_CLIP); // global Var asigned in buildTestsession1() + PAsset clipAsset = aMang.getAsset(clipPlacement->subject->getMedia()); + IDA clipAID = clipAsset->getID(); + ASSERT (clipPlacement); + + sess.remove (clipPlacement); + + ASSERT (!sess.getEDL().find(SESSION1_CLIP)); // EDL forgot the Clip/Placement + ASSERT (!aMang.known (clipAID)); // corresponding Clip Asset has disappeared + ASSERT (!aMang.getAsset(clipPlacement->subject->getMedia())); // internal cross-links removed } }; diff --git a/tests/components/proc/mobject/session/rebuildfixturetest.cpp b/tests/components/proc/mobject/session/rebuildfixturetest.cpp index 01ad76b34..7af4be5e7 100644 --- a/tests/components/proc/mobject/session/rebuildfixturetest.cpp +++ b/tests/components/proc/mobject/session/rebuildfixturetest.cpp @@ -22,13 +22,18 @@ #include "common/test/run.hpp" -//#include "common/factory.hpp" -//#include "common/util.hpp" +#include "proc/mobject/session/session.hpp" +#include "proc/mobject/session/testsession1.hpp" +#include "common/util.hpp" //#include +#include #include //using boost::format; +using boost::bind; +using util::contains; +using util::for_each; using std::string; using std::cout; @@ -53,7 +58,26 @@ namespace mobject { virtual void run(Arg arg) { + clearSession(); + buildTestseesion1(); + Session& sess = Session::getCurrent(); + ASSERT (sess.isValid()); + sess.rebuildFixture(); + TODO ("check the fixture has been touched. e.g. by hash."); + TODO ("query all Placements of all Clips (via AssetManager). Verify explicit plac contained in Fixture."); + + for_each (sess.getFixture(), + bind (&check_is_from_EDL, _1, sess.getEDL())); + + TODO ("can we check the other direction, from EDL to Fixture??"); } + + static void + check_is_from_EDL (PPla explicitPlacement, EDL& edl) + { + PPla originalPlacement = explicitPlacement->subject->placement; + ASSERT (contains(edl, originalPlacement)); + } }; diff --git a/tests/components/proc/mobject/session/sessionmanagertest.cpp b/tests/components/proc/mobject/session/sessionmanagertest.cpp new file mode 100644 index 000000000..f6f8169e4 --- /dev/null +++ b/tests/components/proc/mobject/session/sessionmanagertest.cpp @@ -0,0 +1,134 @@ +/* + SessionManager(Test) - accessing, loading and saving the Session/EDL + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +#include "proc/mobject/session/session.hpp" +#include "proc/mobject/session/testsession1.hpp" +//#include "common/util.hpp" +//#include +#include + +//using boost::format; +using std::string; +using std::cout; + + +namespace mobject + { + namespace session + { + namespace test + { + + + /******************************************************************************* + * Check the session management operations provided by mobject::session::Seesion + * This includes accessing the current Session (somewhat a singleton). + * @todo load a Mock session + * @todo create a session and save (serialize) it + * @todo load a real test session + */ + class SessionManager_test : public Test + { + virtual void run(Arg arg) + { + getCurrentSession (); + clearSession(); + loadMockSession(); + + clearSession(); + buildTestseesion1(); + string serialized; + saveSession (serialized); + loadSession (serialized); + ASSERT (checkTestsession1()); + } + + /** @test accessing the current (global) session + */ + void getCurrentSession () + { + Session& sess = Session::getCurrent(); + ASSERT (sess.isValid()); + } + + /** @test clear current session contents + * without resetting global session config. + * @todo implement all session content, implement + * mobject and asset deletion operations. + */ + void clearSession () + { + UNIMPLEMENTED ("clear objects in current session"); + } + + /** @test reset global session config and start with + * a pristine default session. + * @todo define the "global session config", implement session default ctor + */ + void resetSession () + { + UNIMPLEMENTED ("construct a pristine session"); + } + + /** @test use a mock session serializer to load + * a preconfigured test session. Verify + * objects are wired correctly. + * @todo implement rebuilding session, implement mock session serializer + */ + void loadMockSession () + { + UNIMPLEMENTED ("rebuild session using a mock serializer"); + } + + /** @test load serialized session using the + * real session serializer implementation. + * @param src string with serialized session data + * @todo implement real session serializer + */ + void loadSession (const string& src) + { + UNIMPLEMENTED ("loding real sesion"); + } + + /** @test serialize (save) the current session + * @param dest string recieving the generated serialized stream + * @todo implement real session serializer + */ + void saveSession (string& dest) + { + UNIMPLEMENTED ("serialize current session"); + } + }; + + + /** Register this test class... */ + LAUNCHER (SessionManager_test, "function session"); + + + + } // namespace test + + } // namespace session + +} // namespace mobject diff --git a/tests/components/proc/mobject/session/sessionstructuretest.cpp b/tests/components/proc/mobject/session/sessionstructuretest.cpp new file mode 100644 index 000000000..18ee496e0 --- /dev/null +++ b/tests/components/proc/mobject/session/sessionstructuretest.cpp @@ -0,0 +1,79 @@ +/* + SessionStructure(Test) - verifying basic Session/EDL structure + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "common/test/run.hpp" +#include "proc/mobject/session/session.hpp" +#include "proc/assetmanager.hpp" +//#include "common/util.hpp" +//#include +#include + +//using boost::format; +using std::string; +using std::cout; + + +namespace mobject + { + namespace session + { + namespace test + { + using proc_interface::AssetManager; + using proc_interface::PAsset; + + + /******************************************************************************* + * @test access the current session and verify the correct + * structure of the most important components: The session + * contains an EDL, we can get at the Fixture, we have at least + * one Track and the corresponding Track asset is available. + * @todo define further criteria to be checked + * @todo implement EDL, Fixture, Session#rebuildFixture, asset::Track + */ + class SessionStructure_test : public Test + { + virtual void run(Arg arg) + { + Session& sess = Session::getCurrent(); + ASSERT (0 <= sess.getEDL().size()); // TODO implement + ASSERT (0 <= sess.getFixture().size()); // TODO implement + ASSERT (0 < sess.getTracks().size()); // TODO implement + + PAsset track = sess.getTracks()[0]; + AssetManager& aMang = AssetManager::instance(); + ASSERT (track == aMang.getAsset (track->getID())); + } + }; + + + /** Register this test class... */ + LAUNCHER (SessionStructure_test, "unit session"); + + + + } // namespace test + + } // namespace session + +} // namespace mobject diff --git a/tests/components/proc/mobject/session/testclip.cpp b/tests/components/proc/mobject/session/testclip.cpp new file mode 100644 index 000000000..fb33be2ec --- /dev/null +++ b/tests/components/proc/mobject/session/testclip.cpp @@ -0,0 +1,63 @@ +/* + TestClip - bookkeeping (asset) view of a media clip. + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + This program 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. + + This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "proc/mobject/session/testclip.hpp" +#include "proc/asset/media.hpp" +#include "proc/asset/clip.hpp" + +namespace mobject + { + namespace session + { + namespace test + { + typedef shared_ptr PC; + typedef shared_ptr PM; + typedef MediaAccessFacade MAF; + + + /** @todo find a way to link to an existing clip object. + * Idea: use the clip's copy operation, i.e. feed it + * to mobject::session::clip copy ctor + */ + TestClip::TestClip () + { + // install Mock-Interface to cinelerra backend + MAF::instance.injectSubclass (new MediaAccessMock); + + PM media = asset::Media::create("test-2", VIDEO); // query magic filename + PC clip = media->createClip(); + //TODO how to link to *this ??? + + MAF::instance.injectSubclass (0); // remove Mock-Interface + } + + /** storage for the TestClip-Factory */ + TestClip::Factory TestClip::create; + + + } // namespace test + + } // namespace session + +} // namespace mobject diff --git a/tests/components/proc/mobject/session/testclip.hpp b/tests/components/proc/mobject/session/testclip.hpp index ec9ec8715..f9edae2a5 100644 --- a/tests/components/proc/mobject/session/testclip.hpp +++ b/tests/components/proc/mobject/session/testclip.hpp @@ -41,19 +41,40 @@ namespace mobject { namespace session { - /** - * Sample or Test Clip for checking - * various EDL, session and builder operations. - * - */ - class TestClip + namespace test { - public: - }; - + + /** + * Sample or Test Clip for checking + * various EDL, session and builder operations. + * Can be used as Mock object to record invoked operations. + * + */ + class TestClip ////TODO inherit from mobject::session::Clip + { + + /** smart ptr factory allowed to invoke TestClip's ctor */ + struct Factory : cinelerra::Factory + { + typedef shared_ptr PType; + PType operator() () { return PType (new TestClip, &destroy); } + protected: + static void destroy (TestClip* tc) { delete tc; } + }; + + + TestClip (); + friend class Factory; + + public: + static Factory create; + }; + + } // namespace test + } // namespace session } // namespace mobject diff --git a/tests/components/proc/mobject/session/testsession1.hpp b/tests/components/proc/mobject/session/testsession1.hpp index 5426047be..97a93719f 100644 --- a/tests/components/proc/mobject/session/testsession1.hpp +++ b/tests/components/proc/mobject/session/testsession1.hpp @@ -1,5 +1,5 @@ /* - TESTSESSION1.hpp - complete session configuration use for various tests + TESTSESSION1.hpp - complete session configuration used for various tests Copyright (C) CinelerraCV 2007, Christian Thaeter @@ -21,8 +21,8 @@ */ -#ifndef MOBJECT_SESSION_TESTCLIP_H -#define MOBJECT_SESSION_TESTCLIP_H +#ifndef MOBJECT_SESSION_TESTSESSION_H +#define MOBJECT_SESSION_TESTSESSION_H #include "proc/mobject/session/session.hpp" @@ -42,18 +42,29 @@ namespace mobject { namespace session { - typedef std::auto_ptr PSession; /////TODO /** * Create a Test Session configuration usable for various Tests. * This Session holds two Clips and corresponds to "Example1" - * in the UML design. + * in the UML design. All changes are done to the (global) + * current session. */ - PSession Testsession1 () + void buildTestseesion1 () { UNIMPLEMENTED ("Test-Session 1"); }; + + /** + * Analyze the current (gloal) Session to verify the + * configuration of "Test-Session 1" + */ + bool checkTestseesion1 () + { + UNIMPLEMENTED ("Test-Session 1"); + return false; + }; + diff --git a/uml/cinelerra3/5.session b/uml/cinelerra3/5.session index b6381c7cf..e2727d655 100644 --- a/uml/cinelerra3/5.session +++ b/uml/cinelerra3/5.session @@ -1,20 +1,20 @@ window_sizes 1140 783 270 860 633 71 diagrams classdiagram_ref 130309 // Asset Kinds - 860 633 100 4 180 0 - classdiagram_ref 128133 // Session structure - 688 506 100 4 120 0 - active classdiagram_ref 130437 // Media-Asset Relations + 860 633 100 4 0 0 + active classdiagram_ref 128133 // Session structure + 860 633 100 4 341 0 + classdiagram_ref 130437 // Media-Asset Relations 860 633 100 4 0 0 classdiagram_ref 128389 // Render Entities 688 506 100 4 120 0 end show_stereotypes selected - package_ref 129 // cinelerra3 +package_ref 129 // cinelerra3 open - package_ref 128005 // design +package_ref 128005 // design classview_ref 128901 // Assets classview_ref 128005 // Session classview_ref 129029 // Interface diff --git a/wiki/renderengine.html b/wiki/renderengine.html index ea3fc49ce..9ddac1a24 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -763,6 +763,34 @@ Cinelerra uses this term in a related manner but with a somewhat shifted focus ( In this usage, the EDL is almost synonymous to the ''Session'', just the latter emphasizes more the state aspect, as it can be thought as a current state of the EDL contained in a file or data structure together with additional Option values and settings for the GUI. The Session is what you save and load, while the EDL rather denotes a structure of Objects placed in time. +
+
These are the tools provided to any client of the Proc layer for handling and manipulating the entities in the EDL. When defining such operations, //the goal should be to arrive at some uniformity in the way things are done.// Ideally, when writing client code, one should be able to guess how to achieve some desired result.
+
+!guiding principle
+The approach taken to define any operation is based primarily on the ''~OO-way of doing things'': entities operate themselfs. You don't advise some manager, session or other &raquo;god class&laquo; to manipulate them. And, secondly, the scope of each operation will be as large as possible, but not larger. This often means performing quite some elementary operations &mdash; sometimes a convenience shortcut provided by the higher levels of the application may come in handy &mdash; and basically this gives rise to several different paths of doing the same thing, all of which need to be equivalent.
+
+!main tasks
+* you ''create a clip'' either from a source media or from another clip (copy, maybe clone?). The new clip always reflects the full size (and other properties) of the source used for creating.
+* you can request a clip to ''resize'', which always relates to its current dimensions.
+* you can ''place or attach'' the clip to some point or other entity by creating a [[Placement]] from the clip.
+* you can ''adjust'' a placement relative to some other placement, meta object (i.e. selection), label or media, and this may cause the placement to resize or even delete the clip as necessary
+* you can perform ''adjustments'' on the whole EDL.
+All these operations propagate to directly dependant objects and may schedule global reconfigurations.
+
+!state, locking, policies
+While performing any manipulative task, the state of the object is considered inconsistent, but it is guaranteed to be consistent after any such operation, irrespective of the result. There is no automatic atomicity and, consequently each propagation is considered a separate operation.
+
+!!parallelism
+At the level of fine grained operations on individual entities, there is ''no support for parallelism''. Individual entities don't lock themselves. Tasks perform locking and are to be scheduled. Thus, we need an isolation layer towards all inherently multithreaded parts of the system, like the GUI or the renderengine.
+
+This has some obvious and some subtle consequences. Of course, manipulating //tasks// will be queued and scheduled somewhere. But as we rely on object identity and reference semantics for the entities in the EDL, some value changes are visible to  operations going on in parallel threads (e.g. rendering) and each operation on the EDL entities //has to be aware of this.//
+Consequently, sometimes there needs to be done a ''self-replacement by copy'' followed by manipulation of the new copy, while ongoing processes use the unaltered original object until they receive some sort of reset.
+
+!!undo
+Basically, each elementary operation has to record the informations necessary to be undone. It does so by registering a Memento with some central UndoManager facility. This Memento object contains a functor pre-bound with the needed parameter values. (Besides, the UndoManager is free to implement a second level of security by taking independent state snapshots). 
+{{red{to be defined in more detail later...}}}
+
+
The &raquo;Timeline&laquo; is a sequence of ~MObjects -- here clips -- together with an ExplicitPlacement, locating each clip at a given time and track. (Note: I simplified the time format and wrote frame numbers to make it more clear)
 [img[Example1: Objects in the EDL/Fixture|uml/fig128773.png]]
@@ -951,7 +979,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 &rarr;see in [[Wikipedia|http://en.wikipedia.org/wiki/Group_of_pictures]]
 
-
+
This wiki page is the entry point to detail notes covering some technical decisions, details and problems encountered in the course of the implementation of the Cinelerra Renderengine, the Builder and the related parts.
 
 * [[Packages, Interfaces and Namespaces|InterfaceNamespaces]]
@@ -959,6 +987,7 @@ For this Cinelerra3 design, we could consider making GOP just another raw media
 * [[Creating and registering Assets|AssetCreation]]
 * [[Creating new Objects|ObjectCreation]]
 * [[Multichannel Media|MultichannelMedia]]
+* [[Editing Operations|EditingOperations]]
 
 
@@ -2035,7 +2064,7 @@ DAMAGE. //Note, we have yet to specify how exactly the building and rendering will work together with the backend. There are several possibilities how to structure the Playlist//
-
+
Open issues, Things to be worked out, Problems still to be solved... 
 
 !!Parameter Handling
@@ -2062,7 +2091,14 @@ Users accustomed with modern GUI applications typically expect that //everything
 !!Compound and Multiplicity
 Simple relations can be hard wired. But, on the contrary, it would be as naive to define a Clip as having a Video track and two audio tracks, as it would be naive to overlook the problem of holding video and corresponding audio together. And, moreover, the default case has to be processed in a //straight forward// fashion, with as few tests and decisions as possible. So, basically each component participating in getting the core processing done has to mirror the structure pattern of the other parts, so that  processing can be done without testing and forking. But this leaves us with the problem where to put the initial knowledge about the structural pattern used for building up the compound structures and &mdash; especially &mdash; the problem how to treat different kinds of structural patterns, how to detect the pattern to be applied and how to treat multiple instances of the same structural pattern.
 
-One example of this problem is the [[handling of multichannel media|MultichannelMedia]]. Following the above reasoning, we end with having a [["structural processing pattern"|ProcPatt]], typically one video stream with MPEG decoder and a pair of audio streams which need either to be routed to some "left" and "right" output ports, or have to be passed through a panning filter accordingly. Now the problem is: //create a new instance of this structure for each new media, or detect which media to subsume under a existing pattern instance.//
+One example of this problem is the [[handling of multichannel media|MultichannelMedia]]. Following the above reasoning, we end with having a [["structural processing pattern"|ProcPatt]], typically one video stream with MPEG decoder and a pair of audio streams which need either to be routed to some "left" and "right" output ports, or have to be passed through a panning filter accordingly. Now the problem is: //create a new instance of this structure for each new media, or detect which media to subsume under a existing pattern instance.// + +!!Parallelism +We need to work out guidelines for dealing with operations going on simultaneously. Certainly, this will divide the application in several different regions. As always, the primary goal is to avoid multithread problems altogether. Typically, this can be achieved by making matters explicit: externalizing state, make the processing subsystems stateless, queue and schedule tasks, use isolation layers. +* the StateProxy is a key for the individual render processes state, which is managed in separate [[StateFrame]]s in the backend. The [[processing network|ProcNode]] is stateless. +* the [[Fixture]] provides an isolation layer between the renderengine and the Session/EDL +* all EditingOperations are not threadsafe intentionally, because they are [[scheduled|ProcLayerScheduler]] +
All Assets of kind asset::Proc represent //processing algorithms// in the bookkeeping view. They enable loading, browsing and maybe even parametrizing all the Effects, Plugins and Codecs available for use within the Cinelerra Session.