Discovering new things to watch was once a simple glance at the TV listings, or channel hopping in an idle moment. Today, new video lives on an ever-growing list of Internet video channels, and the volume of new content arriving in those channels is growing daily.
This is a challenge that Berlin based developers of mixd.tv have stepped forward to address, using Qt Quick. Their mixd.tv application lets you discover video content across many internet video providers and share playlists with the mixd.tv community.
Rewriting the UI in QML
mixd.tv’s desktop client was originally written using GTK, but the team realised that they needed a more dynamic and feature rich UI: one that matched the rich nature of the video content users would be accessing. After evaluating several options, the team chose to implement the client’s UI in QML, something we covered in an earlier post.
For another development team member, Jakob Oswald, ‘a really nice feature is the computational layout. This enables us to position a component in relation to the size of another, which is something we often miss in HTML.’
Jakob also used the example of a ticker tape display using a computational layout being easy to realise because the code could calculate offsets from the dynamic width of the ticker’s text content. ‘This is a nice feature, and really useful anywhere the size of a container depends on the dynamic size of one of its children or siblings,’
Intergrating the client and back-end
QML presented the team with a technical challenge, as all the backend logic — database access, models, and web service connectivity — were implemented in Python: recoding was simply not an option. So, the team had to find a way of leveraging this large Python codebase.
In addition, the Python code needed to be separated from the UI implementation to optimise the development work. However, at the time the team started work neither PySide nor PyQt offered QML binding.
The team’s first solution was a single, large C++ class providing the bridge. Then they figured out that they could have their own ListModel, with a PythonListModel behaving like a Python list on the Python side and implemented through a QAbstractItemModel interface on the QML side. Finally they realised they could use the Python meta object model and represent it with a QMetaObject and thereby make arbitrary Python objects accessible from QML.
This method works by inspecting a Python object’s properties at runtime, creating a ProxyObject that subclasses QObject and contains a dynamic Meta Object that reflects the properties of the Python object. As QML accesses all properties of a QObject via the MetaObject, their MetaObject just reimplements metaCall and retrieves data from the Python object. Better still, because all write access to the properties and attributes of the Python objects are routed to a setattr() function, the ProxyObject is aware of changes in the Python object and emits the appropriate onChanged signals.
So in QML the team is able to glue data models and controllers (written in Python) together to define UI behaviour according to the values of Python objects and also call controller methods as a result of user events.
With this solution, separating the application logic from the UI logic became pretty easy. Apart from a small Python file that exposes Python objects under specific names to the UI, the Python code is unaware of the UI.
A fresh release
The mixd.tv application has just received an update < http://mixd.tv/blog#Focus on Video Playback > with plenty of improvements and fixes. It is still in closed beta, but the first 300 readers can use this special link to get early access to the application
For third party developers mixd.tv will be delivering an API to add Video/Channel PlugIns as part of the public release. In addition, a skinning feature will eventually enable users to create their own client skins. If you are interested in these features, please contact firstname.lastname@example.org.