Hello all, I'm developing a small Qt project for SailfishOS (a Linux distribution, Meego descendant, Qt 5 based) and had to use some of PulseAudio (a sound server for POSIX OSes) API functions which are pure C. I've wrapped them in a couple of classes but it's evolving to something bigger now and I'm trying to detach these into a shared library which seems to become a basic PulseAudio binding. It's my first facading of a C library and I'm kind of stuck on the architecture now and hope that someone can share ideas on that.
Obviously, I'm looking forward to encapsulate all the C code in my library and provide library users with Qt-style classes, signals and slots, thus eliminating libpulse dependency for them. My basic architecture is quite simple: for the Qt classes I use d-pointers containing relevant PulseAudio data and static methods to use for PulseAudio callbacks which are called for any kind of events. To emit Qt signals upon PulseAudio events I use q-pointers in these static methods. So this goes like this: // in pseudocode suspiciously resembling C++ class QtPulseAudioContext : public QObject { ... signals: void connected(); private: QtPulseAudioContextPrivate* d; }; class QPulseAudioContextPrivate { pa_context* paContext; // PulseAudio C data QtPulseAudioContext* q; // callback for PulseAudio event static void onContextCallback(..., void* userData) { QtPulseAudioContextPrivate* d = reinterpret_cast< QtPulseAudioContextPrivate* >(userData); .... // processed an event from PulseAudio, redo it Qt style emit d->q->connected(); } }; As for now I'm dealing with three PulseAudio objects: "context" representing connection to PulseAudio server, "sinks" representing audio outputs and "sources" representing audio inputs. Naturally, I've wrapped them as three separate classes. Both sinks and sources operate within single context and any PulseAudio API call involving sinks and sources must provide the corresponding context. When these classes were bundled in my application, I've passed PulseAudio's pa_context* to a ctor of my class, used it internally and was pretty happy with that: // in pseudocode suspiciously resembling C++ class QtPulseAudioContext { QtPulseAudioSource* getSource(...); }; QtPulseAudioSource* QtPulseAudioContext::getSource(...) { ... new QtPulseAudioSource(d->paContext); ... } class QtPulseAudioSource { QtPulseAudioSource(pa_context* context); // pa_context is PulseAudio stuff // the implementation of the following would need to call // PulseAudio API and use pa_context void setDefaultPort(const QString& name); }; Now passing pa_context is a no-go since it exposes PulseAudio dependency to a library user. So my first call is to somehow provide QtPulseAudioContext's private data to a source or sink constructors or even construct their private data in QtPulseAudioContext. I don't think any of both is a good way. The former violates the incapsulation of QtPulseAudioContext, the latter moves initialization of a private data outside the class that owns this data. So with the problem stated, my question is: does anyone know any "good practices" in designing this kind of relationships between classes or can share similar designs to look at? There's no technical problem for me to expose the inner parts of some classes to some other classes, I just wondered if there's a subtle way of doing this. Thanks in advance. Best regards, Dmitriy
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest