Index: mfd/plugins/mmusic/mmusic.cpp
===================================================================
--- mfd/plugins/mmusic/mmusic.cpp	(revision 10565)
+++ mfd/plugins/mmusic/mmusic.cpp	(working copy)
@@ -77,7 +77,7 @@
     //  This is a "magic" number signifying what we want to see
     //
     
-    desired_database_version = "1005";
+    desired_database_version = "1006";
 
     //
     //  Initialize our container and set things up for a clean slate
@@ -526,7 +526,7 @@
     
     MSqlQuery query(MSqlQuery::InitCon());
     
-    query.exec("SELECT intid, filename FROM musicmetadata ;");
+    query.exec("SELECT song_id, filename FROM music_songs ;");
     
     if(query.isActive())
     {
@@ -544,7 +544,7 @@
 
                     ++count;
                     MSqlQuery delete_query(MSqlQuery::InitCon());
-                    delete_query.prepare("DELETE FROM musicmetadata WHERE intid = ?");
+                    delete_query.prepare("DELETE FROM music_songs WHERE song_id = ?");
                     delete_query.bindValue(0, query.value(0).toUInt());
                     delete_query.exec();
                     log(QString("removed item %1 (\"%2\") from the database")
@@ -556,7 +556,7 @@
     }
     else
     {
-        warning("something wrong with your musicmetadata table");
+        warning("something wrong with your music_songs table");
     }
     
     if(count > 0)
@@ -638,26 +638,26 @@
     
     MSqlQuery query(MSqlQuery::InitCon());
     
-    query.exec("SELECT COUNT(filename) FROM musicmetadata;");
+    query.exec("SELECT COUNT(filename) FROM music_songs;");
     
     if(!query.isActive())
     {
         if(!sent_musicmetadata_table_warning)
         {
-            warning("cannot get data from a table called musicmetadata");
+            warning("cannot get data from a table called music_songs");
             sent_musicmetadata_table_warning = true;
         }
         return false;
         
     }
     
-    query.exec("SELECT COUNT(playlistid) FROM musicplaylist ");
+    query.exec("SELECT COUNT(playlist_id) FROM music_saved_playlists ");
 
     if(!query.isActive())
     {
         if(!sent_playlist_table_warning)
         {
-            warning("cannot get data from a table called musisplaylist");
+            warning("cannot get data from a table called music_saved_playlists");
             sent_playlist_table_warning = true;
         }
         return false;
@@ -977,17 +977,30 @@
 
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("SELECT intid, artist, album, title, genre, "
-                  "year, tracknum, length, rating, "
-                  "lastplay, playcount, mythdigest, size, date_added, "
-                  "date_modified, format, description, comment, "
-                  "compilation, composer, disc_count, disc_number, "
-                  "track_count, start_time, stop_time, eq_preset, "
-                  "relative_volume, sample_rate, bpm "
-                  "FROM musicmetadata WHERE filename = ? ;");
+    query.prepare("SELECT music_songs.song_id, music_artists.artist_name, "
+		  "music_albums.album_name, music_songs.name, "
+		  "music_genres.genre, music_songs.year, "
+		  "music_songs.track, music_songs.length, "
+		  "music_songs.rating, music_songs.lastplay, "
+		  "music_songs.numplays, music_songs.mythdigest,"
+		  "music_songs.size, music_songs.date_entered, "
+		  "music_songs.date_modified, music_songs.format, "
+		  "music_songs.description, music_songs.comment, "
+		  "music_songs.compilation, music_comp_artists.artist_name AS composer, "
+		  "music_songs.disc_count, music_songs.disc_number, "
+		  "music_songs.track_count, music_songs.start_time, "
+		  "music_songs.stop_time, music_songs.eq_preset, "
+		  "music_songs.relative_volume, music_songs.bitrate, "
+		  "music_songs.bpm "
+		  "FROM music_songs "
+		  "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id " 
+		  "LEFT JOIN music_artists AS music_comp_artists ON music_songs.compilationartist_id=music_comp_artists.artist_id " 
+		  "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id " 
+		  "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id " 
+		  "WHERE filename = ? ;");
 
     query.bindValue(0, sqlfilename.utf8());
-    
+
     query.exec();
 
     if (query.isActive())
@@ -1198,7 +1211,7 @@
         
         MSqlQuery query(MSqlQuery::InitCon());
 
-        query.prepare("INSERT INTO musicmetadata (filename, mythdigest) "
+        query.prepare("INSERT INTO music_songs(filename, mythdigest) "
                       "values ( ? , ?)");
 
         query.bindValue(0, sqlfilename.utf8());
@@ -1213,7 +1226,7 @@
             return NULL;
         }
         
-        query.prepare("SELECT intid FROM musicmetadata "
+        query.prepare("SELECT song_id FROM music_songs "
                                "WHERE mythdigest = ? ;");
         query.bindValue(0, new_item->getMythDigest());
         query.exec();
@@ -1322,26 +1335,140 @@
 
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("UPDATE musicmetadata SET "
-                  "title = ? , "
-                  "artist = ? , "
-                  "album = ? , "
-                  "genre = ? , "
+
+//Genrecheck
+//Albumcheck
+//Artist
+    int ArtistID;
+    query.prepare("SELECT music_artists.artist_id FROM music_artists "
+                  " WHERE (((music_artists.artist_name)=:ARTIST));");
+    query.bindValue(":ARTIST", an_item->getArtist().utf8());
+    query.exec();
+//    cout << query.executedQuery() << endl;
+    if (query.size() > 0)
+	{
+	query.next();
+        ArtistID = query.value(0).toInt();
+	}
+    else
+	{
+	query.prepare("INSERT INTO music_artists (artist_name) VALUES (:ARTIST);");
+	query.bindValue(":ARTIST", an_item->getArtist().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+	query.prepare("SELECT music_artists.artist_id FROM music_artists "
+                  " WHERE (((music_artists.artist_name)=:ARTIST));");
+	query.bindValue(":ARTIST", an_item->getArtist().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+	query.next();
+        ArtistID = query.value(0).toInt();	
+	}
+
+//Compilation Artist	
+    int CoArtistID;
+    query.prepare("SELECT music_artists.artist_id FROM music_artists "
+                  " WHERE (((music_artists.artist_name)=:ARTIST));");
+    query.bindValue(":ARTIST", an_item->getComposer().utf8());
+    query.exec();
+//    cout << query.executedQuery() << endl;
+    if (query.size() > 0)
+	{
+	query.next();
+        CoArtistID = query.value(0).toInt();
+	}
+    else
+	{
+	query.prepare("INSERT INTO music_artists (artist_name) VALUES (:ARTIST);");
+	query.bindValue(":ARTIST", an_item->getComposer().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+	query.prepare("SELECT music_artists.artist_id FROM music_artists "
+                  " WHERE (((music_artists.artist_name)=:ARTIST));");
+	query.bindValue(":ARTIST", an_item->getComposer().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+	query.next();
+        CoArtistID = query.value(0).toInt();	
+	}
+
+//Album
+    int AlbumID;
+    query.prepare("SELECT music_albums.album_id FROM music_albums "
+                  " WHERE (((music_albums.album_name)=:ALBUM));");
+    query.bindValue(":ALBUM", an_item->getAlbum().utf8());
+    query.exec();
+//    cout << query.executedQuery() << endl;
+    if (query.size() > 0)
+	{
+	query.next();
+        AlbumID = query.value(0).toInt();
+	}
+    else
+	{
+	query.prepare("INSERT INTO music_albums (album_name) VALUES (:ALBUM);");
+	query.bindValue(":ALBUM", an_item->getAlbum().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+        
+	query.prepare("SELECT music_albums.album_id FROM music_albums "
+                  " WHERE (((music_albums.album_name)=:ALBUM));");
+	query.bindValue(":ALBUM", an_item->getAlbum().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+	query.next();
+
+        AlbumID = query.value(0).toInt();	
+	}
+
+//Genres
+    int GenreID;
+    query.prepare("SELECT music_genres.genre_id FROM music_genres "
+                  " WHERE (((music_genres.genre)=:GENRE));");
+    query.bindValue(":GENRE", an_item->getGenre().utf8());
+    query.exec();
+//    cout << query.executedQuery() << endl;
+    if (query.size() > 0)
+	{
+	query.next();
+        GenreID = query.value(0).toInt();
+	}
+    else
+	{
+	query.prepare("INSERT INTO music_genres (genre) VALUES (:GENRE);");
+	query.bindValue(":GENRE", an_item->getGenre().utf8());
+	query.exec();
+//        cout << query.executedQuery() << endl;
+        
+        query.prepare("SELECT music_genres.genre_id FROM music_genres "
+                  " WHERE (((music_genres.genre)=:GENRE));");
+	query.bindValue(":GENRE", an_item->getGenre().utf8());
+	query.exec();
+//	cout << query.executedQuery() << endl;
+	query.next();
+        GenreID = query.value(0).toInt();	
+	}
+
+    query.prepare("UPDATE music_songs SET "
+                  "name = ? , "
+                  "artist_id = ? , "
+                  "album_id = ? , "
+                  "genre_id = ? , "
                   "year = ? , "
-                  "tracknum = ? , "
+                  "track = ? , "
                   "length = ? , "
                   "rating = ? , "
                   "lastplay = ? , "
-                  "playcount = ? , "
+                  "numplays = ? , "
                   "mythdigest = ? , "
                   "size = ? , "
-                  "date_added = ? , "
+                  "date_entered = ? , "
                   "date_modified = ? , "
                   "format = ? , "
                   "description = ? , "
                   "comment = ? , "
                   "compilation = ? , "
-                  "composer = ? , "
+                  "compilationartist_id = ? , "
                   "disc_count = ? , "
                   "disc_number = ? , "
                   "track_count = ? , "
@@ -1349,14 +1476,14 @@
                   "stop_time = ? , "
                   "eq_preset = ? , "
                   "relative_volume = ? , "
-                  "sample_rate = ? , "
+                  "bitrate = ? , "
                   "bpm = ?  "
-                  "WHERE intid = ? ;");
+                  "WHERE song_id = ? ;");
 
     query.bindValue(0,  an_item->getTitle().utf8());
-    query.bindValue(1,  an_item->getArtist().utf8());
-    query.bindValue(2,  an_item->getAlbum().utf8());
-    query.bindValue(3,  an_item->getGenre().utf8());
+    query.bindValue(1,  ArtistID);
+    query.bindValue(2,  AlbumID);
+    query.bindValue(3,  GenreID);
     query.bindValue(4,  an_item->getYear());
     query.bindValue(5,  an_item->getTrack());
     query.bindValue(6,  an_item->getLength());
@@ -1371,7 +1498,7 @@
     query.bindValue(15, an_item->getDescription().utf8());
     query.bindValue(16, an_item->getComment().utf8());
     query.bindValue(17, an_item->getCompilation());
-    query.bindValue(18, an_item->getComposer().utf8());
+    query.bindValue(18, CoArtistID);
     query.bindValue(19, an_item->getDiscCount());
     query.bindValue(20, an_item->getDiscNumber());
     query.bindValue(21, an_item->getTrackCount());
@@ -1467,14 +1594,12 @@
 
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("SELECT name, songlist, playlistid FROM musicplaylist "
-                  "WHERE name != ? "
-                  "AND name != ? "
-                  "AND hostname = ? ;");
+    query.prepare("SELECT playlist_name, playlist_songs, playlist_id FROM music_saved_playlists "
+                  "WHERE playlist_name != ? "
+                  "AND playlist_name != ? ;");
         
     query.bindValue(0, "backup_playlist_storage");
     query.bindValue(1, "default_playlist_storage");
-    query.bindValue(2, hostname);
         
     query.exec();
 
@@ -1617,12 +1742,31 @@
     
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("UPDATE musicplaylist SET songlist = ?, name = ? WHERE "
-                  "playlistid = ? ;");
+    int songcount = 0, playtime = 0, an_int;
+    QStringList list = QStringList::split(",", db_song_list_string);
+    QStringList::iterator it = list.begin();
+    for (; it != list.end(); it++)
+    {
+        an_int = QString(*it).toInt();
+        if (an_int != 0)
+        {
+	    songcount++;
+	    query.prepare("SELECT length FROM music_songs WHERE song_id = :ID ;");
+    	    query.bindValue(":ID", an_int);
+    	    query.exec();
+	    query.next();
+	    playtime += query.value(0).toInt();
+	}
+    }
 
+    query.prepare("UPDATE music_saved_playlists SET playlist_songs = ?, playlist_name = ? WHERE "
+                  "playlist_id = ?, songcount = ?, time = ? ;");
+
     query.bindValue(0, db_song_list_string);
     query.bindValue(1, a_playlist->getName().utf8());
     query.bindValue(2, a_playlist->getDbId());
+    query.bindValue(3, songcount);
+    query.bindValue(4, playtime);
         
     query.exec();
     
@@ -1665,11 +1809,30 @@
     
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("INSERT INTO musicplaylist (name, hostname, songlist) values (?, ?, ?) ; ");
+    int songcount = 0, playtime = 0, an_int;
+    QStringList list = QStringList::split(",", db_song_list_string);
+    QStringList::iterator it = list.begin();
+    for (; it != list.end(); it++)
+    {
+        an_int = QString(*it).toInt();
+        if (an_int != 0)
+        {
+	    songcount++;
+	    query.prepare("SELECT length FROM music_songs WHERE song_id = :ID ;");
+    	    query.bindValue(":ID", an_int);
+    	    query.exec();
+	    query.next();
+	    playtime += query.value(0).toInt();
+	}
+    }
 
+    query.prepare("INSERT INTO music_saved_playlists (playlist_name, hostname, playlist_songs, songcount, time) values (?, ?, ?, ?, ?) ; ");
+
     query.bindValue(0, a_playlist->getName().utf8());
     query.bindValue(1, hostname);
     query.bindValue(2, db_song_list_string);
+    query.bindValue(3, songcount);
+    query.bindValue(4, playtime);
         
     query.exec();
     
@@ -1681,11 +1844,20 @@
         return;
     }
     
-    query.prepare("SELECT playlistid FROM musicplaylist WHERE name = ? AND hostname = ? AND songlist = ? ; ");
+    if (a_playlist->getName() == "default_playlist_storage" || a_playlist->getName() == "backup_playlist_storage")
+	{
+	query.prepare("SELECT playlist_id FROM music_saved_playlists WHERE playlist_name = ? AND hostname = ? AND playlist_songs = ? ; ");
+	query.bindValue(0, a_playlist->getName().utf8());
+	query.bindValue(1, hostname);
+	query.bindValue(2, db_song_list_string);
+	}
+    else
+	{
+	query.prepare("SELECT playlist_id FROM music_saved_playlists WHERE playlist_name = ? AND playlist_songs = ? ; ");
+	query.bindValue(0, a_playlist->getName().utf8());
+	query.bindValue(1, db_song_list_string);
+	}
 
-    query.bindValue(0, a_playlist->getName().utf8());
-    query.bindValue(1, hostname);
-    query.bindValue(2, db_song_list_string);
 
     query.exec();
 
@@ -1776,7 +1948,7 @@
 
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("DELETE FROM musicplaylist WHERE playlistid = ? ; ");
+    query.prepare("DELETE FROM music_saved_playlists WHERE playlist_id = ? ; ");
 
     query.bindValue(0, playlist_database_id);
         
Index: mfd/dbcheck.cpp
===================================================================
--- mfd/dbcheck.cpp	(revision 10565)
+++ mfd/dbcheck.cpp	(working copy)
@@ -9,7 +9,7 @@
 #include "mythtv/mythcontext.h"
 #include "mythtv/mythdbcon.h"
 
-const QString currentDatabaseVersion = "1005";
+const QString currentDatabaseVersion = "1006";
 
 static void UpdateDBVersionNumber(const QString &newnumber)
 {
@@ -323,5 +323,121 @@
 
         performActualUpdate(updates, "1005", dbver);
     }
+
+
+        if (dbver == "1005")
+        {
+            const QString updates[] = {
+"CREATE TABLE music_albums ("
+"    album_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
+"    artist_id int(11) unsigned NOT NULL default '0',"
+"    album_name varchar(255) NOT NULL default '',"
+"    year smallint(6) NOT NULL default '0',"
+"    compilation tinyint(1) unsigned NOT NULL default '0',"
+"    INDEX idx_album_name(album_name)"
+");",
+"CREATE TABLE music_artists ("
+"    artist_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
+"    artist_name varchar(255) NOT NULL default '',"
+"    INDEX idx_artist_name(artist_name)"
+");",
+"CREATE TABLE music_genres ("
+"    genre_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
+"    genre varchar(25) NOT NULL default '',"
+"    INDEX idx_genre(genre)"
+");",
+"CREATE TABLE music_playlists ("
+"    playlist_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
+"    playlist_name varchar(255) NOT NULL default '',"
+"    playlist_songs text NOT NULL default '',"
+"    last_accessed timestamp NOT NULL,"
+"    length int(11) unsigned NOT NULL default '0',"
+"    songcount smallint(8) unsigned NOT NULL default '0',"
+"    hostname VARCHAR(255) NOT NULL default ''"
+");",
+"CREATE TABLE music_songs ("
+"    song_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
+"    filename text NOT NULL default '',"
+"    name varchar(255) NOT NULL default '',"
+"    track smallint(6) unsigned NOT NULL default '0',"
+"    artist_id int(11) unsigned NOT NULL default '0',"
+"    album_id int(11) unsigned NOT NULL default '0',"
+"    genre_id int(11) unsigned NOT NULL default '0',"
+"    year smallint(6) NOT NULL default '0',"
+"    length int(11) unsigned NOT NULL default '0',"
+"    numplays int(11) unsigned NOT NULL default '0',"
+"    rating tinyint(4) unsigned NOT NULL default '0',"
+"    lastplay timestamp NOT NULL,"
+"    date_entered datetime default NULL,"
+"    date_modified datetime default NULL,"
+"    format varchar(4) NOT NULL default '0',"
+"    mythdigest VARCHAR(255),"
+"    size BIGINT(20) unsigned,"
+"    description VARCHAR(255),"
+"    comment VARCHAR(255),"
+"    disc_count SMALLINT(5) UNSIGNED DEFAULT '0',"
+"    disc_number SMALLINT(5) UNSIGNED DEFAULT '0',"
+"    track_count SMALLINT(5) UNSIGNED DEFAULT '0',"
+"    start_time INT(10) UNSIGNED DEFAULT '0',"
+"    stop_time INT(10) UNSIGNED,"
+"    eq_preset VARCHAR(255),"
+"    relative_volume TINYINT DEFAULT '0',"
+"    bpm SMALLINT(5) UNSIGNED,"
+"    INDEX idx_name(name),"
+"    INDEX idx_mythdigest(mythdigest)"
+");",
+"CREATE TABLE music_stats ("
+"    num_artists smallint(5) unsigned NOT NULL default '0',"
+"    num_albums smallint(5) unsigned NOT NULL default '0',"
+"    num_songs mediumint(8) unsigned NOT NULL default '0',"
+"    num_genres tinyint(3) unsigned NOT NULL default '0',"
+"    total_time varchar(12) NOT NULL default '0',"
+"    total_size varchar(10) NOT NULL default '0'"
+");",
+"RENAME TABLE smartplaylist TO music_smartplaylists;",
+"RENAME TABLE smartplaylistitem TO music_smartplaylist_items;",
+"RENAME TABLE smartplaylistcategory TO music_smartplaylist_categories;",
+// Run necessary SQL to migrate the table structure
+"CREATE TEMPORARY TABLE tmp_artists"
+"  SELECT DISTINCT artist FROM musicmetadata;",
+"INSERT INTO tmp_artists"
+"  SELECT DISTINCT compilation_artist"
+"  FROM musicmetadata"
+"  WHERE compilation_artist<>artist;",
+"INSERT INTO music_artists (artist_name) SELECT DISTINCT artist FROM tmp_artists;",
+"INSERT INTO music_albums (artist_id, album_name, year, compilation) "
+"  SELECT artist_id, album, ROUND(AVG(year)) AS year, IF(SUM(compilation),1,0) AS compilation"
+"  FROM musicmetadata"
+"  LEFT JOIN music_artists ON compilation_artist=artist_name"
+"  GROUP BY artist_id, album;",
+"INSERT INTO music_genres (genre) SELECT DISTINCT genre FROM musicmetadata;",
+"INSERT INTO music_songs "
+"   (song_id, artist_id, album_id, genre_id, year, lastplay,"
+"    date_entered, date_modified, name, track, length, size, numplays,"
+"    rating, filename)"
+"  SELECT intid, ma.artist_id, mb.album_id, mg.genre_id, mmd.year, lastplay,"
+"         date_added, date_modified, title, tracknum, length, IFNULL(size,0), playcount,"
+"         rating, filename"
+"  FROM musicmetadata AS mmd"
+"  LEFT JOIN music_artists AS ma ON mmd.artist=ma.artist_name"
+"  LEFT JOIN music_artists AS mc ON mmd.compilation_artist=mc.artist_name"
+"  LEFT JOIN music_albums AS mb ON mmd.album=mb.album_name AND mc.artist_id=mb.artist_id"
+"  LEFT JOIN music_genres AS mg ON mmd.genre=mg.genre;",
+"INSERT INTO music_playlists"
+"  (playlist_id,playlist_name,playlist_songs,hostname)"
+"  SELECT playlistid, name, songlist, hostname"
+"  FROM musicplaylist;",
+// Set all playlists to be global by killing the hostname
+"UPDATE music_playlists"
+"  SET hostname=''"
+"  WHERE playlist_name='default_playlist_storage'"
+"    OR playlist_name='backup_playlist_storage';",
+//"DROP TABLE musicmetadata;",
+//"DROP TABLE musicplaylist;",
+//RENAME TABLE music_smartplaylists TO smartplaylist;RENAME TABLE music_smartplaylist_categories TO smartplaylistcategory;RENAME TABLE music_smartplaylist_items TO smartplaylistitem; DROP TABLE music_albums; DROP TABLE music_artists; DROP TABLE music_genres; DROP TABLE music_playlists; DROP TABLE music_songs; DROP TABLE music_stats;UPDATE settings SET data=1005 WHERE value='MusicDBSchemaVer';
+""
+};
+        performActualUpdate(updates, "1006", dbver);
+    }
 }
 

