Пример #1
0
int
main (int argc, char **argv)
{
	GtkWidget *main_window;
	GtkTreeModel *main_model;
	GtkTreeIter iter;
	RBEntryView *view;
	RhythmDB *db;
	RhythmDBEntry *entry;

	gtk_init (&argc, &argv);
	gdk_threads_init ();
	rb_thread_helpers_init ();
	rb_file_helpers_init (TRUE);
	rb_stock_icons_init ();
	rb_debug_init (TRUE);

	GDK_THREADS_ENTER ();

	db = rhythmdb_tree_new ("test");

	rhythmdb_write_lock (db);

	entry = create_entry (db, "file:///sin.mp3",
			      "Sin", "Pretty Hate Machine", "Nine Inch Nails", "Rock");
	
	rhythmdb_write_unlock (db);

	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TYPE, RHYTHMDB_ENTRY_TYPE_IGNORE,
				RHYTHMDB_QUERY_END);

	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));
	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));

	main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

	view = rb_entry_view_new (db, rb_file ("rb-entry-view-library.xml"));

	rb_entry_view_set_query_model (view, RHYTHMDB_QUERY_MODEL (main_model));

	gtk_container_add (GTK_CONTAINER (main_window), GTK_WIDGET (view));

	g_signal_connect (G_OBJECT (main_window), "destroy",
			  G_CALLBACK (gtk_main_quit), NULL);

	gtk_widget_show_all (GTK_WIDGET (main_window));

	gtk_main ();
	
	rhythmdb_shutdown (db);
	g_object_unref (G_OBJECT (db));
	GDK_THREADS_LEAVE ();
	
	exit (0);
}
static gboolean
_remove_entry_cb (GtkTreeModel *model,
		  GtkTreePath *path,
		  GtkTreeIter *iter,
		  RhythmDBPropertyModel *propmodel)
{
	RhythmDBEntry *entry;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model), iter);
	rhythmdb_property_model_entry_removed_cb (RHYTHMDB_QUERY_MODEL (model),
						  entry,
						  propmodel);
	rhythmdb_entry_unref (entry);
	return FALSE;
}
static gboolean
save_playlist_foreach (GtkTreeModel *model,
		       GtkTreePath *path,
		       GtkTreeIter *iter,
		       SavePlaylistData *data)
{
	RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (data->source);
	RhythmDBEntry *entry;
	TotemPlPlaylistIter pl_iter;
	const char *host_uri;
	char *uri;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model), iter);
	if (entry == NULL) {
		return FALSE;
	}

	host_uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
	uri = rb_generic_player_source_uri_to_playlist_uri (priv->player_source, host_uri, data->playlist_type);

	totem_pl_playlist_append (data->playlist, &pl_iter);
	totem_pl_playlist_set (data->playlist, &pl_iter, TOTEM_PL_PARSER_FIELD_URI, uri, NULL);
	set_field_from_property (data->playlist, &pl_iter, entry, RHYTHMDB_PROP_ARTIST, TOTEM_PL_PARSER_FIELD_AUTHOR);
	set_field_from_property (data->playlist, &pl_iter, entry, RHYTHMDB_PROP_GENRE, TOTEM_PL_PARSER_FIELD_GENRE);
	set_field_from_property (data->playlist, &pl_iter, entry, RHYTHMDB_PROP_ALBUM, TOTEM_PL_PARSER_FIELD_ALBUM);
	set_field_from_property (data->playlist, &pl_iter, entry, RHYTHMDB_PROP_TITLE, TOTEM_PL_PARSER_FIELD_TITLE);
	rhythmdb_entry_unref (entry);

	g_free (uri);
	return FALSE;
}
Пример #4
0
/**
 * rb_playlist_source_set_query_model:
 * @source: the #RBPlaylistSource
 * @model: the new #RhythmDBQueryModel
 *
 * Sets a new query model for the playlist.  This updates the
 * entry view to use the new query model and also updates the
 * source query-model property.
 *
 * This needs to be called when the playlist subclass
 * creates a new query model.
 */
