📄 walkthrough.txt
字号:
.. _walkthrough-section:How does the AmbulantPlayer play a SMIL document?=================================================Last updated for Ambulant version 1.8.Introduction------------This section attempts to explain the basic structure of the Ambulant Player byloosely explaining what happens when you run it and play a document.There is an informal `overall structure diagram`_ that tries to put the wholedesign in one pretty picture and may be worthwhile to keep handy while readingthis document.The main program is platform dependent and GUI-toolkit dependent. The detailsof this main program are skipped here (and they can actually vary quite a bitfor the platforms we support), but at some point after the program has startedthe GUI is put on the screen, with the usual set of menus for Open, Play, etc.Opening a document------------------When the user selects Open (or Open URL, or double-clicks or drags a document)we need to get the data, parse the document into a DOM tree and create aplayer to play that DOM tree. In addition, we need to tell the player howit can obtain media data, create windows, and more.Most player implementations (the Windows player is an exception) have aclass with a name like ``mainloop`` to handle this. Such a mainloop is createdper SMIL document. Actually, Ambulant provides a class ``gui_player`` whichcan be used as a skeleton for such a mainloop class, handling most of the bookkeepingsketched below.The mainloop object should first create the various factoriesand populate them:- A ``window_factory`` is usually implemented by the main program itself. The player will call this when it needs a window. Usually the first request to create a window will actually return the document window (after resizing to the appropriate size).- A ``global_playable_factory`` is created. This is the object the player will use to create renderers for the various media types. The global factory is filled with the various renderers this ambulant player supports. In effect, this is the step where you get to decide how various media are rendered.- A ``datasource_factory`` is created and filled with the factory functions that will create datasources for audio, video or other, raw, data such as text. The factory functions that are added to the datasource_factory partially determine how data is retrieved over the net, which protocols and formats are supported and such. Partially, because some media items (audio and video, notably) may be rendered by simply passing the URL to some underlying media infrastructure such as DirectX or QuickTime. - A ``parser_factory`` is created and populated with the default XML parser.- A ``node_factory`` used to create the DOM tree nodes.Next ``init_plugins`` is called, and if thearchitecture supports dynamically loadable plugins we get the ``plugin_engine``singleton object and ask it to load the plugins. This will search the plugindirectories for dynamic objects with the correct naming convention, load them,and call their ``initialize`` routine. The ``factories`` object (another interfaceusually implemented by ``gui_player``) and ``gui_player`` object are passed tothe ``initialize`` routine, so the plugin itself can register any factoriesit wants. Additionally, a plugin could modify the ``gui_player`` to allowit to get controllater, during playback of the document.The next step is to create the DOM tree. One way to do this is to use``read_data_from_url`` to read the data from the document, and then pass thisdata to ``document::create_from_string``. This will return a ``document`` object.This object contains the DOM tree itself (implemented by the ``node`` object) andsome context information (XML namespace information, original URL for resolvingrelative URLs used in the document, a mapping from XML IDs to node objects). There is aconvenience function ``create_document`` that does all this for you.The final step is to create a ``player`` object. This is done through``create_smil2_player``, passing the ``document``, the ``factories`` and onefinal object, ``embedder``. This object is again implemented by the main program,and implements a small number of auxiliary functions, such as opening anexternal webbrowser or opening a new SMIL document.Creating the player-------------------When the ``smil_player`` object is created it gets the ``document``, ``factories``and ``embedder`` arguments. It now needs to create its internal data structuresto facilitate playback later on:- A ``timer`` and ``event_processor`` are created. The timer is the master clock for the presentation, and the event processor is a runqueue object that is used for low-level scheduling. Whenever the high-level scheduler wants some code to be executed it will add an ``event`` to the ``event_processor``, possibly with a timeout and a priority. The event processor runs in a separate thread, waits for events in its runqueue to become elegible and then runs them. This mechanism is the underlying engine that makes the whole player work, anything that needs to wait doesn't do so inline but uses the event processor to get a callback at a later stage: the scheduler, renderers needing input data, etc. - A ``layout_manager`` is created, which will be used to find where media items should be displayed. The ``smil_layout_manager`` reads the ``<layout>`` section of the DOM tree and builds a parallel layout tree (which also contains information on some of the body media nodes, the ones that have layout information themselves) of ``region_node`` objects. Then this tree of ``region_node`` objects is converted into a tree of ``surface_template`` objects. To create toplevel windows the ``new_topsurface`` method of the window factory is used, and subregions are created using the ``new_subsurface`` method of their parent ``surface_template``. The layout manager also contains mappings to be able to get from a ``node`` to the corresponding ``region_node`` to the ``surface_template``, and this will be used during playback to play media items in the correct location. - A ``timegraph`` is created. This is the internal representation of the ``<body>`` part of the DOM tree that will be used to play back the document. In addition a ``scheduler`` is created, which will interpret the data in the ``timegraph``.Starting playback-----------------When the user selects Play we call the ``start`` method of the ``player`` object.This will invoke ``start`` on the scheduler. This will start playing the rootnode of the tree. The scheduler will now do all the SMIL 2 magic, whereby eventssuch as the root node being played causes other nodes to become playable, etc.At some point a media item needs to be rendered. The scheduler calls the ``new_playable``method from the ``global_playable_factory``. This will pass the DOM ``node`` to thevarious factories until one signals it can create a ``playable`` for the object.In addition, if the playable has a renderer (which is true for most media objects,but not for things like SMIL animations) we also obtain the ``surface`` on whichthe media item should be renderered, through the ``layout_manager``. We then tellthe renderer which surface to use.Soon afterwards the ``start`` method of the playable is called to start playback.An average renderer will need to obtain data from some URL. It will do this by creatinga ``datasource`` for the document through the ``datasource_factory`` object. Every timethe renderer wants more data it calls the ``start`` method of the datasource passinga callback routine. Whever data is available the datasource will schedule a callto the callback routine, through the event processor. When the renderer has enoughinformation to start drawing it will not actually draw immedeately, but it willsend a ``need_redraw`` call to its surface. This will percolate up the surfacehierarchy, to the GUI code, and eventually come back down as a ``redraw`` call allthe way to the renderer (assuming it is not obscured by other media items, etc).At this point the bits finally get drawn on the screen.Whenever anything "interesting" happens in the renderer (the media item stopped playing,the user clicked the mouse, etc) it invokes a corresponding method on its``playable_notification``. This interface is implemented by the scheduler, and thesenotifications are how the scheduler gets informed that it can start scheduling new things,etc.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -