Inside Kdenlive projects, we have to differentiate between the bin clips and the bin folders. The information about clips and folders is stored in separate regions of a Kdenlive project file, as we'll now see...
While MLT doesn't care about organizing clips (or producers to be correct), an important feature of Kdenlive are its hierarchical bin folders. This way, more complex projects with lots of clips can be managed more easily. To me, bin folders are one of the most important feature that make Kdenlive stick out from the competition.
When it comes to Kdenlive projects as such, the so-called main bin is the place to look at. It's a playlist with the unique id of "main bin". And it houses a lot of project-specific information. Such as the bin folder information, as we can quickly find out:
<mlt> <playlist id="main bin"> <property name="kdenlive:folder.-1.1">1st. Folder</property> <property name="kdenlive:folder.-1.2">2nd. Folder</property> <property name="kdenlive:folder.1.3">Subfolder inside 1st. Folder</property> </playlist> </mlt>As we can deduce from the XML snippet above, Kdenlive stores its bin folder hierarchy in form of properties with names that start with "kdenlive:folder.". Following are two numbers in each folder property name that have these semantics:
- the folder ident of the parent folder, or -1 in case of a top-level folder.
- the ident of folder itself. This is simply a cardinal number starting with 1, thus without any hierarchy. Folder idents are assigned in the same sequence the folders were created in this project.
So the project XML snipped represents this project bin folder structure:
- folder #1 with title "1st. Folder"
- folder #2 with title "2nd. Folder"
- folder #3 with title "Subfolder inside 1st. Folder"
But this leaves the question as to how Kdenlive knows which bin clips belong into which folders?
For today's topic of bin folders it is sufficient to understand that from MLT's perspective bin clips are just <producers>. We'll cover bin clips in more detail in a dedicated post about bin clips. And producers in MLT don't have any hierarchy.
In consequence, by scanning the producers inside a Kdenlive project we'll get all bin clips, but we don't get the bin folder hierarchy. Yet, bin clips/producers need to be assigned to bin folders somehow. So let's see what we can find when looking more closely at producers...
<mlt> <producer id="2" title="Anonymous Submission" out="49" in="0"> <property name="kdenlive:folderid">2</property> </producer> </mltNow things fall into place: the folder identifiers get stored in additional "kdenlive:folderid" properties inside producers. This way, Kdenlive recreates the project bin clip contents when loading a project. The folder identifier is the text content of such a folder property and simply references a specific bin folder by identifier. In our example above, the bin clip with id="2" is contained in the folder id="2"("kdenlive:folder.1.2" to be precise), which is the one titled "2nd. Folder".
An identifier of -1 then indicates that the clip is at the root level, for which is no explicit root folder.
As can also be seen from the examples above, linking bin clips to their folder elements can be slightly involved in some pure XML tools, such as XSLT stylesheet transformations. But at least it is doable in pure XPath 1.0 without extensions. Phew!
The example below assumes that you got a folder identifier somehow in the variable folderid. It will then lookup the title and parent folder of this folder.
<xsl:variable name="folderid" select="..."/> <xsl:variable name="foldertitle" select="/mlt/playlist[@id='main bin']/property[starts-with(@name,'kdenlive:folder.') and string-after(string-after(@name,'.'),'.')=$folderid]/text()"/> <xsl:variable name="parentfolderid" select="substring-before(substring-after(/mlt/playlist[@id='main bin']/property[starts-with(@name,'kdenlive:folder.') and string-after(string-after(@name,'.'),'.')=$folderid]/@name,'.'),'.')"/>