Re: [Rhythmbox-devel] State Of The Rhythmbox (3)

On Mon, 2003-09-08 at 02:06, Joshua Haberman wrote:

> RhythmDB is an abstraction that provides these services to Rhythmbox:
> * storing a set of songs and associated attributes
> * adding individual songs to this database
> * querying this set of songs by a number of different criteria

Right.  Also deletion.

> Each song in RhythmDB is represented as a RhythmDBEntry, and are added
> to the DB as such, but results from queries are returned as
> GtkTreeModels.  The UI uses these GtkTreeModels directly as the source
> data for the GtkTreeViews (but how?  the main_model GtkTreeModel only
> has one column: a pointer to a RhythmDBTreeEntry.  How can a GtkTreeView
> display this directly? 

Basically we add a bunch of GtkTreeViewColumns to the main GtkTreeView,
but then call gtk_tree_view_column_set_cell_data_func to set a function
for that column which maps from the RhythmDBEntry pointer to the value
it's displaying (such as a string/int/whatever), by calling
rhythmdb_entry_get with its column number.

> RhythmDB will emit signals when the library changes, but apparently it
> needs the GDK lock to do this!  Why?  And who is intended to catch these
> signals?

The GDK locking stuff is removed now.  In the new plan, the
RhythmDBQueryResult model is what catches the signals.

> RhythmDB is only an API: 

Well, it is also an abstract class which implements some things itself,
but in general yes, it is only an API.

> it needs an implementation to actually do the
> work.  You have implemented one such subclass: RhythmDBTree, which
> stores the DB information in an XML file.


> RhythmDB is multithreaded because it needs to be able to provide
> services to all of these uses:
> * Songs added to the DB by a background thread when the user uses the
> "Add to Library" command
> * Song attributes updated or songs deleted by a background thread when
> Rhythmbox refreshes the DB on startup
> * Queries performed by the main thread
> * Song attributes updated by the main thread when the user modifies song
> properties

Yep, exactly.

> When a RhythmDBEntry is added, changed or is deleted, it is neccesary to
> emit an appropriate signal so that the GtkTreeViews can redraw
> accordingly.  Emitting these signals will cause a synchronous redraw, so
> it is necessary to hold the GDK lock to do so.

Not anymore in the new design.  The RhythmDBQueryModel will queue these
signals, and then the main thread will poll them.

> How many threads are currently in the design and what do they all do? 
> How do they communicate and synchronize (roughly.  I know it's a big
> question)?

First, there is the main UI thread.  Now, the present plan is to have a
separate thread for executing a query, which will populate a
RhythmDBQueryModel.  This model will attach to several database signals
to keep itself in sync.

Now we will have another thread which is used for loading the XML file
at startup.  This simply translates into a bunch of database additions. 
Simultaneously, we will create a thread that watches for these database
additions, and pushes them onto a queue.  It then reads from this queue
and checks to see if there are any metadata updates (or the file was
deleted).  If so it performs the appropriate work to update the

We will probably have some sort of file monitoring thread eventually. 
This might turn out to be the same thing as the latter thread above.

How exactly to handle deletions from the UI is another issue.  I think
we may need another queue for that, I'm still not sure.

> I don't quite understand the problem.
> 1. Why would you need to call the gtk_tree_model_* functions before
> processing queued changes by emitting the appropriate signals?

We just need a way to sync up the UI.  I think this problem has been
solved as outlined in my other mail.

> 2. Why is it harmful to call the gtk_tree_model_* functions before
> processing queued changes?

The deal is that we can't call e.g. gtk_tree_model_row_changed while the
GtkTreeView is calling gtk_tree_model_get_value.

> I'm skeptical that another thread is necessary here.

It isn't necessarily - we could have an idle handler poll, as well.

> > One other thought occurs to me - if you were trying to implement
> > RhythmDB with an SQL database, I'm not sure how you could provide the
> > kind of fine-grained notification like "This particular entry changed"
> > (maybe with some sort of database-specific trigger or something?  I
> > don't know enough about SQL databases to say.)
> If I'm understanding your question correctly, I think the easiest way
> would be to add information to the database row indicating whether the
> GUI needed to have this row refreshed.  Either a boolean column called
> "needs_redraw" or a timestamp column that you could compare with the
> last time you processed GUI updates.

This information will be represented in the queue of pending updates in
the RhythmDBQueryModel.

> What do you mean?  Are you saying GTK+ only allows you to perform GUI
> operations in the main thread?  I thought that this was the purpose of
> the GDK lock, to allow GUI operations from other threads.

You can use the GDK lock to perform GUI operations in other threads. 
But since GTK+/GDK isn't reentrant at all, it just isn't very useful.

> I didn't mean to imply it was the same problem, just illustrate a
> situation where the GUI is polling for backend changes instead of the
> backend updating the GUI.  And as far as implementing this disk/audio
> model for Rhythmbox, I was under the impression that all disk and audio
> i/o was handled by Gstreamer !

Well, we are constructing the GStreamer pipeline manually, and that
pipeline involves threads.  It turns out that we are already using two
threads as you described.

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]