void
rb_playlist_source_set_query_model (RBPlaylistSource *source,
				    RhythmDBQueryModel *model)
{
	g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source));

	if (source->priv->model != NULL) {
		/* if the query model is replaced, the set of entries in
		 * the playlist will change, so we should mark the playlist dirty.
		 */
		source->priv->dirty = TRUE;
		g_signal_handlers_disconnect_by_func (source->priv->model,
						      G_CALLBACK (rb_playlist_source_row_deleted),
						      source);
		g_object_unref (source->priv->model);
	}

	source->priv->model = model;

	if (source->priv->model != NULL) {
		g_object_ref (source->priv->model);
		g_signal_connect_object (source->priv->model, "row_deleted",
					 G_CALLBACK (rb_playlist_source_row_deleted), source, 0);
	}

	rb_entry_view_set_model (source->priv->songs, RHYTHMDB_QUERY_MODEL (source->priv->model));

	g_object_set (source, "query-model", source->priv->model, NULL);
}
Пример #5
0
static gboolean
collect_entries (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **list)
{
	RhythmDBEntry *entry;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model), iter);
	*list = g_list_prepend (*list, rhythmdb_entry_ref (entry));
	return FALSE;
}
static void
playlist_row_inserted_cb (GtkTreeModel       *model,
			  GtkTreePath        *path,
			  GtkTreeIter        *iter,
			  RBDiscRecorderPlugin *pi)
{
	RhythmDBEntry *entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model), iter);

	playlist_entries_changed (model, entry, pi);

	rhythmdb_entry_unref (entry);
}
Пример #7
0
static void
rhythmdb_property_model_row_inserted_cb (GtkTreeModel *model,
					 GtkTreePath *path,
					 GtkTreeIter *iter,
					 RhythmDBPropertyModel *propmodel)
{
	RhythmDBEntry *entry;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model), iter);

	rhythmdb_property_model_insert (propmodel, entry);
	rhythmdb_property_model_sync (propmodel);

	rhythmdb_entry_unref (entry);
}
Пример #8
0
static gboolean
set_extract (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
	RBAudioCDEntryData *extra_data;
	RhythmDBEntry *entry;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model),
						    iter);
	if (entry != NULL) {
		extra_data = RHYTHMDB_ENTRY_GET_TYPE_DATA (entry, RBAudioCDEntryData);
		extra_data->extract = GPOINTER_TO_INT (data);

		gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, iter);
		rhythmdb_entry_unref (entry);
	}
	return FALSE;
}
Пример #9
0
static void
extract_cell_data_func (GtkTreeViewColumn *column,
			GtkCellRenderer *renderer,
			GtkTreeModel *tree_model,
			GtkTreeIter *iter,
			RBAudioCdSource *source)
{
	RBAudioCDEntryData *extra_data;
	RhythmDBEntry *entry;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (tree_model), iter);
	if (entry != NULL) {
		extra_data = RHYTHMDB_ENTRY_GET_TYPE_DATA (entry, RBAudioCDEntryData);
		gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (renderer), extra_data->extract);
		rhythmdb_entry_unref (entry);
	}
}
Пример #10
0
static void
rb_playlist_source_row_deleted (GtkTreeModel *model,
				GtkTreePath *path,
				RBPlaylistSource *source)
{
	RhythmDBEntry *entry;
	RBRefString *location;

	entry = rhythmdb_query_model_tree_path_to_entry (RHYTHMDB_QUERY_MODEL (model),
							 path);

	location = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_LOCATION);
	if (g_hash_table_remove (source->priv->entries, location))
		source->priv->dirty = TRUE;

	rb_refstring_unref (location);
	rhythmdb_entry_unref (entry);
}
static void
save_playlist_entry (GtkTreeModel *model, GtkTreeIter *iter,
		     char **uri, char **title,
		     gboolean *custom_title,
		     RBGenericPlayerPlaylistSource *source)
{
	RBGenericPlayerPlaylistSourcePrivate *priv = GET_PRIVATE (source);
	RhythmDBEntry *entry;
	const char *host_uri;

	entry = rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model),
						    iter);
	if (entry == NULL) {
		return;
	}

	host_uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
	*uri = rb_generic_player_source_uri_to_playlist_uri (priv->player_source, host_uri);
	*title = rhythmdb_entry_dup_string (entry, RHYTHMDB_PROP_TITLE);
	*custom_title = TRUE;
}
int
main (int argc, char **argv)
{
	RhythmDB *db;
	RhythmDBEntry *entry, *entry2, *entry3, *entry4;
	GtkTreeModel *main_model;
	GtkTreeIter iter;
	guint testnum = 1;
	query_func qfunc;

	gtk_init (&argc, &argv);
	gdk_threads_init ();
	rb_thread_helpers_init ();
	rb_debug_init (TRUE);

	GDK_THREADS_ENTER ();

	qfunc = rhythmdb_do_full_query;

begin:	

	db = rhythmdb_tree_new ("test");

	/*
	 *  TEST 1: Entry creation with album
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_write_lock (db);

	entry = create_entry (db, "file:///sin.mp3",
			      "Sin", "Pretty Hate Machine", "Nine Inch Nails", "Rock");
	
	rhythmdb_write_unlock (db);
	g_print ("Test %d\n", testnum);
	
	testnum++;
	/*
	 *  TEST 2: Do a query for all songs, verify our single song is in it
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	qfunc (db, main_model,
	       RHYTHMDB_QUERY_PROP_EQUALS,
	       RHYTHMDB_PROP_TYPE, RHYTHMDB_ENTRY_TYPE_IGNORE,
	       RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	/* We should only have one entry. */
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 3: Do a query for songs named "Sin"
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Sin",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	/* We should only have one entry. */
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 4: Do a query for songs named "Cow", should be empty
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Cow",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (!gtk_tree_model_get_iter_first (main_model, &iter));

	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 5
	 *  Do a query for songs named "Cow" and "Sin", should be empty.
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Cow",
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Sin",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (!gtk_tree_model_get_iter_first (main_model, &iter));

	DESTROY_MODELS ();
	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 6
	 *  Do a query for songs named "Cow" or "Sin", should have our song.
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Cow",
				RHYTHMDB_QUERY_DISJUNCTION,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Sin",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	/* We should only have one entry. */
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 7
	 *  Do a query for songs with Genre "Rock", should have our song.
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_GENRE, "Rock",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	/* We should only have one entry. */
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 8
	 *  Do a query for songs with Genre "Nine Inch Nails",
	 *  should be empty.
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_GENRE, "Nine Inch Nails",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (!gtk_tree_model_get_iter_first (main_model, &iter));

	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);
	
	testnum++;
	/*
	 *  TEST 9
	 *  Do a query for songs with album "Pretty Hate Machine",
	 *  should have our song.
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_ALBUM, "Pretty Hate Machine",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	/* We should only have one entry. */
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	/*
	 *  TEST 10
	 *  Do a query for songs with artist "Nine Inch Nails",
	 *  should have our song.
	 */
	g_print ("Test %d\n", testnum);
	rhythmdb_read_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_ARTIST, "Nine Inch Nails",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	/* We should only have one entry. */
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	DESTROY_MODELS ();

	rhythmdb_read_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	g_print ("Test %d\n", testnum);
	rhythmdb_write_lock (db);

	entry2 = create_entry (db, "file:///head like a hole.mp3",
			       "Head Like A Hole", "Pretty Hate Machine",
			       "Nine Inch Nails", "Rock");

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_ARTIST, "Nine Inch Nails",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	g_assert (gtk_tree_model_iter_next (main_model, &iter));
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	VERIFY_MAIN_MODEL (entry2);
	DESTROY_MODELS ();
	
	rhythmdb_write_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	g_print ("Test %d\n", testnum);
	rhythmdb_write_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_ALBUM, "Pretty Hate Machine",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	g_assert (gtk_tree_model_iter_next (main_model, &iter));
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	VERIFY_MAIN_MODEL (entry2);
	DESTROY_MODELS ();
	
	rhythmdb_write_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	g_print ("Test %d\n", testnum);
	rhythmdb_write_lock (db);

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_GENRE, "Rock",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	g_assert (gtk_tree_model_iter_next (main_model, &iter));
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	VERIFY_MAIN_MODEL (entry2);
	DESTROY_MODELS ();
	
	rhythmdb_write_unlock (db);
	g_print ("Test %d\n", testnum);

	g_print ("Test %d\n", testnum);
	rhythmdb_write_lock (db);

	entry3 = create_entry (db, "file:///angel.ogg",
			       "Angel", "Mezzanine", "Massive Attack", "Electronica");

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_GENRE, "Electronica",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Mezzanine", "Massive Attack", "Electronica");
	VERIFY_MAIN_MODEL (entry3);
	DESTROY_MODELS ();
	
	rhythmdb_write_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;
	g_print ("Test %d\n", testnum);
	rhythmdb_write_lock (db);

	entry4 = create_entry (db, "file:///killa bees.ogg",
			       "Killa Bees", "Armageddon", "Usual Suspects", "Drum N' Bass");

	main_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty (db));
	rhythmdb_do_full_query (db, main_model,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Angel",
				RHYTHMDB_QUERY_DISJUNCTION,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Sin",
				RHYTHMDB_QUERY_DISJUNCTION,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Head Like A Hole",
				RHYTHMDB_QUERY_DISJUNCTION,
				RHYTHMDB_QUERY_PROP_EQUALS,
				RHYTHMDB_PROP_TITLE, "Killa Bees",
				RHYTHMDB_QUERY_END);
	wait_for_model_completion (RHYTHMDB_QUERY_MODEL (main_model));

	g_assert (gtk_tree_model_get_iter_first (main_model, &iter));
	g_assert (gtk_tree_model_iter_next (main_model, &iter));
	g_assert (gtk_tree_model_iter_next (main_model, &iter));
	g_assert (gtk_tree_model_iter_next (main_model, &iter));
	g_assert (!gtk_tree_model_iter_next (main_model, &iter));

	VERIFY_META_MODELS ("Mezzanine", "Massive Attack", "Electronica");
	VERIFY_META_MODELS ("Armageddon", "Usual Suspects", "Drum N' Bass");
	VERIFY_META_MODELS ("Pretty Hate Machine", "Nine Inch Nails", "Rock");
	VERIFY_MAIN_MODEL (entry);
	VERIFY_MAIN_MODEL (entry2);
	VERIFY_MAIN_MODEL (entry3);
	VERIFY_MAIN_MODEL (entry4);
	DESTROY_MODELS ();
	
	rhythmdb_write_unlock (db);
	g_print ("Test %d\n", testnum);

	testnum++;

	if (qfunc == rhythmdb_do_full_query) {
		rhythmdb_shutdown (db);
		g_object_unref (G_OBJECT (db));
		qfunc = rhythmdb_do_full_query_async;
		goto begin;
	}

	/*
	 * THE END
	 */
	rhythmdb_shutdown (db);
	g_object_unref (G_OBJECT (db));
	GDK_THREADS_LEAVE ();
	
	exit (0);
}