From: Michael R. <mr...@us...> - 2005-10-04 14:00:48
|
Hi, > imho the second proposition involves far less changes in the lib. Probably. But if we change things anyway, I think we should choose the solution that is believed to last longer. > There is a complicated mecanism introduced to fix potential bugs > and keep the API unchanged. > basically we keep a copy of the frontend metadata string. > this copy is free()ed when the stream is free()ed Right. That's what all the metadata helpers do, I forgot. Now, can't we somehow combine easy data retrieval for frontends with easy data management inside the engine? Let me just dump my ideas here and see what you think of it (I haven't thought this through completely, so I may be completely off track here. I apologize in advance for the long reading.). Our requirements are: * the engine wants to store a large amount of per stream metadata * it wants to store it easily and with low overhead * for plugin developers, publishing metadata should be as easy as writing to a variable (maybe calling a function to push changes) * metadata can have fixed or variable length and it changes constantly * it should be possible to store arrays of arbitrary length * there should be a consistent "not available" value for any metadata * there should be concept of metadata ownership, so that each plugin has an idea, for what data it is responsible (since plugins can be expected to behave, this will probably just be a header comment) * the frontends want to get the metadata easily and in time * write access for frontends would be interesting (see below) What I think of is a global, read-only metadata store in the engine. This would be a big structure, probably including sub-structures to represent, which data the various plugins and engine parts are allowed to change. Everyone inside and outside of xine (plugins and frontends) has a declaration of this and can get a read-only (const) pointer directly to this structure. No copying, everyone sees the same. To allow reading of string data to be safe, the structure has * a read-write-lock, which only the engine is allowed to lock for writing and everyone can (and must) lock for reading * a version number, so you can quickly notice changes (To support the use cases I have in mind, the version+lock combination should have a finer granularity than the entire structure, so I think each sub-structure should have one version+lock.) Frontends and plugins can now easily read any metadata by simply * locking for reading * read data by simply accessing a C struct * unlock (you must guarantee to unlock after a finite time) Changing something is also easy: * get yourself an empty version of this struct, let's call it "the form" (an engine function should provide that) * you can fill in your data by simply writing to a C struct * commit the form to the engine's metadata store * the engine takes the form, iterates through all the entries and, since the struct was all filled with "not available" before, can easily determine, which values have been changed * it locks the global metadata store for writing and propagates the changes, automatically increasing the respective version numbers * the form is freed and since all string data is deep-copied, no assumptions on the provider of the data are made, once the commit is finished Any change can easily be noticed by anyone through an increase in the version number, so you don't have to go through the complete lock/ unlock song and dance to get your info up-to-date. What's the benefit of all this? I think this can immensely unify a couple of now separated concepts of xine. What if we turn things like the current audio channel, audio volume or the playback position into metadata entries and allow frontend write access to them? The mechanism for writing would be the same. Data is held in a central database and every engine component can just check the version numbers of the interesting entries. We might be able to deprecate the current parameter setting functions for this. In case anyone needs to do something synchronously, we could upgrade the version+lock to a version+lock+conditional, so you can do a pthread_cond_wait() which wakes you up on version number increments. I think there is even a nice migration path here: Just start small and move some metadata over to the new central storage, keeping the old API for backwards compatibility (the old API would just be an ordinary client to this database). As our time permits, we can move more data to the new scheme and eventually move over stream and engine parameters too. I thank anyone who managed to stick with me to the end of my brain-dump. Michael |