Plugin libraries are modules coupled to the Cruiser Core that provide functionality shared between one more more plugins. These libraries are summarised in Table 5.3.
5.4. Plugin Libraries CHAPTER 5. DESIGN
5.4.1 Cross Platform File Search (libfolder)
One part of this library is a cross-platform interface to a Folder, or directory, on disk. This part is loosely coupled with Cruiser; taking advantage of its debugging and RxString libraries. The contents of a Folder can be retrieved, and the directory tree can be walked depth-first or breadth-first, to retrieve the contents.
The ImageSearch capabilities are more tightly coupled with Cruiser. This provides a facility that uses Folder to search for potential images to load into the interface. The capabilities are activated when the imagesearch plugin is present.
The Folder library is also used by the browser and fsviewer plugins, as well as the libdb plugin library. But, like all plugin libraries, it is not required to compile the Cruiser core.
5.4.2 Database Access (libdb)
The libdb plugin module provides to plugins the concept of metadata associated with each Resource. It is backed by an SQLite30database, but one of the goals is to hide this database access from plugins that use it. Instead, access is through the Meta class, which is created for a Resource on request by querying the database for additional information that has previously been saved in the database.
When a Meta object is created for a Resource for the first time, or it has been modified since the database was last updated, information about the file is refreshed and stored in the database. Plugins can add update callbacksthat are called whenever a file’s metadata is updated in the database. This is how, for example, theExifplugin is informed that it should process a file’sExif header and cache it in the database (see §5.5.2).
One task of the database library is to detect when database accesses occur in a new thread. Each thread needs its own database connection, so when a request is made for metadata for the first time in a thread, a new handle is created and stored in a lookup. The library also emits a warning with a backtrace to indicate how it occurred – threads that take out database handles should close or reuse their database handle. Generally threads that use the database will be synchronised tasks, managed by the thread manager (§5.3.2).
5.4.3 Video Images (libvideo)
Libvideo provides an implementation of the Video Resource. This is a class derived from Image that continuously updates its content. Usually, it plays a video file on disk, such as a clip recorded by a digital camera. However, it interfaces with the mplayer31 program through aFirst In First Out (FIFO) socket so that it is able to render any video format that the mplayer program is able to handle.
Mplayer runs on Windows, OSX and Linux (also ARM, PlayStation and others), and it has support for over 20 input formats, and all major audio and video codecs. Interfacing through a FIFO socket allows Cruiser to decouple itself from the complexities of video decoding. Mplayer outputs a stream of frames inYUVformat, that is received through the socket by libvideo, which converts these frames to RGB. TheRGB frames are then converted into textures, suitable for the video card to render at any size and orientation. This is a processing-intensive task, but not prohibitively so. Video decoding is already very demanding and converting each frame to a texture roughly doubles the CPU load. However, Cruiser’s use of concurrency allows this processing all to occur in a background thread – possibly running on a second CPU core – thus keeping the main interface responsive.
30
http://www.sqlite.orgverified 2008-03-28.
Mplayer, too, does not interfere with Cruiser’s responsiveness because it is a separate process.
For processing any audio associated with the video clip, there is a simple solution. Mplayer’s video is redirected from the screen to the FIFO socket so we can process it, but there is no need for us to process the audio. The command that starts mplayer simply asks it to play the audio as it would normally – directly to the sound card’s mixer.
Mplayer does not only play video files on disk. Merely by specifying the video “file” as a streaming video from an Internet URL, a webcam attached to the computer, or a TV capture card, we can easily have streaming or live video from these locations.
We also retain control of mplayer, through a pipe (using popen). So, the commands such as pause, seek, etc. that would normally be sent via keyboard to the mplayer process, can now be sent over the pipe. At present, libvideo registers a callbackwith Environment that requests keypresses when a Video Resource is selected and sends these keypresses over the pipe for mplayer to process. In future, on-screen video controls can avoid using the keyboard.
5.4.4 Plugin utility and program initialisation (plug)
This is not really a library, so much as a repository for plugin-related housekeeping. The header file – plugin.h – gives plugins a set of macros to define the hook functions they need to operate with Cruiser. Template files for plugins, and a new_plugin script, make creating your own plugin even simpler.
This module also contains definitions of the functions that the actual application statically links to create the executable file. It includes the infrastructure to find and initialise plugins, initiate servers, install signal handlers (orSEH), and initialise debugging utilities (e.g. mcheck, for checking memory accesses).
5.4.5 Browsing Containers (libbrowser)
This library provides new Resources – BrowseContainer and BrowserAttachment – that are used to group collections of related Resources in the Environment. BrowseContainer implements the common parts of the Photocopier, StorageBin, Browser and SubBrowser. BrowserAttachment implements the common parts of CopyImage and Thumbnail, which become attached to Photocopier and Browsers, respectively. These relationships are shown in Figure5.2 on page 99. Because each of thederived classes are defined in plugins, putting the common parts in a plugin library allows them to be shared.
This submodule also provides the shared, space-filling thumbnails Layout (§5.2.4.2, and SFTLayout in Figure 5.3 on page 107). This is the default layout used for arranging items in BrowseContainer and its derived classes. The operation of the layout is discussed in Subsection 4.5.6.
5.4.6 Slider Widget (libslider)
The slider widget is an example of a screen element for providing control input to the interface. It is inspired by sliders from traditional WIMP interfaces, e.g. those used for controlling volume. A Slider is an object much longer than it is wide, with a button that can be moved over its length to alter an underlying value. The raw position of the slider is always stored as a real number between 0 and 1. However, a range can be specified to alter observed values. This value can also be displayed in text, drawn in the centre of the slider button.
The observer design pattern is used to inform objects of state changes to the slider. Like the factories used for creating Resources (§5.2.2.1 on page 103), C++templates are
5.4. Plugin Libraries CHAPTER 5. DESIGN
used to simplify the process of subscribing to state changes. The Slider’s observe member function takes a functor argument – any function or callable object that will be passed the new value of the slider whenever it is changed. A Boolean is also passed, indicating whether the slider is still being manipulated, or whether it has been released. Any number of observers can observe a single Slider.
The implementation of the Slider is derived from Image, and overrides the detailed_
_intersection member function in order to determine which part of the Slider was selected.
If the button was selected, subsequent move requests from a Gesture will move the button along the slider’s track. Otherwise the Slider can behave like a regular Image, and be moved, rotated and resized (depending whether it was selected near one of its endpoints).
A Slider can also operate in a fixed mode, with user-initiated move, rotate and resize disabled. In this mode, a Slider is typically attached to a parent Resource by making it PositionDependant using the PDAdapter (§5.2.4.2 on page 106). For example, a Slider is attached to a clustered Browser to change the number of clusters formed. When the slider value changes, an observer function triggers a recluster operation.
5.4.7 main()
The entry point to the application is the main function defined in main.cpp. Its primary purpose is initialisation. The following tasks are performed (mostly indirectly, using functionality in §5.4.4):
1. debugging functions are initialised (§5.2.6.3),
2. the command line processed (e.g. to specify an alternative plugin search path), 3. plugins are found in the search paths and they are opened with lt_dlopen, 4. the plugin configuration hooks are executed (§5.2.6.1)
• this is the optional tell_rc_variables symbol that plugins export, 5. the configuration file is parsed (§5.2.6.1),
6. TCPservers are initialised (§5.3.5.1), 7. the AudioSystem is initialised (§5.3.1),
8. the Environment is created and initialised (§5.2.2), 9. the EventHandler is created (§5.2.7),
10. all plugins are loaded into the Environment (in alphabetical order32) • this is the load_and_register symbol that plugins must export, 11. the EventHandler’s mainLoop is executed
• this runs until the application is exited, then 12. all plugins are unloaded, in reverse order
• this is the deregister_unload symbol that plugins must export,
13. the AudioSystem is stopped, then the EventHandler, Environment and AudioSystem are destroyed, and finally
14. the process exits.
Utility SLOC† Files
rfb 1541 rfbprotopp, vncimage, rfbdrag, rectangle-update, remotecursor browser 1001 browser-plugin, photocopy, thumbnail
men 877 flowmenu, menulayout, menuframe, menuitem, menusystem, menulocal
fsviewer* 926 fsclient, fsimage, historylayout, historybrowser, fsviewer disk 561 w32-drive-detect, dbus-drive-detect, osx-drive-detect,
dummy-drive-detect, imagesearch-plugin, drive-event res 431 smartframe, frame
people 323 audioman, person
exif 290 exif
vu-widget 261 vu-widget
net 142 listener
metadata 139 metadata
storagebin 120 storagebin-plugin
input 117 mimio2dt, dummy-dt-handler
ges 88 recogniser
audiodump 50 audiodump video 33 video-plugin
local 24 local
TOTAL 6 924
Table 5.4: Cruiser Plugins
†SLOC: Source Lines of Code
*fsviewer is a contributed plugin, now packaged with Cruiser (see §6.2.1)