From 90008b8b917620152113f9222c1bda50e646335f Mon Sep 17 00:00:00 2001 From: Jens Georg Date: Mon, 25 May 2009 22:01:56 +0200 Subject: [PATCH] core: Add basic media database class --- configure.ac | 6 ++ src/rygel/Makefile.am | 12 ++-- src/rygel/rygel-media-db.vala | 146 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 src/rygel/rygel-media-db.vala diff --git a/configure.ac b/configure.ac index 32d5bfa..0f1cb18 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,7 @@ GEE_REQUIRED=0.1.5 UUID_REQUIRED=1.41.3 LIBSOUP_REQUIRED=2.26.0 GTK_REQUIRED=2.16 +LIBSQLITE3_REQUIRED=3.5 PKG_CHECK_MODULES(LIBGUPNP, gupnp-1.0 >= $GUPNP_REQUIRED) PKG_CHECK_MODULES(LIBGUPNP_AV, gupnp-av-1.0 >= $GUPNP_AV_REQUIRED) @@ -40,6 +41,7 @@ PKG_CHECK_MODULES(LIBGIO, gio-2.0 >= $GIO_REQUIRED) PKG_CHECK_MODULES(GEE, gee-1.0 >= $GEE_REQUIRED) PKG_CHECK_MODULES(UUID, uuid >= $UUID_REQUIRED) PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4 >= $LIBSOUP_REQUIRED) +PKG_CHECK_MODULES(LIBSQLITE3, sqlite3 >= $LIBSQLITE3_REQUIRED) AC_PATH_PROG(GCONFTOOL, gconftool-2) AM_GCONF_SOURCE_2 @@ -98,6 +100,10 @@ if test x$enable_vala = xyes ; then AC_CHECK_FILE("${VAPIDIR}/gee-1.0.vapi", true, [AC_MSG_ERROR("Unable to find Vala bindings for gee-1.0")]) + + AC_CHECK_FILE("${VAPIDIR}/sqlite3.vapi", + true, + [AC_MSG_ERROR("Unable to find Vala bindings for sqlite3")]) else VAPIDIR=`echo ${datadir}/vala/vapi` fi diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am index 6819082..c416e09 100644 --- a/src/rygel/Makefile.am +++ b/src/rygel/Makefile.am @@ -21,6 +21,7 @@ AM_CFLAGS = $(LIBGUPNP_CFLAGS) \ $(UUID_CFLAGS) \ $(LIBSOUP_CFLAGS) \ $(LIBDBUS_GLIB_CFLAGS) \ + $(LIBSQLITE3_CFLAGS) \ -I$(top_srcdir) -DDATA_DIR='"$(shareddir)"' \ -DPLUGIN_DIR='"$(plugindir)"' -DDESKTOP_DIR='"$(desktopdir)"'\ -include config.h @@ -61,8 +62,8 @@ BUILT_SOURCES = rygel-1.0.vapi \ rygel-media-container.c \ rygel-simple-async-result.c \ rygel-media-item.c \ - rygel-transcoder.c \ rygel-metadata-extractor.c \ + rygel-media-db.c \ rygel-mp2ts-transcoder.c \ rygel-mp3-transcoder.c \ rygel-l16-transcoder.c \ @@ -116,7 +117,8 @@ rygel_SOURCES = $(VAPI_SOURCE_FILES) \ rygel.stamp: $(filter %.vala,$(rygel_SOURCES)) $(VALAC) -C --vapidir=$(srcdir) --thread \ --pkg cstuff --pkg gupnp-1.0 --pkg gupnp-av-1.0 --pkg dbus-glib-1 \ - --pkg gconf-2.0 --pkg gstreamer-0.10 --pkg gio-2.0 --pkg gee-1.0 $^ + --pkg gconf-2.0 --pkg gstreamer-0.10 --pkg gio-2.0 --pkg gee-1.0 \ + --pkg sqlite3 $^ touch $@ rygel_LDADD = $(LIBGUPNP_LIBS) \ @@ -128,6 +130,7 @@ rygel_LDADD = $(LIBGUPNP_LIBS) \ $(UUID_LIBS) \ $(LIBSOUP_LIBS) \ $(LIBDBUS_GLIB_LIBS) \ + $(LIBSQLITE3_LIBS) \ librygel-configuration.a rygel_LDFLAGS = -export-dynamic @@ -165,12 +168,13 @@ VAPI_SOURCE_FILES = rygel-configuration.vala \ rygel-mp2ts-transcoder-bin.vala \ rygel-mp3-transcoder-bin.vala \ rygel-l16-transcoder-bin.vala \ - rygel-gst-utils.vala + rygel-gst-utils.vala \ + rygel-media-db.vala rygel-1.0.vapi: $(VAPI_SOURCE_FILES) $(VALAC) -H rygel.h -C --library=rygel-1.0 --vapidir=$(srcdir) \ --pkg cstuff --pkg gupnp-1.0 --pkg gupnp-av-1.0 --pkg gconf-2.0 \ - --pkg gee-1.0 --pkg gstreamer-0.10 --pkg dbus-glib-1 \ + --pkg gee-1.0 --pkg gstreamer-0.10 --pkg sqlite3 --pkg dbus-glib-1 \ $(VAPI_SOURCE_FILES) noinst_LIBRARIES = librygel-configuration.a diff --git a/src/rygel/rygel-media-db.vala b/src/rygel/rygel-media-db.vala new file mode 100644 index 0000000..e9271b9 --- /dev/null +++ b/src/rygel/rygel-media-db.vala @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2009 Jens Georg . + * + * Author: Jens Georg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + */ + +using Gee; +using Sqlite; + +public class Rygel.MediaDB : Object { + private Database db; + private const string schema_version = "1"; + private const string db_schema_v1 = + "BEGIN;" + + "CREATE TABLE Schema_Info (version TEXT NOT NULL); " + + "CREATE TABLE Object_Type (id INTEGER PRIMARY KEY, " + + "desc TEXT NOT NULL);" + + "CREATE TABLE Meta_Data (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "size INTEGER NOT NULL, " + + "mime_type TEXT NOT NULL, " + + "width INTEGER, " + + "height INTEGER, " + + "class TEXT NOT NULL, " + + "title TEXT NOT NULL, " + + "author TEXT, " + + "album TEXT, " + + "date TEXT, " + + "bitrate INTEGER, " + + "sample_freq INTEGER, " + + "bits_per_sample INTEGER, " + + "channels INTEGER, " + + "track, " + + "color_depth);" + + "CREATE TABLE Object (id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "upnp_id TEXT UNIQUE, " + + "type_fk INTEGER REFERENCES Object_Type(id), " + + "metadata_fk INTEGER REFERENCES Meta_Data(id) " + + "ON DELETE CASCADE);" + + "CREATE TABLE Uri (object_fk INTEGER REFERENCES Object(id), "+ + "uri TEXT NOT NULL);" + + "INSERT INTO Object_Type (id, desc) VALUES (0, 'Container'); " + + "INSERT INTO Object_Type (id, desc) VALUES (1, 'Item'); " + + "INSERT INTO Schema_Info (version) VALUES ('" + MediaDB.schema_version + + "'); " + + "END;"; + + + public MediaDB (string name) { + var rc = Database.open (name, out this.db); + if (rc != Sqlite.OK) { + warning ("Failed to open database: %d, %s", + rc, + db.errmsg ()); + return; + } + + weak string[] schema_info; + int nrows; + int ncolumns; + // FIXME error message causes segfaul + rc = db.get_table ("SELECT version FROM Schema_Info;", + out schema_info, + out nrows, + out ncolumns, + null); + + if (rc == Sqlite.OK) { + if (nrows == 1 && ncolumns == 1) { + if (schema_info[0] == schema_version) { + debug ("Media DB schema has current version"); + } else { + debug ("Schema version differs... checking for upgrade"); + // FIXME implement if necessary + } + } else { + warning ("Incompatible schema... cannot proceed"); + db = null; + return; + } + } else { + debug ("Could not find schema version; checking for empty database..."); + rc = db.get_table ("SELECT * FROM sqlite_master", + out schema_info, + out nrows, + out ncolumns, + null); + if (rc != Sqlite.OK) { + warning ("Something weird going on: %s", + db.errmsg ()); + db = null; + return; + } + + if (nrows == 0) { + debug ("Empty database, creating new schema version %s", + schema_version); + if (!create_schema ()) { + return; + } + } else { + warning ("Incompatible schema... cannot proceed"); + return; + } + } + } + + /** + * Create the current schema. + * + * If schema creation fails, schema will be rolled back + * completely. + * + * @returns: true on success, false on failure + */ + private bool create_schema () { + var rc = db.exec (db_schema_v1); + if (rc == Sqlite.OK) { + debug ("Schema created"); + return true; + } else { + warning ("Could not create schema: %d, %s", + rc, + db.errmsg ()); + rc = db.exec ("ROLLBACK;"); + return false; + } + } +} -- 2.7.4