Changeset 109

Show
Ignore:
Timestamp:
03/03/07 11:15:16 (2 years ago)
Author:
tulloss2
Message:

More small server updates, improved performance, proper update handling.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • dmp/trunk/client/linux-settop-gui/linux-settop-gui.csproj

    r97 r109  
    5252    <Reference Include="System.Xml" /> 
    5353  </ItemGroup> 
     54  <ItemGroup> 
     55    <Folder Include="Properties\" /> 
     56  </ItemGroup> 
    5457</Project> 
  • dmp/trunk/client/linux-settop-gui/topwindow.cs

    r97 r109  
    1010    { 
    1111        private Window newWin; 
     12        const int TOPFRAME_HEIGHT=85; 
     13 
    1214        //Initialize view and store 
    1315        TreeStore songTree = new TreeStore(typeof(string), typeof(string), typeof(string), typeof(int)); 
     
    1517        TreeView songView; 
    1618        TreeView serverView; 
     19 
     20        /********* The many components we need to display and manipulate******/ 
     21        //Setup icons for buttons 
     22        Image playIcon = new Image("./icons/media-playback-start.png"); 
     23 
     24        //Create playback buttons 
     25        ToolButton playButton; 
     26 
     27        //Initialize all our etc. containers 
     28        Toolbar controlButtons = new Toolbar(); 
     29        HPaned playerH = new HPaned(); 
     30        VBox playerV = new VBox(false, 6); 
     31        Layout mainLayout = new Layout(null, null); 
     32        Layout topLayout = new Layout(null, null); 
     33 
     34        //Initialize containers for song info area 
     35        Fixed songInfo = new Fixed(); 
     36        HScale songPos = new HScale(null); 
     37        RcStyle resFile = new RcStyle(); 
     38        /****************End Component creation ******************************/ 
     39 
    1740 
    1841        public static void Main() 
     
    2750            Application.Init(); 
    2851 
    29             //Setup containers for all our crap 
    30             Button playButton = new Button(); 
    31             Button prevButton = new Button(); 
    32             Button nextButton = new Button(); 
     52            resFile. 
    3353 
    34             HButtonBox controlButtons = new HButtonBox(); 
    35             HPaned playerH = new HPaned(); 
    36             VBox playerV = new VBox(); 
    37             Layout songLayout= new Layout(new Adjustment(50,0,500,5,50,100),new Adjustment(0,0,50000,5,50,100)); 
     54            newWin = new Window("Rubicon Music Player"); 
    3855 
    39             newWin = new Window("Hi"); 
     56            //Initialize toolbar buttons 
     57            playButton = new ToolButton(playIcon, "Play"); 
     58            
     59            newWin = new Window("Rubicon Music Player"); 
    4060 
    4161            newWin.Decorated = false; 
    4262            newWin.Fullscreen(); 
    43             newWin.Add(playerV); 
     63            newWin.Add(mainLayout); 
     64 
     65            //For some reason you need to call ShowAll before the height 
     66            //and width are properly updated 
     67            newWin.ShowAll(); 
     68            int winHeight, winWidth; 
     69            newWin.GetSize(out winWidth, out winHeight); 
    4470 
    4571            songView = new TreeView(songTree); 
    4672            serverView = new TreeView(serverList); 
    4773 
     74            //////Inside music info frame///////// 
     75            songInfo.SetSizeRequest(300, 60); 
     76            songInfo.Put(songPos, 30, 40); 
     77            songInfo.Realized += new EventHandler(songInfo_Realized); 
     78 
     79 
     80            ///////////////////////////////////// 
     81 
    4882            //Layout main window 
    4983            playerH.Add(serverView); 
    5084            playerH.Add(songView); 
    51             playerV.Add(controlButtons); 
    52             playerV.Add(playerH); 
    5385 
    54             //Insert control buttons 
    55             controlButtons.Add(prevButton); 
    56             controlButtons.Add(playButton); 
    57             controlButtons.Add(nextButton); 
     86            //Put the top frame and the paned horizontal thing in the right place 
     87            mainLayout.Put(topLayout, 0, 0); 
     88            mainLayout.Put(playerH, 0, TOPFRAME_HEIGHT); 
     89            
     90            //layout toolbar 
     91            controlButtons.Insert(playButton, 0); 
     92 
     93            //Layout top frame 
     94            topLayout.Put(controlButtons, 0, 0); 
     95            topLayout.Put(songInfo, winWidth / 2, 30); 
     96 
     97            playerH.SetSizeRequest(winWidth, winHeight - TOPFRAME_HEIGHT); 
     98            topLayout.SetSizeRequest(winWidth, TOPFRAME_HEIGHT); 
     99 
     100            //configure toolbar 
     101            controlButtons.IconSize = IconSize.LargeToolbar; 
     102            controlButtons.ToolbarStyle = ToolbarStyle.Icons; 
     103            controlButtons.SetSizeRequest(winWidth/4, TOPFRAME_HEIGHT); 
     104 
     105            //Layout song display panes 
     106            playerH.Position = winWidth / 7; 
    58107 
    59108            //set up server list 
     
    92141            songView.RulesHint = true; 
    93142 
    94             songLayout.Add(songView); 
    95  
    96143            newWin.ShowAll(); 
    97144 
    98145            Application.Run(); 
    99146        } 
     147 
     148        void songInfo_Realized(object o, EventArgs events) 
     149        { 
     150            //Fixed songInfo = (Fixed)o; 
     151 
     152            Gdk.Pixbuf playBuf = new Gdk.Pixbuf("./icons/media-playback-start.png"); 
     153            Gdk.Pixmap playMap, playMask; 
     154            playBuf.RenderPixmapAndMask(out playMap, out playMask, 255); 
     155 
     156            songInfo.Put(new Label("hey there"), 0, 0); 
     157            songInfo.AppPaintable = true; 
     158            songInfo.Style.SetBgPixmap(StateType.Normal, playMap); 
     159        } 
     160             
    100161    } 
    101162} 
  • dmp/trunk/daap-sharp/Server.cs

    r87 r109  
    273273                    try { 
    274274                        string path = splitRequest[1]; 
    275                         using (StreamWriter sw = new StreamWriter("logFile.txt")) 
    276                         { 
    277                             sw.WriteLine("Path: {0}", path); 
    278                         } 
     275                                                Console.WriteLine("Path: {0}", path); 
    279276                        if (!path.StartsWith ("daap://")) { 
    280277                            path = String.Format ("daap://localhost{0}", path); 
  • dmp/trunk/server/dataserver/metadata.cs

    r102 r109  
    1919namespace DMP.Server 
    2020{ 
    21     [XmlRpcExposed] 
    22     public class Metadata 
    23     { 
    24         //Delegates for communicating with the GUI 
    25         public delegate void UpdateProgressBar(); 
    26         public delegate void UpdateProgressTitle(string newTitle); 
    27         public delegate void SetProgressMax(int max); 
    28         public delegate void ResetProgressBar(); 
    29  
    30         //Instances of above delegates 
    31         public static UpdateProgressTitle progressTitle; 
    32         public static UpdateProgressBar progressUpdate; 
    33         public static ResetProgressBar progressReset; 
    34         public static SetProgressMax progressMax; 
    35  
    36         private IDbConnection dbCon; 
    37         //The current revision that the database is at 
    38         private static int revision; 
    39         private static Object revLock = new Object(); 
    40  
    41         /// <summary> 
    42         /// Default Constructor, creates db in current directory 
    43         /// </summary> 
    44         public Metadata() : this(System.IO.Directory.GetCurrentDirectory()+"/serverdb.db3") 
    45         { } 
    46  
    47         //Default Constructor 
    48         //TODO: 
    49         // -Fail on bad path 
    50         public Metadata(string path) 
    51         { 
    52             InitializeDb(path); 
    53             revision = this.LatestRevision; 
    54         } 
    55  
    56         /// <summary> 
    57         /// Takes as an argument the SQLite database file to use for this server 
    58         /// instance, checks whether it's there and creates it if not 
    59         /// </summary> 
    60         public bool InitializeDb(string path) 
    61         { 
    62             path = EscapePath(path); 
    63  
    64             if (path == null) 
    65                 return false; 
    66  
    67             string directory = System.IO.Path.GetDirectoryName(path); 
    68             if (!System.IO.Directory.Exists(directory)) 
    69                 return false; 
    70  
    71  
    72 #if MONO 
    73             string connection = "URI=file:" + path; 
    74             dbCon = (IDbConnection)new SqliteConnection(connection); 
    75 #else 
    76             string connection = "Data Source=" + path; 
    77             dbCon = (IDbConnection)new SQLiteConnection(connection); 
    78 #endif 
    79  
    80             if (System.IO.File.Exists(path)) 
    81             { 
    82                 //TODO: Should validate database here, perhaps on a version number 
    83                 InitSQLCommands(); 
    84                 return true; 
    85             } 
    86  
    87             return CreateDb(); 
    88         } 
    89  
    90         /// <summary> 
    91         /// This function creates a new database at the given path 
    92         /// </summary> 
    93         /// <returns>Success or failure</returns> 
    94         private bool CreateDb() 
    95         { 
    96             if (dbCon == null) 
    97                 return false; 
    98  
    99             IDbCommand dbcmd = dbCon.CreateCommand(); 
    100  
    101             dbcmd.CommandText = @"CREATE TABLE songs ( 
     21        [XmlRpcExposed] 
     22        public class Metadata 
     23        { 
     24                const int DEFAULT_PORT = 3689; 
     25                const string DEFAULT_NAME = "DMPDBSTYLE"; 
     26                //All the queries we could ever want to define 
     27 
     28                /****Settings queries*****/ 
     29                const string FIND_SERVER_NAME =  
     30                        "SELECT value FROM settings WHERE key=\"servername\""; 
     31                const string UPDATE_SERVER_NAME =  
     32                        "UPDATE settings SET value=? WHERE key=\"servername\""; 
     33                const string INSERT_SERVER_NAME = 
     34                        "INSERT INTO settings values(\"servername\",?)"; 
     35                const string FIND_SERVER_PORT = 
     36                        "SELECT value FROM settings WHERE key=\"serverport\""; 
     37                const string UPDATE_SERVER_PORT = 
     38                        "UPDATE settings SET value=? WHERE key=\"serverport\""; 
     39                const string INSERT_SERVER_PORT = 
     40                        "INSERT INTO settings values(\"serverport\",?)"; 
     41                /*****End settings queries *****/ 
     42 
     43                /*****Creation querie *****/ 
     44                const string CREATE_DB = @"CREATE TABLE songs ( 
    10245                        id INTEGER PRIMARY KEY AUTOINCREMENT, 
    10346                        path TEXT, 
    10447                        artist TEXT, 
    105             album TEXT, 
    106             title TEXT, 
    107             year INTEGER, 
    108             format TEXT, 
    109             duration TIME, 
    110             genre TEXT, 
    111             tracknumber INTEGER, 
    112             trackcount INTEGER, 
    113             size INTEGER, 
     48                       album TEXT, 
     49                       title TEXT, 
     50                       year INTEGER, 
     51                       format TEXT, 
     52                       duration TIME, 
     53                       genre TEXT, 
     54                       tracknumber INTEGER, 
     55                       trackcount INTEGER, 
     56                       size INTEGER, 
    11457                        updated INTEGER, 
    115             fileLastModified DATETIME, 
    116             dbLastModified UNSIGNED INTEGER, 
    117             deleted TINYINT 
     58                       fileLastModified DATETIME, 
     59                       dbLastModified UNSIGNED INTEGER, 
     60                       deleted TINYINT 
    11861                        );  
    119             CREATE INDEX rev_idx on songs(dbLastModified); 
    120             CREATE TABLE playlists ( 
    121             id INTEGER, 
    122             songid INTEGER); 
    123             CREATE INDEX pl_idx ON playlists(id); 
    124             CREATE TABLE directories (path TEXT);"; 
    125  
    126             dbCon.Open(); 
    127             dbcmd.ExecuteNonQuery(); 
    128  
    129             dbCon.Close(); 
    130  
    131             InitSQLCommands(); 
    132  
    133             return true; 
    134         } 
    135  
    136         /// <summary> 
    137         /// Returns true if directory successfully added or is already monitored, 
    138         /// false if unable or directory doesn't exist 
    139         /// </summary> 
    140         /// <remarks> 
    141         /// 070117::JMT - Altered this to return Error ErrorStruct (for RPC) 
    142         /// </remarks> 
    143         /// <param name="path">Directory to add</param> 
    144         /// <returns>Success or failure</returns> 
    145         public Error AddDirectory(string path) 
    146         { 
    147             if (dbCon == null) 
    148             { 
    149                 Error noConn = new Error("Database Connection does not exist"); 
    150                 return noConn; 
    151             } 
    152  
    153             path = EscapePath(path); 
    154  
    155             if (path == null) 
    156             { 
    157                 Error noPath = new Error("Must pass non-null file path"); 
    158                 return noPath; 
    159             } 
    160  
    161             if (!System.IO.Directory.Exists(path)) 
    162             { 
    163                 Error badPath = new Error("Directory does not exist"); 
    164                 return badPath; 
    165             } 
    166  
    167             dbCon.Open(); 
    168             IDbCommand dbCmd = dbCon.CreateCommand(); 
    169  
    170             dbCmd.CommandText = "SELECT COUNT(*) FROM directories WHERE path=?"; 
    171             IDataParameter pPath = dbCmd.CreateParameter(); 
    172             dbCmd.Parameters.Add(pPath); 
    173             pPath.Value = path; 
    174  
    175             IDataReader reader = dbCmd.ExecuteReader(); 
    176             reader.Read(); 
    177  
    178             int count = reader.GetInt32(0); 
    179             reader.Close(); 
    180  
    181             if (count > 0) 
    182             { 
    183                 dbCmd.Dispose(); 
    184                 dbCon.Close(); 
    185                 return null; 
    186             } 
    187  
    188             dbCmd.CommandText = "INSERT INTO directories('path') VALUES(?)"; 
    189             pPath = dbCmd.CreateParameter(); 
    190             dbCmd.Parameters.Add(pPath); 
    191             pPath.Value = path; 
    192             dbCmd.ExecuteNonQuery(); 
    193  
    194             //dbCmd.Dispose(); 
    195             dbCon.Close(); 
    196  
    197             return null; 
    198         } 
    199  
    200         /// <summary> 
    201         /// Returns true if directory was successfully removed, false otherwise 
    202         /// </summary> 
    203         /// <remarks> 
    204         /// 070117::JMT - Altered this to return Error ErrorStruct (for RPC) 
    205         /// </remarks> 
    206         /// <param name="path">Path of directory to remove</param> 
    207         /// <returns>Success or failure errorstruct</returns> 
    208         [XmlRpcExposed] 
    209         public Hashtable RemoveDirectory(string path) 
    210         { 
    211             if (dbCon == null) 
    212             { 
    213                 Error noDb = new Error("Database has not been initialized"); 
    214                 return noDb.Structure; 
    215             } 
    216             path = EscapePath(path); 
    217  
    218             if (path == null) 
    219             { 
    220                 Error noPath = new Error("Must pass non-null file path"); 
    221                 return noPath.Structure; 
    222             } 
    223  
    224             IDbCommand dbCmd = dbCon.CreateCommand(); 
    225             dbCmd.CommandText = "DELETE FROM directories WHERE path=?"; 
    226             IDataParameter pPath = dbCmd.CreateParameter(); 
    227             dbCmd.Parameters.Add(pPath); 
    228             pPath.Value = path; 
    229  
    230             dbCon.Open(); 
    231             int rowsAffected = dbCmd.ExecuteNonQuery(); 
    232             dbCon.Close(); 
    233  
    234             dbCmd.Dispose(); 
    235  
    236             if (rowsAffected != 0) 
    237                 return null; 
    238             else 
    239             { 
    240                 Error delFailed = new Error("Delete Failed"); 
    241                 return delFailed.Structure; 
    242             } 
    243         } 
    244  
    245         /// <summary> 
    246         /// This returns a list of strings representing all monitored directories 
    247         /// </summary> 
    248         [XmlRpcExposed] 
    249         public ArrayList ListDirectories() 
    250         { 
    251             if (dbCon == null) 
    252                 return null; 
    253  
    254             IDbCommand dbCmd = dbCon.CreateCommand(); 
    255  
    256             dbCmd.CommandText = "SELECT COUNT(*) FROM directories"; 
    257             dbCon.Open(); 
    258             IDataReader reader = dbCmd.ExecuteReader(); 
    259  
    260             reader.Read(); 
    261             int count = reader.GetInt32(0); 
    262             reader.Close(); 
    263  
    264             ArrayList returnVal = new ArrayList(count); 
    265  
    266             dbCmd.CommandText = "SELECT path FROM directories"; 
    267             reader = dbCmd.ExecuteReader(); 
    268  
    269             for (int i = 0; i < count; i++) 
    270             { 
    271                 reader.Read(); 
    272                 returnVal.Add(reader.GetString(0)); 
    273             } 
    274  
    275             dbCon.Close(); 
    276             reader.Close(); 
    277             //dbCmd.Dispose(); 
    278  
    279             return returnVal; 
    280         } 
    281  
    282         /// <summary> 
    283         /// Takes each of the directories in the directories table and updates the 
    284         /// songs in those directories 
    285         /// </summary> 
    286         /// <remarks> 
    287         /// 070117::JMT - Altered this to return Error ErrorStruct (for RPC) 
    288         /// </remarks> 
    289         /// <returns></returns> 
    290         public Error UpdateMusic() 
    291         { 
    292             if (dbCon == null) 
    293             { 
    294                 Error noDb = new Error("Database has not been initialized"); 
    295                 return noDb; 
    296             } 
    297  
    298             ArrayList directories = ListDirectories(); 
    299  
    300             dbCon.Open(); 
    301             IDbTransaction dbTrans = dbCon.BeginTransaction(); 
    302  
    303             IDbCommand markUpdated = dbCon.CreateCommand(); 
    304             markUpdated.CommandText = "UPDATE songs SET Updated=0; DELETE FROM playlists WHERE id=0;"; 
    305             markUpdated.ExecuteNonQuery(); 
    306  
    307             foreach (string path in directories) 
    308             { 
    309  
    310                 System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(path); 
    311  
    312                 //Should this return? It seems to me like it should silently 
    313                 //remove the directory from the DB if it's found to no longer 
    314                 //exist. Either that or just skip it. 
    315                 if (!di.Exists) 
    316                 { 
    317                     Error dirFailure = new Error("Directory " + path + " no longer exists"); 
    318                     return dirFailure; 
    319                 } 
    320  
    321                 bool returnVal = UpdateDirectory(di); 
    322  
    323                 if (returnVal == false) 
    324                 { 
    325                     Error updateFailed = new Error("Updating " + path + " failed"); 
    326                     return updateFailed; 
    327                 } 
    328             } 
    329  
    330             IDbCommand delNotUpdated = dbCon.CreateCommand(); 
    331             delNotUpdated.CommandText = "UPDATE songs SET deleted=1 WHERE Updated=0"; 
    332             delNotUpdated.ExecuteNonQuery(); 
    333  
    334             dbTrans.Commit(); 
    335             dbCon.Close(); 
    336  
    337             //Update Revision 
    338             TimeSpan unixTime = (DateTime.UtcNow - new DateTime(1970, 1, 1)); 
    339             lock (revLock) 
    340             { 
    341                 revision = (int)unixTime.TotalSeconds; 
    342                 Monitor.PulseAll(revLock); 
    343             } 
    344  
    345             return null; 
    346         } 
    347  
    348         //Updates all the songs in the current directory and calls itself  
    349         //recursively on all subdirectories 
    350         //TODO: 
    351         // --Handle updating existing entries 
    352         // --Find way of extracting tag info and inserting into db 
    353         private bool UpdateDirectory(System.IO.DirectoryInfo currentDir) 
    354         { 
    355             bool returnVal = true; //Not sure what this will be used for... 
    356             AudioFile song; 
    357  
    358             System.IO.FileInfo[] files = currentDir.GetFiles(); 
    359  
    360             //Do progress bar reset 
    361             if (progressTitle != null) 
    362                 progressTitle("Adding songs in "+currentDir.Name+"..."); 
    363             if (progressMax != null) 
    364                 progressMax(files.GetLength(0)); 
    365             if (progressReset != null) 
    366                 progressReset(); 
    367  
    368             foreach (System.IO.FileInfo fi in files) 
    369             { 
    370                 //Update progress bar 
    371                 if (progressUpdate != null) 
    372                     progressUpdate(); 
    373  
    374                 if (ValidMusicFile(fi)) 
    375                 { 
    376                     try 
    377                     { 
    378                         song = new AudioFile(fi.FullName); 
    379                     } 
    380                     catch (Exception e) 
    381                     { 
    382                         Console.WriteLine("Problem with file {0} : {1}", fi.FullName, e); 
    383                         continue; 
    384                     } 
    385  
    386                     insertSongPath.Value = fi.FullName; 
    387                     insertSongArtist.Value = song.Artist; 
    388                     insertSongAlbum.Value = song.Album; 
    389                     insertSongTitle.Value = song.Title; 
    390                     insertSongYear.Value = song.Year; 
    391                     insertSongFormat.Value = fi.Extension.Substring(1); 
    392                     insertSongDuration.Value = song.Duration.TotalMilliseconds; 
    393                     insertSongGenre.Value = song.Genre; 
    394                     insertSongTrackNumber.Value = song.TrackNumber; 
    395                     insertSongTrackCount.Value = song.TrackCount; 
    396                     insertSongSize.Value = fi.Length; 
    397                     insertSongFileLastModified.Value = fi.LastWriteTimeUtc; 
    398                     insertSongDbLastModified.Value = revision; 
    399  
    400                     int updateId = 0; 
    401                     DateTime lastUpdated = new DateTime(); 
    402  
    403                     getSongPath.Value = fi.FullName; 
    404                     IDataReader sqlTrack = getSongByPath.ExecuteReader(); 
    405                     if (sqlTrack.Read()) 
    406                     { 
    407                         updateId = sqlTrack.GetInt32(0); 
    408                         lastUpdated = sqlTrack.GetDateTime(1).ToUniversalTime(); 
    409                     } 
    410  
    411                     sqlTrack.Dispose(); 
    412  
    413                     //File was not already in database 
    414                     if (updateId == 0) 
    415                     { 
    416                         System.Console.WriteLine("Adding file {0} to database", fi.FullName); 
    417                         IDataReader lastID = insertSong.ExecuteReader(); 
    418  
    419                         lastID.Read(); 
    420                         insertSongInPlaylistId.Value = 0; 
    421                         insertSongInPlaylistSongId.Value = lastID.GetInt32(0); 
    422                         lastID.Dispose(); 
    423  
    424                         insertSongInPlaylist.ExecuteNonQuery(); 
    425                     } 
    426                     else 
    427                     { 
    428                         updateSongId.Value = updateId; 
    429  
    430                         //Put track back in the base playlist 
    431                         insertSongInPlaylistId.Value = 0; 
    432                         insertSongInPlaylistSongId.Value = updateId; 
    433  
    434                         insertSongInPlaylist.ExecuteNonQuery(); 
    435  
    436                         if (!lastUpdated.Equals(fi.LastWriteTimeUtc)) 
    437                         { 
    438                             System.Console.WriteLine("Updating file {0} in database", fi.FullName); 
    439                             updateSong.ExecuteNonQuery(); 
    440                         } 
    441                         else 
    442                             hasUpdated.ExecuteNonQuery(); 
    443                     } 
    444  
    445                 } 
    446             } 
    447  
    448             System.IO.DirectoryInfo[] directories = currentDir.GetDirectories(); 
    449  
    450             foreach (System.IO.DirectoryInfo di in directories) 
    451                 returnVal &= UpdateDirectory(di); 
    452  
    453             return returnVal; 
    454         } 
    455  
    456         [XmlRpcExposed] 
    457         public ArrayList ListSongs() 
    458         { 
    459             if (dbCon == null) 
    460                 return null; 
    461  
    462             try 
    463             { 
    464                 IDbCommand dbCmd = dbCon.CreateCommand(); 
    465  
    466                 dbCmd.CommandText = "SELECT COUNT(*) FROM songs"; 
    467  
    468                 dbCon.Open(); 
    469  
    470                 IDataReader reader = dbCmd.ExecuteReader(); 
    471                 reader.Read(); 
    472                 int count = reader.GetInt32(0); 
    473                 reader.Close(); 
    474  
    475                 ArrayList returnVal = new ArrayList(count); 
    476  
    477                 dbCmd.CommandText = "SELECT path FROM songs"; 
    478                 reader = dbCmd.ExecuteReader(); 
    479  
    480                 for (int i = 0; i < count; i++) 
    481                 { 
    482                     reader.Read(); 
    483                     returnVal.Add(reader.GetString(0)); 
    484                 } 
    485  
    486                 dbCon.Close(); 
    487                 return returnVal; 
    488             } 
    489             catch (Exception e) 
    490             { 
    491                 Console.WriteLine("Exception: {0}", e.Message); 
    492                 return null; 
    493             } 
    494         } 
    495  
    496         public int SongCount 
    497         { 
    498             get 
    499             { 
    500                 int count;                 
    501                 IDbCommand dbCmd = dbCon.CreateCommand(); 
    502  
    503                 dbCon.Open(); 
    504  
    505                 dbCmd.CommandText = "SELECT COUNT(*) FROM songs"; 
    506  
    507                 IDataReader reader = dbCmd.ExecuteReader(); 
    508                 if (reader.Read()) 
    509                     count = reader.GetInt32(0); 
    510                 else 
    511                     return 0; 
    512                 reader.Dispose(); 
    513  
    514                 dbCon.Close(); 
    515  
    516                 return count; 
    517             } 
    518         } 
    519  
    520         /// <summary> 
    521         /// A list of every track in the database 
    522         /// </summary> 
    523         public List<TrackBase> TrackList 
    524         { 
    525             get 
    526             { 
    527                 IDbCommand dbCmd = dbCon.CreateCommand(); 
    528                 List<TrackBase> trackList; 
    529  
    530                 dbCon.Open(); 
    531  
    532                 dbCmd.CommandText = "SELECT * FROM songs"; 
    533                 IDataReader reader = dbCmd.ExecuteReader(); 
    534  
    535                 trackList = (List<TrackBase>)SqlToTrack(reader); 
    536                 reader.Dispose(); 
    537                 dbCon.Close(); 
    538                 return trackList;   
    539             } 
    540         } 
    541  
    542         /// <summary> 
    543         /// Checks to see if the file already exists in the database. 
    544         /// </summary> 
    545         /// <param name="fi">FileInfo object about the file in question</param> 
    546         /// <returns>songid if file is in the database</returns> 
    547         private int FileExistsInDb(System.IO.FileInfo fi) 
    548         { 
    549             getSongPath.Value = fi.FullName; 
    550             int retTrack; 
    551  
    552             IDataReader sqlTrack = getSongByPath.ExecuteReader(); 
    553             if (sqlTrack.Read()) 
    554             { 
    555                 retTrack = sqlTrack.GetInt32(0); 
    556             } 
    557             else 
    558                 retTrack = 0; 
    559  
    560             sqlTrack.Dispose(); 
    561  
    562             return retTrack; 
    563         } 
    564  
    565         /// <summary> 
    566         /// Gets song data from the database. 
    567         /// </summary> 
    568         /// <param name="songid">Id of the song to play</param> 
    569         /// <returns></returns> 
    570         public TrackBase GetSong(Int32 songid) 
    571         { 
    572             getSongId.Value = songid; 
    573             dbCon.Open(); 
    574             IDataReader sqlTrack = getSong.ExecuteReader(); 
    575             List<TrackBase> retTrack = (List<TrackBase>) SqlToTrack(sqlTrack); 
    576             sqlTrack.Dispose(); 
    577             dbCon.Close(); 
    578  
    579             return retTrack[0]; 
    580         } 
    581  
    582         /// <summary> 
    583         /// Retreives playlist from the database 
    584         /// </summary> 
    585         /// <param name="playlistid">Id of the playlist to get</param> 
    586         /// <returns></returns> 
    587         public PlaylistBase GetPlaylist(Int32 playlistid) 
    588         { 
    589             PlaylistBase retVal = new PlaylistBase(playlistid); 
    590  
    591             dbCon.Open(); 
    592             getPlaylistId.Value = playlistid; 
    593             IDataReader sqlPlaylist = getPlaylist.ExecuteReader(); 
    594  
    595             while(sqlPlaylist.Read()) 
    596             { 
    597                 retVal.AddTrack(sqlPlaylist.GetInt32(1)); 
    598             } 
    599  
    600             sqlPlaylist.Dispose(); 
    601             dbCon.Close(); 
    602             return retVal; 
    603         } 
    604  
    605         //DB Commands 
    606         private IDbCommand insertSong; 
    607         private IDbCommand updateSong; 
    608         private IDbCommand hasUpdated; 
    609         private IDbCommand insertSongInPlaylist; 
    610         private IDbCommand getSong; 
    611         private IDbCommand getSongByPath; 
    612         private IDbCommand getPlaylist; 
    613         private IDbCommand getLatestRevision; 
    614  
    615         //Data parameters for insertSong and updateSong commands 
    616         private IDataParameter insertSongPath; 
    617         private IDataParameter insertSongArtist; 
    618         private IDataParameter insertSongAlbum; 
    619         private IDataParameter insertSongTitle; 
    620         private IDataParameter insertSongYear; 
    621         private IDataParameter insertSongFormat; 
    622         private IDataParameter insertSongDuration; 
    623         private IDataParameter insertSongGenre; 
    624         private IDataParameter insertSongTrackNumber; 
    625         private IDataParameter insertSongTrackCount; 
    626         private IDataParameter insertSongSize; 
    627         private IDataParameter insertSongFileLastModified; 
    628         private IDataParameter insertSongDbLastModified; 
    629  
    630         //Song id to update 
    631         private IDataParameter updateSongId; 
    632  
    633         //Data parameters for insertSongInPlaylist command 
    634         private IDataParameter insertSongInPlaylistSongId; 
    635         private IDataParameter insertSongInPlaylistId; 
    636  
    637         //parameters for getSong 
    638         private IDataParameter getSongId; 
    639         private IDataParameter getSongPath; 
    640  
    641         //parameters for getPlaylist 
    642         private IDataParameter getPlaylistId; 
    643  
    644         /// <summary> 
    645         /// initializes all the commands needed so they are only created once 
    646         /// </summary> 
    647         private void InitSQLCommands() 
    648         { 
    649             insertSong = dbCon.CreateCommand(); 
    650             updateSong = dbCon.CreateCommand(); 
    651             hasUpdated = dbCon.CreateCommand(); 
    652             insertSongInPlaylist = dbCon.CreateCommand(); 
    653             getSong = dbCon.CreateCommand(); 
    654             getSongByPath = dbCon.CreateCommand(); 
    655             getPlaylist = dbCon.CreateCommand(); 
    656             getLatestRevision = dbCon.CreateCommand(); 
    657  
    658             insertSong.CommandText = @"INSERT INTO songs(path, artist, album, title, year, format, duration, 
    659                                         genre, tracknumber, trackcount, size, updated, fileLastModified,  
    660                                         dbLastModified, deleted)  
    661                                         VALUES(?,?,?,?,?,?,?,?,?,?,?,1,?,?,0); 
    662                                         SELECT last_insert_rowid()"; 
    663             updateSong.CommandText = @"UPDATE songs SET path = ?, artist = ?, album = ?, title = ?, year =?, 
    664                                             format = ?, duration = ?, genre = ?, tracknumber = ?, trackcount =?, 
    665                                             size = ?, updated = 1, fileLastModified=?,  
    666                                             dbLastModified= ? 
    667                                             WHERE id = ?"; 
    668             hasUpdated.CommandText = @"UPDATE songs SET updated = 1 WHERE id = ?"; 
    669             insertSongInPlaylist.CommandText = @"INSERT INTO playlists(id, songid) VALUES(?,?)"; 
    670             getSong.CommandText = @"SELECT * FROM songs WHERE id = ?"; 
    671             getSongByPath.CommandText = @"SELECT id, fileLastModified FROM songs WHERE path = ?"; 
    672             getPlaylist.CommandText = @"SELECT * FROM playlists WHERE id = ?"; 
    673             getLatestRevision.CommandText = @"SELECT MAX(dbLastModified) FROM songs"; 
    674  
    675             //Create and add parameters for inserting songs 
    676             insertSongPath = insertSong.CreateParameter(); 
    677             insertSong.Parameters.Add(insertSongPath); 
    678             insertSongArtist = insertSong.CreateParameter(); 
    679             insertSong.Parameters.Add(insertSongArtist); 
    680             insertSongAlbum = insertSong.CreateParameter(); 
    681             insertSong.Parameters.Add(insertSongAlbum); 
    682             insertSongTitle = insertSong.CreateParameter(); 
    683             insertSong.Parameters.Add(insertSongTitle); 
    684             insertSongYear = insertSong.CreateParameter(); 
    685             insertSong.Parameters.Add(insertSongYear); 
    686             insertSongFormat = insertSong.CreateParameter(); 
    687             insertSong.Parameters.Add(insertSongFormat); 
    688             insertSongDuration = insertSong.CreateParameter(); 
    689             insertSong.Parameters.Add(insertSongDuration); 
    690             insertSongGenre = insertSong.CreateParameter(); 
    691             insertSong.Parameters.Add(insertSongGenre); 
    692             insertSongTrackNumber = insertSong.CreateParameter(); 
    693             insertSong.Parameters.Add(insertSongTrackNumber); 
    694             insertSongTrackCount = insertSong.CreateParameter(); 
    695             insertSong.Parameters.Add(insertSongTrackCount); 
    696             insertSongSize = insertSong.CreateParameter(); 
    697             insertSong.Parameters.Add(insertSongSize); 
    698             insertSongFileLastModified = insertSong.CreateParameter(); 
    699             insertSong.Parameters.Add(insertSongFileLastModified); 
    700             insertSongDbLastModified = insertSong.CreateParameter(); 
    701             insertSong.Parameters.Add(insertSongDbLastModified); 
    702  
    703             //update song parameters 
    704             updateSong.Parameters.Add(insertSongPath); 
    705             updateSong.Parameters.Add(insertSongArtist); 
    706             updateSong.Parameters.Add(insertSongAlbum); 
    707             updateSong.Parameters.Add(insertSongTitle); 
    708             updateSong.Parameters.Add(insertSongYear); 
    709             updateSong.Parameters.Add(insertSongFormat); 
    710             updateSong.Parameters.Add(insertSongDuration); 
    711             updateSong.Parameters.Add(insertSongGenre); 
    712             updateSong.Parameters.Add(insertSongTrackNumber); 
    713             updateSong.Parameters.Add(insertSongTrackCount); 
    714             updateSong.Parameters.Add(insertSongSize); 
    715             updateSong.Parameters.Add(insertSongFileLastModified); 
    716             updateSong.Parameters.Add(insertSongDbLastModified); 
    717  
    718             //update song id only applies to updates 
    719             updateSongId = updateSong.CreateParameter(); 
    720             updateSong.Parameters.Add(updateSongId); 
    721             hasUpdated.Parameters.Add(updateSongId); 
    722  
    723             insertSongInPlaylistId = insertSongInPlaylist.CreateParameter(); 
    724             insertSongInPlaylist.Parameters.Add(insertSongInPlaylistId); 
    725             insertSongInPlaylistSongId = insertSongInPlaylist.CreateParameter(); 
    726             insertSongInPlaylist.Parameters.Add(insertSongInPlaylistSongId); 
    727  
    728             getSongId = getSong.CreateParameter(); 
    729             getSong.Parameters.Add(getSongId); 
    730  
    731             getSongPath = getSongByPath.CreateParameter(); 
    732             getSongByPath.Parameters.Add(getSongPath); 
    733  
    734             getPlaylistId = getPlaylist.CreateParameter(); 
    735             getPlaylist.Parameters.Add(getPlaylistId); 
    736         } 
    737  
    738  
    739         /// <summary> 
    740         /// This returns an escaped path so all directory entries are uniform 
    741         /// </summary> 
    742         /// <param name="path"></param> 
    743         /// <returns></returns> 
    744         private string EscapePath(string path) 
    745         { 
    746             try 
    747             { 
    748                 path = System.IO.Path.GetFullPath(path); 
    749             } 
    750             catch (System.Exception e) 
    751             { 
    752                 return null; 
    753             } 
    754             return path; 
    755         } 
    756  
    757         ///<summary> 
    758         ///This checks whether a file is music 
    759         ///</summary> 
    760         private bool ValidMusicFile(System.IO.FileInfo fi) 
    761         { 
    762             if (fi.Extension == ".mp3" || fi.Extension == ".m4a") 
    763                 return true; 
    764             else 
    765                 return false; 
    766         } 
    767  
    768         /// <summary> 
    769         /// Turns an sql data reader into a list of tracks 
    770         /// </summary> 
    771         /// <param name="sqlResult"></param> 
    772         /// <returns></returns> 
    773         private IList<TrackBase> SqlToTrack(IDataReader sqlResult) 
    774         { 
    775             List<TrackBase> trackList = new List<TrackBase>(); 
    776             while (sqlResult.Read()) 
    777             { 
    778                 TrackBase track = new TrackBase(); 
    779  
    780                 track.SetId(sqlResult.GetInt32(0)); 
    781                 if (!sqlResult.IsDBNull(1)) 
    782                     track.FileName = sqlResult.GetString(1); 
    783                 if (!sqlResult.IsDBNull(2)) 
    784                     track.Artist = sqlResult.GetString(2); 
    785                 if (!sqlResult.IsDBNull(3)) 
    786                     track.Album = sqlResult.GetString(3); 
    787  
    788