Hello everyone,
I had the opportunity to work on the 2014 MATE GSoC project aimed on
providing a replacement for deprecated GstMixer functionality, used by
the mate-media and mate-settings-daemon packages.
*** The state before my project:
The mate-media package used to provide two distinct volume control
applications. A more modern PulseAudio-based one called MATE Volume
Control and a legacy GstMixer-based one. The reason for supporting two
separate volume control applications was portability. The newer
PulseAudio-based application relies on having functional PulseAudio
support in the operating system and many (especially BSD) systems choose
not to use PulseAudio by default and prefer the legacy GstMixer-based
application instead.
The main problem with GstMixer is that it used to be a part of the
gstreamer package, which was removed from gstreamer in version 1.0 and
the application relies on the now unsupported version 0.10. This creates
maintenance overhead as it requires operating systems and distributions
to keep providing packages of an unsupported library.
My project was based on the idea of removing the legacy GstMixer-based
application from MATE and improving the newer PulseAudio-based one to
support other sound systems as well. The newer application contained a
somehow separable PulseAudio support code, which was also duplicated in
mate-settings-daemon to provide support for multimedia key actions
(changing volume and muting).
I decided the best approach would be to develop a new library, providing
an abstraction layer for PulseAudio and other sound systems and allow
both the volume control application and the settings daemon to use this
library instead of duplicating the existing PulseAudio support code.
I also decided to write the library from scratch, using ideas from both
the PulseAudio support code in the applications and also from GstMixer.
*** How my work progressed:
At the start of my project I created a library called libmatemixer.
Designing a reasonable API for the library turned out to be very
challenging as there are big design differences between PulseAudio and
other sound systems. The volume control application also uses many
PulseAudio features, which are not available in other sound systems. The
approach I took was to make the API initially resemble the existing
PulseAudio support code, but in a more robust way to make room to later
support at least ALSA and OSS sound systems without requiring larger
design changes of the API.
Even so, I couldn't avoid changing and rethinking the API design several
times during the project as there were always cases where some parts
just didn't fit. I'd say this was one of the major struggles I had with
the project. Each time you see a well designed API, it may make you
think that it must be so easy to design such thing yourself, but I
learned the hard way that it is not :)
During the first half of the coding period I made the library fully
functional with most PulseAudio features working and I did some initial
work done on porting the applications. I managed to follow my project
schedule almost exactly as I planned it.
The second half turned out to be much more challenging. I spent much
more time on the project (some days 12-16 hours a day including most
weekends), but as the code became more complex, the progress was much
slower than I anticipated.
At first I continued porting the applications until I got them into a
reasonable shape. I took more time with the volume control program,
cleaning it up, rewriting some parts to better match libmatemixer
design, removing dead code and improving GTK3 support (which wasn't
really a part of the project, but the idea of making user-visible
changes was very tempting :)
Then I moved back to libmatemixer and started working on supporting the
ALSA and OSS sound systems. I added initial support for both of them
fairly quickly, in less than 2 weeks, but making them fully functional
took me pretty much another month of time (mainly due to making API
changes in libmatemixer, incomplete documentation of both sound systems
and OSS differences on Linux/FreeBSD/other BSDs).
I also spent about a week looking into OSS version 4, but after seeing
how difficult it is to map OSS4 mixer elements to libmatemixer, I
decided to postpone it and later abandoned it completely.
About 2-3 weeks before the end of the coding period, I finally started
cleaning things up and adapting the PulseAudio code and the applications
to the API changes I made while working on ALSA and OSS. This was the
most difficult time for me, I still kept finding API inconsistencies,
thinking, rethinking, and my progress was very slow. As I had to spend
most of the polishing time fixing problems, the code didn't receive as
much testing and polishing as I wanted to, but I managed to complete it
and with several late fixes, I can say that the code works very well.
*** So what is libmatemixer like?
The libmatemixer library makes heavy use of GLib and GObject libraries
and is written in the C programming language. I have taken care to
provide an easy to use API, which will be familiar to programmers
experienced with PulseAudio or GstMixer. My intention was to make the
library dynamic, flexible, robust, extensible, make good use of GObject
features (properties and signals) and follow the OOP principles.
Support for each sound system is provided as a dynamically loaded module
(a plugin) and allows for individual modules to be packaged separately.
While the supported sound systems differ greatly in functionality, they
share a single abstract API and their capabilities can be queried
dynamically by applications. They also don't need to worry about which
sound system they are running on (though the library tells them if they
ask).
The library provides one main entry point to communicate with a sound
system, called a Context. Context can be associated with some particular
sound system or it can select a working sound system automatically. When
done so, the Context can be used to query the system for a list of sound
cards and streams (described in the next paragraph).
Most sound cards are capable of providing sound input (recording) and
output (playback), in libmatemixer, these input/output "channels" are
called streams. Streams may not only be found on sound cards, but a
stream may for example exist to output sound over a network (this is
possible on PulseAudio and supported by libmatemixer).
Each stream can contain an arbitrary number of volume controls and
switches. Volume control is simply a volume slider with any number of
channels. Depending on the sound system, controls can have
readable/writable volume, a mute toggle and may even support peak level
monitoring. Per-application volume controls, per-channel volume, decibel
values, balancing, fading and volume limits are all supported. Switches
can be used for example to change the active recording source of a sound
card or the sound card profile on PulseAudio.
All the elements in libmatemixer are dynamic, they can appear and
disappear at any time (for example when user unplugs a USB sound card or
starts her music player) and the library provides asynchronous
notifications for all events and on all the sound systems using the
GObject facilities.
This was only a brief intro and a fraction of supported features. I have
taken care to provide support to all features which may be useful to
applications and to allow writing both PulseAudio-style mixers (such as
the MATE Volume Control with a single input/output volume slider) as
well as applications wanting to provide many controls at once, such as
the legacy GstMixer application, XFCE mixer or KMix.
As you can see, my goal was to provide a flexible library, not just to
match the needs of a single application.
*** Final word
I must say that working on the project was challenging, but I enjoyed it
a lot and it was a valuable learning experience. I hope libmatemixer
will get a chance and that we can provide it as a production quality
code for the next MATE release.
I'd like to thank my mentors Stefano and Martin and the openSUSE program
admins Manu and Saurabh for giving me this opportunity (you've all been
great!) and of course everyone who followed my project (I'm sure there
was at least one person hiding in the shadows).
If you are interested in seeing or playing with the code, see my GitHub:
https://github.com/mratajsky
I keep providing fixes for the packages and they reside in a separate
branch called after-gsoc, this branch contains some important fixes and
will probably give you a better testing experience ;)
*** But wait, we want screenshots!
Cielos! Seriously?
Alright, I somehow expected you'd ask, so let me show you MATE Volume
Control running on libmatemixer using Pulse, ALSA and OSS (notice the
differently named devices, but they are made on the same hardware and OS).
https://dl.dropboxusercontent.com/u/28460082/MATE/alsa-1.png
https://dl.dropboxusercontent.com/u/28460082/MATE/alsa-2.png
https://dl.dropboxusercontent.com/u/28460082/MATE/oss-1.png
https://dl.dropboxusercontent.com/u/28460082/MATE/oss-2.png
https://dl.dropboxusercontent.com/u/28460082/MATE/oss-3.png
https://dl.dropboxusercontent.com/u/28460082/MATE/pulse-1.png
https://dl.dropboxusercontent.com/u/28460082/MATE/pulse-2.png
https://dl.dropboxusercontent.com/u/28460082/MATE/pulse-3.png
https://dl.dropboxusercontent.com/u/28460082/MATE/pulse-4.png
Thank you and see you next year,
Michal ;-)
--
To unsubscribe, e-mail: opensuse-project+unsubscribe(a)opensuse.org
To contact the owner, email: opensuse-project+owner(a)opensuse.org