Click here to Skip to main content
15,896,154 members
Articles / Mobile Apps / Windows Mobile

Audio Book Player

Rate me:
Please Sign up or sign in to vote.
4.86/5 (36 votes)
11 Jun 2009CPOL6 min read 198.7K   3.5K   84  
Audio player designed specifically for listening to audio books
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.Windows.Forms;
using System.Collections;
using System.Reflection;
using System.IO;
using System.Runtime.InteropServices;
using System.Data;
using System.Data.SqlServerCe;
using System.Linq;

public class cDatabasePersistantcy : cBasePersistancy
{
    private String pActiveBookName = "";
    private SqlCeCommand cmd = null;
    private String[] BOOK_ATTRIBUTE_NAME = { "BOOKMARKENTRY", 
        "BOOKMARKLOCATION", "VOLUME", "SHUFFLE" };
    private int[] BOOK_ATTRIBUTE_DEFAULTS = { 0, 0, 40, 0 };
    // ============================================================================
    private const Int64 MAX_STORAGE_CARD_CAPACITY = 20000000000;//20GB;
    // initial schema creation ====================================================
    private const String CREATE_BOOKS_TABLE = "CREATE TABLE BOOKS(" +
        "BOOKNAME nVarChar(100) NOT NULL CONSTRAINT PK PRIMARY KEY, " +
        "BOOKSHELF nVarChar(100) DEFAULT(''), " +
        "BOOKMARKENTRY int DEFAULT(0), " +
        "BOOKMARKLOCATION int DEFAULT(0), " +
        "VOLUME int DEFAULT(0), " +
        "SHUFFLE int DEFAULT(0))";
    private const String CREATE_BOOKSHELVES_TABLE = "CREATE TABLE BOOKSHELVES(" +
        "BOOKSHELF nVarChar(100) NOT NULL)";
    private const String CREATE_BOOKFILES_TABLE = "CREATE TABLE BOOKFILES(" +
        "BOOKNAME nVarChar(100) NOT NULL, " +
        "FILENAME nVarChar(255) DEFAULT(''), " +
        "FILEORDER int)";
    private const String CREATE_ATTRIBUTES_TABLE = "CREATE TABLE ATTRIBUTES(" +
        "IX int NOT NULL CONSTRAINT PK PRIMARY KEY, " +
        "ACTIVEBOOKNAME nVarChar(100) DEFAULT(''), " +
        "SKIN nVarChar(100) DEFAULT(''))";
    private const String INSERT_ATTRIBUTES_RECORD = "INSERT INTO ATTRIBUTES " +
        "(IX) VALUES (1)";
    // ============================================================================

