**************************************************************************** * BIG FAT WARNING: * * Media Device Framework is outdated and is going to be removed as soon as * * we rewrite MtpCollection and AudioCdColleciton not to use it anymore. * **************************************************************************** Media Device Framework ====================== 1. Solid Interface Solid is KDE's hardware detection library, and Amarok uses it to detect all of the devices that it knows how to interface with. It does this through two classes: MediaDeviceCache(singleton) - Talks directly to Solid, gets list of all present media devices and external hard drives, even if Amarok does not support them. MediaDeviceMonitor(singleton) - Talks to the MDC to see what devices are available. Keeps track of the kind of devices that Amarok supports. It does this by receiving and caching a single ConnectionAssistant object from the MediaDeviceCollectionFactory of the particular device type, so that as devices are detected, they can be tested for compatibility with Amarok. 2. Collection/Metadata Music-related data in Amarok is handled in Collections, themselves consisting of metadata such as Tracks, Artists etc. The base classes to set up collections are abstract, and several classes which provide more media-device-specific methods are available to be subclassed. It is some of these classes that must be subclassed to add support in Amarok for a device. The heart of it all is MediaDeviceHandler, and this class will be discussed in depth. NNTS = No Need To Subclass 2.1 Connection ConnectionAssistant - Knows how to identify that a particular device matches the type of this CA. Can also create MediaDeviceInfo. MediaDeviceInfo - Contains the device-specific information pertinent to connection, such as mountpoint. 2.2 Factory/Collection MediaDeviceCollectionFactory(NNTS) - Creates MediaDeviceCollections. Provides ConnectionAssistant to register the appropriate device type with the MDM. MediaDeviceCollection - Given a MediaDeviceInfo object, connects to the device described by creating a MediaDeviceHandler. Provides a few other rudimentary functions. MediaDeviceCollectionLocation(NNTS) - Receives/sends orders to add tracks to Collection, remove them, copy them. move them. Forwards the low-level work (the actual copying/deleting etc.) to the MediaDeviceHandler. MediaDeviceMeta*(NNTS) - The actual metadata a Collection consists of: Track, Album, Artist, Genre, Composer. No need to reimplement these, as they are standard across all devices, and the interactions concerning them are dealt with in the MediaDeviceHandler. 2.3 Handler and Capabilities 2.3.1 Handler MediaDeviceHandler - This is it. This is the beast that knows how to do all the low-level tasks specific to a given device: connection, parsing metadata, copying, deletion, changing of metadata, battery%, device capacity, the whole lot of it. Since it is responsible for so many pieces, and since these pieces vary greatly from device to device, it actually relies on Capability-based classes that each know how to do a particular job. Capabilities are similar to Java interfaces, and provide a standard way for the MediaDeviceHandler class to ask the many subclasses of MediaDeviceHandler for what they are capable of, and depending on that, will make different requests. For instance, AudioCDs cannot be written to, so they would have no use for WriteCapability, and don't have to implement it. The MediaDeviceHandler has abstracted the logic so common to several device implementations. The libraries libgpod and libmtp, for instance, are based on a struct that is a linked list of metadata, in particular tracks. The common way to parse the devices with these libraries is to walk down this linked list until all metadata has been read into the appropriate MediaDeviceMeta classes. This is exactly what the Handler does, and the only differences are the names of the linked list structs, and the functions called or member data read to retrieve this data. It is these basic function calls that are then called in the subclasses of the Capability classes, with the top-level logic already standardized and done in the main MediaDeviceHandler class. Note: To see the logic hereto referred, check the MediaDeviceHandler's calls to the Capability classes, and the order of the function calls. This helps to understand how best to map the functions of the Capability interface, to function calls or member-data access using the appropriate library. 2.3.2 Capabilities ReadCapability - Maps the necessary functions to read the structs specific to the device, with the goal of parsing the entire device's metadata. Can also read the device's capacity, used and total. WriteCapability - Receives generic commands related to writing to the device: find where to copy a new track onto the device, copy the track, delete the track. Subclass this Capability also to provide a full mapping onto the functions required to set the metadata on a newly created track struct, and the higher logic of in what order to do this is handled by the main Handler class. ArtworkCapability - Optional. If the device supports artwork, this provides the interface for reading/writing that artwork. PlaylistCapability - Optional. If the device supports playlists, this provides the interface for reading/writing playlists, parsing logic is based again on a linked-list struct that is traversed in a standard fashion. The subclass of this just maps to the appropriate functions to walk the linked list. 3. Appendix/Notes - At the time of writing, there isn't a full implementation of Solid on Windows or Mac, which limits support of devices mainly to Linux. Also, libraries used to interface at the low level (libgpod, libmtp) are Linux-specific.