    public cDatabasePersistantcy(String assembly)
    {
        SqlCeResultSet rs = null;
        // DB not supported on storage card in emulator mode.
        String basePath = (IsEmulator) ?
            Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase):
            GetLargestStorageCard();
        if (basePath.Length == 0)
            throw new Exception("No Storage card Found");
        String dbFileName = basePath +
            "\\" + assembly + ".sdf";
        string connString = "Data Source='" + dbFileName + "'";
        cmd = new SqlCeCommand();
        cmd.Connection = new SqlCeConnection(connString);
        try
        {
            if (File.Exists(dbFileName))
            {
                cmd.Connection.Open();
                // get active books
                const String SQL = "SELECT ACTIVEBOOKNAME FROM ATTRIBUTES WHERE IX=1";
                cmd.CommandText = SQL;
                rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
                if (rs.ReadFirst())
                    pActiveBookName = rs.GetString(0);
            }
            else
            {
                SqlCeEngine db = new SqlCeEngine(connString);
                db.CreateDatabase();
                db.Dispose();
                cmd.Connection.Open();
                cmd.CommandText = CREATE_BOOKS_TABLE;
                cmd.ExecuteNonQuery();
                cmd.CommandText = CREATE_BOOKFILES_TABLE;
                cmd.ExecuteNonQuery();
                cmd.CommandText = CREATE_BOOKSHELVES_TABLE;
                cmd.ExecuteNonQuery();
                cmd.CommandText = CREATE_ATTRIBUTES_TABLE;
                cmd.ExecuteNonQuery();
                cmd.CommandText = INSERT_ATTRIBUTES_RECORD;
                cmd.ExecuteNonQuery();
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
    }
    // destructor - close db connection
    ~cDatabasePersistantcy()
    {
        cmd.Connection.Close();
        cmd.Dispose();
    }
    // get driver manufacturer of USB -
    // this is the only way i found to distinguish between the emulator
    // and a real device
    private bool IsEmulator
    {
        get
        {
            // manufacturer registry entries
            const String MANUFACURER_KEY = "drivers\\usb\\functiondrivers";
            const String MANUFACURER_VALUE = "manufacturer";
            const String MANUFACURER_DATA_EMULATOR = "Generic Manufacturer";

            RegistryKey RK = null;
            RegistryKey SRK = null;
            String data = "";
            bool result = false;
            try
            {
                RK = Registry.LocalMachine.OpenSubKey(MANUFACURER_KEY, false);
                String[] keys = RK.GetSubKeyNames();
                if (keys.Length == 0) return false;
                SRK = RK.OpenSubKey(keys[0], false);
                data = (String)SRK.GetValue(MANUFACURER_VALUE);
                if (data.Contains(MANUFACURER_DATA_EMULATOR))
                    result = true;
            }
            catch
            {
            }
            finally
            {
                if (SRK != null) SRK.Close();
                if (RK != null) RK.Close();
            }
            return result;
        }
    }
    private String PrepareSQLCommand(String cmd, params String[] list)
    {
        String[] splitCmd = cmd.Split('?');
        if((splitCmd.Length - list.Length) != 1)
            throw new Exception("Unmatched params count");
        String result = "";
        for (int i = 0; i < list.Length; i++)
            result += splitCmd[i] + list[i].Replace("'", "''");
        return result + splitCmd[list.Length];
    }
    // get/set active book
    public override String ActiveBookName
    {
        get
        {
            return pActiveBookName;
        }
        set
        {
            try
            {
                const String SQL = "UPDATE ATTRIBUTES SET ACTIVEBOOKNAME='?' WHERE IX=1";
                // write value
                cmd.CommandText = PrepareSQLCommand(SQL, value);
                cmd.ExecuteNonQuery();
                pActiveBookName = value;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
    }
    // get/set skin
    public override String Skin
    {
        get
        {
            SqlCeResultSet rs = null;
            const String SQL = "SELECT SKIN FROM ATTRIBUTES WHERE IX=1";
            String sk = "";
            try
            {
                cmd.CommandText = SQL;
                rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
                if (rs.ReadFirst())
                    sk = rs.GetString(0);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            finally
            {
                if (rs != null) rs.Close();
            }
            return sk;
        }
        set
        {
            try
            {
                const String SQL = "UPDATE ATTRIBUTES SET SKIN='?' WHERE IX=1";
                cmd.CommandText = PrepareSQLCommand(SQL, value);
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
    }
    // get book poperty
    public override int GetBookProperty(eBookProperty prop, String book)
    {
        if ((book == "") && (ActiveBookName == "")) return 0;
        SqlCeResultSet rs = null;
        int value = 0;
        try
        {
            const String SQL = "SELECT ? FROM BOOKS WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL, BOOK_ATTRIBUTE_NAME[(int)prop],
                ((book == "") ? ActiveBookName : book));
            rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
            if (rs.ReadFirst())
                value = rs.GetInt32(0);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
        return value;
    }
    // set a book property
    public override bool SetBookProperty(eBookProperty prop, int value, String book)
    {
        if ((book == "") && (ActiveBookName == "")) return false;
        try
        {
            const String SQL = "UPDATE BOOKS SET ?=? WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL, 
                BOOK_ATTRIBUTE_NAME[(int)prop], 
                value.ToString(), 
                ((book == "") ? ActiveBookName : book));
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // get all bookshelves
    public override String[] Books
    {
        get
        {
            SqlCeResultSet rs = null;
            try
            {
                const String SQL = "SELECT BOOKNAME FROM BOOKS " +
                    "ORDER BY BOOKNAME";
                cmd.CommandText = SQL;
                rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
                ArrayList list = new ArrayList();
                while (rs.Read())
                    list.Add(rs.GetString(0));
                return (String[])list.ToArray(typeof(String));
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            finally
            {
                if (rs != null) rs.Close();
            }
            return new String[0];
        }
    }
    // get all bookshelves
    public override String[] Bookshelves
    {
        get
        {
            SqlCeResultSet rs = null;
            try
            {
                const String SQL = "SELECT BOOKSHELF FROM BOOKSHELVES " +
                    "ORDER BY BOOKSHELF";
                cmd.CommandText = SQL;
                rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
                ArrayList list = new ArrayList();
                while (rs.Read())
                    list.Add(rs.GetString(0));
                return (String[])list.ToArray(typeof(String));
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            finally
            {
                if (rs != null) rs.Close();
            }
            return new String[0];
       }
    }
    // get all books on (in) a bookshelf
    public override String[] GetBookshelfBooks(String bookshelf)
    {
        SqlCeResultSet rs = null;
        try
        {
            const String SQL = "SELECT BOOKNAME FROM BOOKS WHERE BOOKSHELF='?' " +
                "ORDER BY BOOKNAME";
            cmd.CommandText = PrepareSQLCommand(SQL, bookshelf);
            rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
            ArrayList list = new ArrayList();
            while (rs.Read())
                if(rs.GetString(0) != "")
                    list.Add(rs.GetString(0));
            return (String[])list.ToArray(typeof(String));
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
        return new String[0];
    }
    // get a book's bookshelf
    public override String GetBooksBookshelf(String book)
    {
        SqlCeResultSet rs = null;
        String value = "";
        if ((book == "") && (ActiveBookName == "")) return "";
        try
        {
            const String SQL = "SELECT BOOKSHELF FROM BOOKS WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL, 
                ((book == "") ? ActiveBookName : book));
            rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
            if (rs.ReadFirst())
                value = rs.GetString(0);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
        return value;
        
    }
    // create new bookshelf
    public override bool NewBookshelf(String bookshelf)
    {
        try
        {
            const String SQL = "INSERT INTO BOOKSHELVES " +
                "(BOOKSHELF) " +
                "VALUES ('?')";
            cmd.CommandText = PrepareSQLCommand(SQL, bookshelf);
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // delete a bookshelf
    public override bool DeleteBookshelf(String bookshelf)
    {
        try
        {
            // move all books in the bookshelf to the root node
            const String SQL1 = "UPDATE BOOKS SET BOOKSHELF='' WHERE BOOKSHELF='?'";
            // delete it
            const String SQL2 = "DELETE FROM BOOKSHELVES WHERE BOOKSHELF='?'"; 
            cmd.CommandText = PrepareSQLCommand(SQL1, bookshelf);
            cmd.ExecuteNonQuery();
            cmd.CommandText = PrepareSQLCommand(SQL2, bookshelf);
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // change a book's bookshelf
    public override bool SetBooksBookshelf(String book, String newBookshelf)
    {
        if ((book == "") && (ActiveBookName == "")) return false;
        try
        {
            const String SQL = "UPDATE BOOKS SET BOOKSHELF='?' WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL, newBookshelf, ((book == "") ? ActiveBookName : book));
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // create new book
    public override bool NewBook(String book, String bookshelf)
    {
        try
        {
            const String SQL = "INSERT INTO BOOKS " +
                "(BOOKNAME, BOOKSHELF, BOOKMARKENTRY, BOOKMARKLOCATION, VOLUME, SHUFFLE) " +
                "VALUES ('?', '?', ?, ?, ?, ?)";
            cmd.CommandText = PrepareSQLCommand(SQL,
                book, 
                bookshelf,
                BOOK_ATTRIBUTE_DEFAULTS[0].ToString(),
                BOOK_ATTRIBUTE_DEFAULTS[1].ToString(),
                BOOK_ATTRIBUTE_DEFAULTS[2].ToString(),
                BOOK_ATTRIBUTE_DEFAULTS[3].ToString());
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // get book file count 
    public override int GetBookFileCount(String book)
    {
        if ((book == "") && (ActiveBookName == "")) return 0;
        SqlCeResultSet rs = null;
        int count = 0;
        try
        {
            const String SQL = "SELECT COUNT (*) FROM BOOKFILES WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL,
                ((book == "") ? ActiveBookName : book));
            rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
            if (rs.ReadFirst())
                count = rs.GetInt32(0);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
        return count;
    }
    // get book files 
    public override String[] GetBookFiles(String book)
    {
        if ((book == "") && (ActiveBookName == "")) return new String[0];
        SqlCeResultSet rs = null;
        try
        {
            const String SQL = "SELECT FILENAME, FILEORDER FROM BOOKFILES WHERE BOOKNAME='?' " +
                "ORDER BY FILEORDER";
            cmd.CommandText = PrepareSQLCommand(SQL, ((book == "") ? ActiveBookName : book));
            rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable);
            ArrayList list = new ArrayList();
            while (rs.Read())
                list.Add(rs.GetString(0));
            return (String[])list.ToArray(typeof(String));
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
        return new String[0];
    }
    // set the book files - 
    // we always add the files to existing ones.
    public override bool SetBookFiles(String[] newFiles, String book)
    {
        if ((book == "") && (ActiveBookName == "")) return false;
        SqlCeResultSet rs = null;
        try
        {
            String[] oldFiles = GetBookFiles(((book == "") ? ActiveBookName : book));
            // delete existing
            DeleteBookFiles(book);
            // write old & new files.
            const String SQL = "SELECT BOOKNAME, FILENAME, FILEORDER FROM BOOKFILES WHERE BOOKNAME='?' ";
            cmd.CommandText = PrepareSQLCommand(SQL, ((book == "") ? ActiveBookName : book));
            rs = cmd.ExecuteResultSet(ResultSetOptions.Scrollable |
                ResultSetOptions.Updatable);
            int n = 0;
            foreach (String file in newFiles)
            {
                n++;
                SqlCeUpdatableRecord rec = rs.CreateRecord();
                rec.SetString(0, book);
                rec.SetString(1, file);
                rec.SetInt32(2, n);
                rs.Insert(rec);
            }
            foreach (String file in oldFiles)
            {
                n++;
                SqlCeUpdatableRecord rec = rs.CreateRecord();
                rec.SetString(0, book);
                rec.SetString(1, file);
                rec.SetInt32(2, n);
                rs.Insert(rec);
            }
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        finally
        {
            if (rs != null) rs.Close();
        }
        return false;
    }
    // delete a file entry
    public override bool DeleteBookFile(int ix, String book)
    {
        if ((book == "") && (ActiveBookName == "")) return false;
        try
        {
            ArrayList files = new ArrayList();
            files.AddRange(GetBookFiles(book));
            if ((ix < 0) || (ix > (files.Count - 1))) return false;
            files.RemoveAt(ix);
            DeleteBookFiles(book);
            SetBookFiles((String[])files.ToArray(typeof(String)), book);
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // delete all book file entries
    public override bool DeleteBookFiles(String book)
    {
        if ((book == "") && (ActiveBookName == "")) return false;
        try
        {
            const String SQL = "DELETE FROM BOOKFILES WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL, ((book == "") ? ActiveBookName : book));
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // rename a bookshelf
    public override bool RenameBookShelf(String newName, String bookshelf)
    {
        try
        {
            const String SQL1 = "UPDATE BOOKSHELVES SET BOOKSHELF='?' WHERE BOOKSHELF='?'";
            cmd.CommandText = PrepareSQLCommand(SQL1, newName, bookshelf);
            cmd.ExecuteNonQuery();
            const String SQL2 = "UPDATE BOOKS SET BOOKSHELF='?' WHERE BOOKSHELF='?'";
            cmd.CommandText = PrepareSQLCommand(SQL2, newName, bookshelf);
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // rename a book
    public override bool RenameBook(String newName, String book)
    {
        if (book == "") return false;
        try
        {
            String[] files = GetBookFiles(book);
            String bookshelf = GetBooksBookshelf(book);
            int[] attr = new int[4];
            for (int i = 0; i < attr.Length; i++)
                attr[i] = GetBookProperty((eBookProperty)i, book);
            DeleteBook(book);
            NewBook(newName, bookshelf);
            SetBookFiles(files, newName);
            for (int i = 0; i < attr.Length; i++)
                SetBookProperty((eBookProperty)i, attr[i], newName);
            if (pActiveBookName == book)
                ActiveBookName = newName;
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
    // delete a book.
    public override bool DeleteBook(String book)
    {
        if (book == "") return false;
        // if active book is deleted - no active book anymore
        if (ActiveBookName == book)
            ActiveBookName = "";
        try
        {
            const String SQL1 = "DELETE FROM BOOKFILES WHERE BOOKNAME='?'";
            const String SQL2 = "DELETE FROM BOOKS WHERE BOOKNAME='?'";
            cmd.CommandText = PrepareSQLCommand(SQL1, book);
            cmd.ExecuteNonQuery();
            cmd.CommandText = PrepareSQLCommand(SQL2, book);
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
        return false;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions