diff --git a/src/core/library/Indexer.cpp b/src/core/library/Indexer.cpp index 045746237..495a34069 100644 --- a/src/core/library/Indexer.cpp +++ b/src/core/library/Indexer.cpp @@ -215,7 +215,7 @@ void Indexer::SynchronizeInternal() { for(std::size_t i = 0; i < paths.size(); ++i) { std::string path = paths[i]; - this->SyncDirectory(path, path ,0, pathIds[i]); + this->SyncDirectory(path, path, pathIds[i]); } /* remove undesired entries from db (files themselves will remain) */ @@ -228,7 +228,7 @@ void Indexer::SynchronizeInternal() { } if (!this->Restarted() && !this->Exited()) { - this->SyncDelete(pathIds); + this->SyncDelete(); } /* cleanup -- remove stale artists, albums, genres, etc */ @@ -270,26 +270,9 @@ void Indexer::SynchronizeInternal() { musik::debug::info(TAG, "done!"); } -////////////////////////////////////////// -///\brief -///Reads all tracks in a folder -/// -///\param dir -///Folder to check files in -/// -///\param parentDirId -///Database ID of the parent folder (folders table) -/// -///\param pathId -///Database ID of the current path (paths table) -/// -///Read all tracks in a folder. All folders in that folder is recursively called. -////////////////////////////////////////// - void Indexer::SyncDirectory( const std::string &syncRoot, const std::string ¤tPath, - DBID parentDirId, DBID pathId) { if (this->Exited() || this->Restarted()) { @@ -300,39 +283,6 @@ void Indexer::SyncDirectory( std::string normalizedCurrentPath = normalizeDir(currentPath); std::string leaf = boost::filesystem::path(currentPath).leaf().string(); /* trailing subdir in currentPath */ - DBID dirId = 0; - - /* get relative folder id */ - - { - db::CachedStatement stmt("SELECT id FROM folders WHERE name=? AND path_id=? AND parent_id=?", this->dbConnection); - stmt.BindText(0, leaf); - stmt.BindInt(1, pathId); - stmt.BindInt(2, parentDirId); - - if (stmt.Step() == db::Row) { - dirId = stmt.ColumnInt(0); - } - } - - /* no ID yet? needs to be inserted... */ - - if (dirId == 0) { - std::string relativePath(normalizedCurrentPath.substr(normalizedSyncRoot.size())); - - db::CachedStatement stmt("INSERT INTO folders (name, path_id, parent_id, relative_path) VALUES(?,?,?,?)", this->dbConnection); - stmt.BindText(0, leaf); - stmt.BindInt(1, pathId); - stmt.BindInt(2, parentDirId); - stmt.BindText(3, relativePath); - - if (stmt.Step() != db::Done) { - return; /* ugh, failed? */ - } - - dirId = this->dbConnection.LastInsertedId(); - } - /* start recursive filesystem scan */ try { /* boost::filesystem may throw */ @@ -343,11 +293,13 @@ void Indexer::SyncDirectory( boost::filesystem::directory_iterator end; boost::filesystem::directory_iterator file(path); + std::string pathIdStr = boost::lexical_cast(pathId); + for( ; file != end && !this->Exited() && !this->Restarted(); file++) { if (is_directory(file->status())) { /* recursion here */ musik::debug::info(TAG, "scanning " + file->path().string()); - this->SyncDirectory(syncRoot, file->path().string(), dirId, pathId); + this->SyncDirectory(syncRoot, file->path().string(), pathId); } else { ++this->filesIndexed; @@ -355,7 +307,7 @@ void Indexer::SyncDirectory( musik::core::IndexerTrack track(0); /* get cached filesize, parts, size, etc */ - if (track.NeedsToBeIndexed(file->path(), this->dbConnection, dirId)) { + if (track.NeedsToBeIndexed(file->path(), this->dbConnection)) { bool saveToDb = false; /* read the tag from the plugin */ @@ -373,7 +325,8 @@ void Indexer::SyncDirectory( /* write it to the db, if read successfully */ if (saveToDb) { - track.Save(this->dbConnection, this->libraryPath, dirId); + track.SetValue("path_id", pathIdStr.c_str()); + track.Save(this->dbConnection, this->libraryPath); this->filesSaved++; if (this->filesSaved % 100 == 0) { @@ -443,133 +396,38 @@ void Indexer::ThreadLoop() { } } -////////////////////////////////////////// -///\brief -///Part of the synchronizer to delete removed files. -/// -///\param paths -///Vector of path-id to check for deletion -/// -///This method will first check for removed folders and automaticaly -///delete all tracks in the removed folders. -///Secondly it will check all files it they are removed. -/// -///\remarks -///This method will not delete related information (meta-data, albums, etc) -////////////////////////////////////////// -void Indexer::SyncDelete(const std::vector& paths) { - /* delete pruned paths from path table */ - this->dbConnection.Execute("DELETE FROM folders WHERE path_id NOT IN (SELECT id FROM paths)"); +void Indexer::SyncDelete() { + /* remove all tracks that no longer reference a valid path entry */ - db::Statement stmtSyncPath("SELECT p.path FROM paths p WHERE p.id=?", this->dbConnection); + this->dbConnection.Execute("DELETE FROM tracks WHERE path_id NOT IN (SELECT id FROM paths)"); - { - db::Statement stmt( - "SELECT f.id, p.path || f.relative_path " - "FROM folders f, paths p " - "WHERE f.path_id=p.id AND p.id=?", this->dbConnection); - - db::Statement stmtRemove("DELETE FROM folders WHERE id=?",this->dbConnection); - - for (std::size_t i = 0; i < paths.size(); ++i) { - stmt.BindInt(0, paths[i]); - - stmtSyncPath.BindInt(0, paths[i]); - stmtSyncPath.Step(); - std::string syncPathString(stmtSyncPath.ColumnText(0)); - stmtSyncPath.Reset(); - - while (stmt.Step() == db::Row && !this->Exited() && !this->Restarted()) { - bool remove = true; - std::string dir = stmt.ColumnText(1); - - try { - boost::filesystem::path path(dir); - if (boost::filesystem::exists(path)) { - remove = false; - } - else { - boost::filesystem::path syncPath(syncPathString); - - if (!boost::filesystem::exists(syncPath)) { - remove = false; - } - } - } - catch (...){ - remove = false; - } - - if (remove) { - stmtRemove.BindInt(0, stmt.ColumnInt(0)); - stmtRemove.Step(); - stmtRemove.Reset(); - } - } - - stmt.Reset(); - } - } - - /* we deleted folders above. remove all tracks that were in those dirs*/ - - this->dbConnection.Execute("DELETE FROM tracks WHERE folder_id NOT IN (SELECT id FROM folders)"); - - // Remove tracks - db::Statement stmtCount("SELECT count(*) FROM tracks", this->dbConnection); - DBID songs = 0, count = 0; - - if (stmtCount.Step() == db::Row) { - songs = stmtCount.ColumnInt(0); - } - - db::Statement stmt( - "SELECT t.id, p.path || f.relative_path || '/' || t.filename " - "FROM tracks t, folders f, paths p " - "WHERE t.folder_id=f.id AND f.path_id=p.id AND p.id=?", this->dbConnection); + /* remove files that are no longer on the filesystem. */ db::Statement stmtRemove("DELETE FROM tracks WHERE id=?", this->dbConnection); - for (std::size_t i = 0; i < paths.size(); ++i) { - stmt.BindInt(0, paths[i]); + db::Statement allTracks( + "SELECT t.id, t.filename " + "FROM tracks t " + "WHERE p.id=?", this->dbConnection); - stmtSyncPath.BindInt(0,paths[i]); - stmtSyncPath.Step(); - - std::string syncPathString = stmtSyncPath.ColumnText(0); + while(allTracks.Step() == db::Row && !this->Exited() && !this->Restarted()) { + bool remove = false; + std::string file = allTracks.ColumnText(1); - stmtSyncPath.Reset(); - - while(stmt.Step() == db::Row && !this->Exited() && !this->Restarted()) { - bool remove = true; - std::string file = stmt.ColumnText(1); - - try{ - boost::filesystem::path file(file); - if (boost::filesystem::exists(file)) { - remove = false; - } - else { - boost::filesystem::path syncPath(syncPathString); - if (!boost::filesystem::exists(syncPath)) { - remove = false; - } - } + try { + boost::filesystem::path file(file); + if (!boost::filesystem::exists(file)) { + remove = true; } - catch(...) { - remove = false; - } - - if (remove) { - stmtRemove.BindInt(0, stmt.ColumnInt(0)); - stmtRemove.Step(); - stmtRemove.Reset(); - } - - ++count; } - - stmt.Reset(); + catch(...) { + } + + if (remove) { + stmtRemove.BindInt(0, allTracks.ColumnInt(0)); + stmtRemove.Step(); + stmtRemove.Reset(); + } } } @@ -694,8 +552,7 @@ void Indexer::SyncOptimize() { db::Statement outer("SELECT t.id FROM tracks t " \ "LEFT OUTER JOIN artists ar ON ar.id=t.visual_artist_id " \ "LEFT OUTER JOIN albums al ON al.id=t.album_id " \ - "LEFT OUTER JOIN folders f ON f.id=t.folder_id " \ - "ORDER BY ar.sort_order, al.sort_order, t.track, f.relative_path, t.filename", + "ORDER BY ar.sort_order, al.sort_order, t.track, t.filename", this->dbConnection); db::Statement inner("UPDATE tracks SET sort_order1=? WHERE id=?",this->dbConnection); @@ -745,8 +602,6 @@ void Indexer::ProcessAddRemoveQueue() { this->addRemoveQueue.pop_front(); } - this->dbConnection.Execute("DELETE FROM folders WHERE path_id NOT IN (SELECT id FROM paths)"); - this->PathsUpdated(); } @@ -775,17 +630,15 @@ void Indexer::RunAnalyzers() { /* for each track... */ DBID trackId = 0; - DBID folderId = 0; db::Statement getNextTrack( - "SELECT id, folder_id FROM tracks WHERE id>? ORDER BY id LIMIT 1", + "SELECT id FROM tracks WHERE id>? ORDER BY id LIMIT 1", this->dbConnection); getNextTrack.BindInt(0, trackId); while(getNextTrack.Step() == db::Row ) { trackId = getNextTrack.ColumnInt(0); - folderId = getNextTrack.ColumnInt(1); getNextTrack.Reset(); getNextTrack.UnBindAll(); @@ -838,7 +691,7 @@ void Indexer::RunAnalyzers() { completed successfully, then save the track. */ if(successPlugins>0) { - track.Save(this->dbConnection, this->libraryPath,folderId); + track.Save(this->dbConnection, this->libraryPath); } } } diff --git a/src/core/library/Indexer.h b/src/core/library/Indexer.h index d712908a1..799a940b8 100644 --- a/src/core/library/Indexer.h +++ b/src/core/library/Indexer.h @@ -76,7 +76,7 @@ namespace musik { namespace core { bool Restarted(); - void SyncDelete(const std::vector& paths); + void SyncDelete(); void SyncCleanup(); void ProcessAddRemoveQueue(); void SyncOptimize(); @@ -87,7 +87,6 @@ namespace musik { namespace core { void SyncDirectory( const std::string& syncRoot, const std::string& currentPath, - DBID parentDirId, DBID pathId); db::Connection dbConnection; diff --git a/src/core/library/LocalLibrary.cpp b/src/core/library/LocalLibrary.cpp index 7f96338be..35954c37c 100644 --- a/src/core/library/LocalLibrary.cpp +++ b/src/core/library/LocalLibrary.cpp @@ -234,7 +234,6 @@ bool LocalLibrary::IsSpecialMTOMetaKey(std::string &metakey){ specialMTOMetaKeys.insert("album"); specialMTOMetaKeys.insert("visual_genre"); specialMTOMetaKeys.insert("visual_artist"); - specialMTOMetaKeys.insert("folder"); } return specialMTOMetaKeys.find(metakey)!=specialMTOMetaKeys.end(); @@ -272,8 +271,8 @@ void LocalLibrary::CreateDatabase(db::Connection &db){ "year INTEGER DEFAULT 0," "visual_genre_id INTEGER DEFAULT 0," "visual_artist_id INTEGER DEFAULT 0," + "path_id INTEGER," "album_id INTEGER DEFAULT 0," - "folder_id INTEGER DEFAULT 0," "title TEXT default ''," "filename TEXT default ''," "filetime INTEGER DEFAULT 0," @@ -333,16 +332,7 @@ void LocalLibrary::CreateDatabase(db::Connection &db){ "path TEXT default ''" ")"); - // Create the folders-table - db.Execute("CREATE TABLE IF NOT EXISTS folders (" - "id INTEGER PRIMARY KEY AUTOINCREMENT," - "name TEXT default ''," - "relative_path TEXT default ''," - "parent_id INTEGER DEFAULT 0," - "path_id INTEGER DEFAULT 0" - ")"); - - // Create the folders-table + // Create the thumbnails table db.Execute("CREATE TABLE IF NOT EXISTS thumbnails (" "id INTEGER PRIMARY KEY AUTOINCREMENT," "filename TEXT default ''," @@ -350,13 +340,14 @@ void LocalLibrary::CreateDatabase(db::Connection &db){ "checksum INTEGER DEFAULT 0" ")"); - // Create the playlists-table + // Create the playlists db.Execute("CREATE TABLE IF NOT EXISTS playlists (" "id INTEGER PRIMARY KEY AUTOINCREMENT," "name TEXT default ''," "user_id INTEGER default 0" ")"); - // Create the playlists-table + + // Create the playlist_tracks table db.Execute("CREATE TABLE IF NOT EXISTS playlist_tracks (" "track_id INTEGER DEFAULT 0," "playlist_id INTEGER DEFAULT 0," @@ -365,13 +356,11 @@ void LocalLibrary::CreateDatabase(db::Connection &db){ // INDEXES db.Execute("CREATE UNIQUE INDEX IF NOT EXISTS users_index ON users (login)"); - db.Execute("CREATE UNIQUE INDEX IF NOT EXISTS folders_index ON folders (name,parent_id,path_id)"); db.Execute("CREATE UNIQUE INDEX IF NOT EXISTS paths_index ON paths (path)"); db.Execute("CREATE INDEX IF NOT EXISTS genre_index ON genres (sort_order)"); db.Execute("CREATE INDEX IF NOT EXISTS artist_index ON artists (sort_order)"); db.Execute("CREATE INDEX IF NOT EXISTS album_index ON albums (sort_order)"); db.Execute("CREATE INDEX IF NOT EXISTS track_index1 ON tracks (album_id,sort_order1)"); - db.Execute("CREATE INDEX IF NOT EXISTS track_index7 ON tracks (folder_id)"); db.Execute("CREATE INDEX IF NOT EXISTS thumbnail_index ON thumbnails (filesize)"); db.Execute("CREATE INDEX IF NOT EXISTS trackgenre_index1 ON track_genres (track_id,genre_id)"); diff --git a/src/core/library/LocalLibraryConstants.h b/src/core/library/LocalLibraryConstants.h index e7f2a844b..bde19945a 100755 --- a/src/core/library/LocalLibraryConstants.h +++ b/src/core/library/LocalLibraryConstants.h @@ -49,13 +49,13 @@ namespace musik { namespace core { namespace library { namespace constants { static const char* DISPLAY_GENRE_ID = "visual_genre_id"; static const char* DISPLAY_ARTIST_ID = "visual_artist_id"; static const char* ALBUM_ID = "album_id"; - static const char* RELATIVE_PATH_ID = "folder_id"; + static const char* PATH_ID = "path_id"; static const char* TITLE = "title"; static const char* FILENAME = "filename"; static const char* FILETIME = "filetime"; static const char* THUMBNAIL_ID = "thumbnail_id"; static const char* SORT_ORDER = "sort_order1"; - static const char* PATH = "path"; /* not in DB; synthesized */ + static const char* PATH = "path"; } namespace Genres { @@ -123,15 +123,6 @@ namespace musik { namespace core { namespace library { namespace constants { static const char* PATH = "path"; } - namespace RelativePaths { - static const char* TABLE_NAME = "folders"; - static const char* ID = "id"; - static const char* NAME = "name"; - static const char* RELATIVE_PATH = "relative_path"; - static const char* PARENT_ID = "parent_id"; - static const char* PATH_ID = "path_id"; - } - namespace Thumbnails { static const char* TABLE_NAME = "thumbnails"; static const char* ID = "id"; diff --git a/src/core/library/track/IndexerTrack.cpp b/src/core/library/track/IndexerTrack.cpp index 25c80a969..63626ff8a 100644 --- a/src/core/library/track/IndexerTrack.cpp +++ b/src/core/library/track/IndexerTrack.cpp @@ -137,12 +137,11 @@ DBID IndexerTrack::Id() { bool IndexerTrack::NeedsToBeIndexed( const boost::filesystem::path &file, - db::Connection &dbConnection, - DBID currentFolderId) + db::Connection &dbConnection) { try { this->SetValue("path", file.string().c_str()); - this->SetValue("filename", file.leaf().string().c_str()); + this->SetValue("filename", file.string().c_str()); size_t lastDot = file.leaf().string().find_last_of("."); if (lastDot != std::string::npos){ @@ -158,10 +157,9 @@ bool IndexerTrack::NeedsToBeIndexed( db::CachedStatement stmt( "SELECT id, filename, filesize, filetime " \ "FROM tracks t " \ - "WHERE folder_id=? AND filename=?", dbConnection); + "WHERE filename=?", dbConnection); - stmt.BindInt(0, currentFolderId); - stmt.BindText(1, this->GetValue("filename")); + stmt.BindText(0, this->GetValue("filename")); bool fileDifferent = true; @@ -184,11 +182,10 @@ bool IndexerTrack::NeedsToBeIndexed( static DBID writeToTracksTable( db::Connection &dbConnection, IndexerTrack& track, - DBID folderId, DBID tempSortOrder) { db::CachedStatement stmt("INSERT OR REPLACE INTO tracks " \ - "(id, track, bpm, duration, filesize, year, folder_id, title, filename, filetime, sort_order1) " \ + "(id, track, bpm, duration, filesize, year, title, filename, filetime, path_id, sort_order1) " \ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", dbConnection); stmt.BindText(1, track.GetValue("track")); @@ -196,10 +193,10 @@ static DBID writeToTracksTable( stmt.BindText(3, track.GetValue("duration")); stmt.BindText(4, track.GetValue("filesize")); stmt.BindText(5, track.GetValue("year")); - stmt.BindInt(6, folderId); - stmt.BindText(7, track.GetValue("title")); - stmt.BindText(8, track.GetValue("filename")); - stmt.BindText(9, track.GetValue("filetime")); + stmt.BindText(6, track.GetValue("title")); + stmt.BindText(7, track.GetValue("filename")); + stmt.BindText(8, track.GetValue("filetime")); + stmt.BindText(9, track.GetValue("path_id")); stmt.BindInt(10, tempSortOrder); if (track.Id() != 0) { @@ -448,7 +445,7 @@ DBID IndexerTrack::ExtractArtist(db::Connection& dbConnection) { ARTIST_TRACK_FOREIGN_KEY); } -bool IndexerTrack::Save(db::Connection &dbConnection, std::string libraryDirectory, DBID folderId) { +bool IndexerTrack::Save(db::Connection &dbConnection, std::string libraryDirectory) { db::ScopedTransaction transaction(dbConnection); /* remove existing relations -- we're going to update them with fresh data */ @@ -461,7 +458,7 @@ bool IndexerTrack::Save(db::Connection &dbConnection, std::string libraryDirecto /* write generic info to the tracks table */ - this->id = writeToTracksTable(dbConnection, *this, folderId, tempSortOrder); + this->id = writeToTracksTable(dbConnection, *this, tempSortOrder); DBID albumId = this->ExtractAlbum(dbConnection); DBID genreId = this->ExtractGenre(dbConnection); @@ -567,9 +564,9 @@ bool IndexerTrack::Reload(db::Connection &db) { "ORDER BY tm.id", db); db::Statement track( - "SELECT t.track, t.bpm, t.duration, t.filesize, t.year, t.title, t.filename, t.thumbnail_id, p.path|| f.relative_path || '/' || t.filename, al.name, t.filetime, t.sort_order1 " \ - "FROM tracks t, folders f, paths p, albums al " \ - "WHERE t.id=? AND t.folder_id=f.id AND f.path_id=p.id AND t.album_id=al.id", db); + "SELECT t.track, t.bpm, t.duration, t.filesize, t.year, t.title, t.filename, t.thumbnail_id, al.name, t.filetime, t.sort_order1 " \ + "FROM tracks t, paths p, albums al " \ + "WHERE t.id=? AND t.album_id=al.id", db); track.BindInt(0, this->id); if(track.Step() == db::Row) { @@ -581,10 +578,9 @@ bool IndexerTrack::Reload(db::Connection &db) { this->SetValue("title", track.ColumnText(5)); this->SetValue("filename", track.ColumnText(6)); this->SetValue("thumbnail_id", track.ColumnText(7)); - this->SetValue("path", track.ColumnText(8)); - this->SetValue("album", track.ColumnText(9)); - this->SetValue("filetime", track.ColumnText(10)); - this->tempSortOrder = track.ColumnInt(11); + this->SetValue("album", track.ColumnText(8)); + this->SetValue("filetime", track.ColumnText(9)); + this->tempSortOrder = track.ColumnInt(10); genres.BindInt(0, this->id); while (genres.Step() == db::Row) { @@ -592,7 +588,7 @@ bool IndexerTrack::Reload(db::Connection &db) { } artists.BindInt(0, this->id); - while (artists.Step()==db::Row) { + while (artists.Step() == db::Row) { this->SetValue("artist", artists.ColumnText(0)); } diff --git a/src/core/library/track/IndexerTrack.h b/src/core/library/track/IndexerTrack.h index b8034d33c..48e90fe4f 100644 --- a/src/core/library/track/IndexerTrack.h +++ b/src/core/library/track/IndexerTrack.h @@ -66,13 +66,11 @@ namespace musik { namespace core { bool NeedsToBeIndexed( const boost::filesystem::path &file, - db::Connection &dbConnection, - DBID currentFolderId); + db::Connection &dbConnection); bool Save( db::Connection &dbConnection, - std::string libraryDirectory, - DBID folderId); + std::string libraryDirectory); bool Reload(db::Connection &db); diff --git a/src/core/library/track/LibraryTrack.cpp b/src/core/library/track/LibraryTrack.cpp index 562fc8517..a18656b6d 100644 --- a/src/core/library/track/LibraryTrack.cpp +++ b/src/core/library/track/LibraryTrack.cpp @@ -197,5 +197,4 @@ LibraryTrack::MetaData::MetaData() LibraryTrack::MetaData::~MetaData() { delete this->thumbnailData; -} - +} \ No newline at end of file diff --git a/src/core/library/track/LibraryTrack.h b/src/core/library/track/LibraryTrack.h index aebe90651..6aa86b2fc 100644 --- a/src/core/library/track/LibraryTrack.h +++ b/src/core/library/track/LibraryTrack.h @@ -39,6 +39,7 @@ #include #include #include +#include namespace musik { namespace core { namespace http { class Responder; @@ -63,9 +64,9 @@ namespace musik { namespace core { virtual DBID Id(); virtual std::string GetValue(const char* metakey); - virtual void SetValue(const char* metakey,const char* value); + virtual void SetValue(const char* metakey, const char* value); virtual void ClearValue(const char* metakey); - virtual void SetThumbnail(const char *data,long size); + virtual void SetThumbnail(const char *data, long size); virtual std::string URI(); virtual std::string URL(); diff --git a/src/musikbox/IKeyHandler.h b/src/musikbox/IKeyHandler.h new file mode 100755 index 000000000..a7ac4bd77 --- /dev/null +++ b/src/musikbox/IKeyHandler.h @@ -0,0 +1,8 @@ +#pragma once + +#include "stdafx.h" + +class IKeyHandler { + public: + virtual void KeyPress(int64 ch) = 0; +}; \ No newline at end of file diff --git a/src/musikbox/IScrollAdapter.h b/src/musikbox/IScrollAdapter.h index 666d990ce..159158d13 100755 --- a/src/musikbox/IScrollAdapter.h +++ b/src/musikbox/IScrollAdapter.h @@ -1,7 +1,6 @@ #pragma once #include "stdafx.h" -#include class IScrollAdapter { public: diff --git a/src/musikbox/LibraryLayout.cpp b/src/musikbox/LibraryLayout.cpp index 3bf979de3..c38c5605f 100755 --- a/src/musikbox/LibraryLayout.cpp +++ b/src/musikbox/LibraryLayout.cpp @@ -3,8 +3,11 @@ #include "Screen.h" #include "LibraryLayout.h" -LibraryLayout::LibraryLayout(LibraryPtr library) +#define CATEGORY_WIDTH 25 + +LibraryLayout::LibraryLayout(Transport& transport, LibraryPtr library) : LayoutBase() { + this->transport = &transport; this->library = library; this->InitializeWindows(); } @@ -18,17 +21,17 @@ void LibraryLayout::Layout() { this->SetPosition(0, 0); this->albumList->SetPosition(0, 0); - this->albumList->SetSize(20, this->GetHeight()); + this->albumList->SetSize(CATEGORY_WIDTH, this->GetHeight()); this->albumList->SetFocusOrder(0); - this->trackList->SetPosition(20, 0); - this->trackList->SetSize(this->GetWidth() - 20, this->GetHeight()); + this->trackList->SetPosition(CATEGORY_WIDTH, 0); + this->trackList->SetSize(this->GetWidth() - CATEGORY_WIDTH, this->GetHeight()); this->trackList->SetFocusOrder(1); } void LibraryLayout::InitializeWindows() { - this->albumList.reset(new CategoryListView(library)); - this->trackList.reset(new TrackListView(library)); + this->albumList.reset(new CategoryListView(this->library)); + this->trackList.reset(new TrackListView(*this->transport, this->library)); this->AddWindow(this->albumList); this->AddWindow(this->trackList); diff --git a/src/musikbox/LibraryLayout.h b/src/musikbox/LibraryLayout.h index dc597648b..10b65954a 100755 --- a/src/musikbox/LibraryLayout.h +++ b/src/musikbox/LibraryLayout.h @@ -4,15 +4,17 @@ #include "CategoryListView.h" #include "TrackListView.h" +#include #include #include using musik::core::LibraryPtr; +using musik::core::audio::Transport; class LibraryLayout : public LayoutBase, public sigslot::has_slots<> { public: - LibraryLayout(LibraryPtr library); + LibraryLayout(Transport& transport, LibraryPtr library); virtual ~LibraryLayout(); virtual void Layout(); @@ -24,6 +26,7 @@ class LibraryLayout : public LayoutBase, public sigslot::has_slots<> { void OnCategoryViewSelectionChanged( ListWindow *view, size_t newIndex, size_t oldIndex); + Transport* transport; LibraryPtr library; std::shared_ptr albumList; std::shared_ptr trackList; diff --git a/src/musikbox/Main.cpp b/src/musikbox/Main.cpp index a37fea3d7..f47d5a116 100644 --- a/src/musikbox/Main.cpp +++ b/src/musikbox/Main.cpp @@ -42,6 +42,7 @@ #include "MainLayout.h" #include "LibraryLayout.h" #include "IInput.h" +#include "IKeyHandler.h" #include "WindowMessageQueue.h" #include @@ -60,6 +61,7 @@ struct WindowState { ILayout* layout; IWindow* focused; IInput* input; + IKeyHandler* keyHandler; IScrollable* scrollable; }; @@ -85,6 +87,7 @@ void changeLayout(WindowState& current, ILayout* newLayout) { current.focused = current.layout->GetFocus(); current.input = dynamic_cast(current.focused); current.scrollable = dynamic_cast(current.focused); + current.keyHandler = dynamic_cast(current.focused); } if (current.input) { @@ -102,8 +105,9 @@ void focusNextInLayout(WindowState& current) { } current.focused = current.layout->FocusNext(); - current.scrollable = dynamic_cast(current.focused); current.input = dynamic_cast(current.focused); + current.scrollable = dynamic_cast(current.focused); + current.keyHandler = dynamic_cast(current.focused); if (current.input != NULL) { curs_set(1); @@ -164,7 +168,7 @@ int main(int argc, char* argv[]) LibraryPtr library = LibraryFactory::Libraries().at(0); MainLayout mainLayout(tp, library); - LibraryLayout libraryLayout(library); + LibraryLayout libraryLayout(tp, library); mainLayout.Hide(); libraryLayout.Hide(); @@ -234,6 +238,9 @@ int main(int argc, char* argv[]) else if (state.input) { state.input->WriteChar(ch); } + else if (state.keyHandler) { + state.keyHandler->KeyPress(ch); + } Window::WriteToScreen(); WindowMessageQueue::Instance().Dispatch(); diff --git a/src/musikbox/TrackListView.cpp b/src/musikbox/TrackListView.cpp index 73d0cb229..15dbcd6b0 100755 --- a/src/musikbox/TrackListView.cpp +++ b/src/musikbox/TrackListView.cpp @@ -6,17 +6,23 @@ #include "TrackListView.h" #include "IWindowMessage.h" +#include + #include #include + #include #define WINDOW_MESSAGE_QUERY_COMPLETED 1002 using musik::core::IQuery; +using musik::core::audio::Transport; +using namespace musik::core::library::constants; -TrackListView::TrackListView(LibraryPtr library, IWindow *parent) +TrackListView::TrackListView(Transport& transport, LibraryPtr library, IWindow *parent) : ListWindow(parent) { this->SetContentColor(BOX_COLOR_WHITE_ON_BLACK); + this->transport = &transport; this->library = library; this->library->QueryCompleted.connect(this, &TrackListView::OnQueryCompleted); this->adapter = new Adapter(*this); @@ -37,6 +43,18 @@ void TrackListView::OnQueryCompleted(QueryPtr query) { } } +void TrackListView::KeyPress(int64 ch) { + if (ch == 10) { /* return */ + size_t selected = this->GetSelectedIndex(); + if (this->metadata->size() > selected) { + TrackPtr track = this->metadata->at(selected); + std::string fn = track->GetValue(Track::FILENAME); + this->transport->Stop(); + this->transport->Start(fn); + } + } +} + void TrackListView::ProcessMessage(IWindowMessage &message) { if (message.MessageType() == WINDOW_MESSAGE_QUERY_COMPLETED) { if (this->query && this->query->GetStatus() == IQuery::Finished) { diff --git a/src/musikbox/TrackListView.h b/src/musikbox/TrackListView.h index da11df5c3..49bcb721b 100755 --- a/src/musikbox/TrackListView.h +++ b/src/musikbox/TrackListView.h @@ -5,18 +5,23 @@ #include "ListWindow.h" #include "TrackListViewQuery.h" #include "ScrollAdapterBase.h" +#include "IKeyHandler.h" +#include #include using musik::core::QueryPtr; using musik::core::LibraryPtr; +using musik::core::audio::Transport; -class TrackListView : public ListWindow, public sigslot::has_slots<> { +class TrackListView : public ListWindow, public IKeyHandler, public sigslot::has_slots<> { public: - TrackListView(LibraryPtr library, IWindow *parent = NULL); + TrackListView(Transport& transport, LibraryPtr library, IWindow *parent = NULL); ~TrackListView(); virtual void ProcessMessage(IWindowMessage &message); + virtual void KeyPress(int64 ch); + void Requery(const std::string& column, DBID id); protected: @@ -39,5 +44,6 @@ class TrackListView : public ListWindow, public sigslot::has_slots<> { std::shared_ptr query; std::shared_ptr> metadata; Adapter* adapter; + Transport* transport; LibraryPtr library; }; \ No newline at end of file diff --git a/src/musikbox/TrackListViewQuery.cpp b/src/musikbox/TrackListViewQuery.cpp index 478a4f2a1..67ba61f89 100755 --- a/src/musikbox/TrackListViewQuery.cpp +++ b/src/musikbox/TrackListViewQuery.cpp @@ -4,12 +4,14 @@ #include "TrackListViewQuery.h" #include +#include #include using musik::core::db::Statement; using musik::core::db::Row; using musik::core::TrackPtr; using musik::core::LibraryTrack; +using namespace musik::core::library::constants; TrackListViewQuery::TrackListViewQuery(LibraryPtr library, const std::string& column, DBID id) { this->library = library; @@ -31,21 +33,30 @@ bool TrackListViewQuery::OnRun(Connection& db) { result.reset(new std::vector()); } - std::string query = boost::str( - boost::format( - "SELECT DISTINCT tracks.id, tracks.track, tracks.title " - "FROM tracks " - "WHERE %1%=? " - "ORDER BY tracks.track;") % this->column); + std::string query = boost::str(boost::format( + "SELECT DISTINCT t.track, t.bpm, t.duration, t.filesize, t.year, t.title, t.filename, t.thumbnail_id, al.name AS album, gn.name AS genre, ar.name AS artist, t.filetime, t.sort_order1 " \ + "FROM tracks t, paths p, albums al, artists ar, genres gn " \ + "WHERE t.%s=? AND t.album_id=al.id AND t.visual_genre_id=gn.id AND t.visual_artist_id=ar.id") % this->column); + + Statement trackQuery(query.c_str(), db); - Statement stmt(query.c_str(), db); - stmt.BindInt(0, this->id); + trackQuery.BindInt(0, this->id); + while (trackQuery.Step() == Row) { + TrackPtr track = TrackPtr(new LibraryTrack(this->id, this->library)); + + track->SetValue(Track::TRACK_NUM, trackQuery.ColumnText(0)); + track->SetValue(Track::BPM, trackQuery.ColumnText(1)); + track->SetValue(Track::DURATION, trackQuery.ColumnText(2)); + track->SetValue(Track::FILESIZE, trackQuery.ColumnText(3)); + track->SetValue(Track::YEAR, trackQuery.ColumnText(4)); + track->SetValue(Track::TITLE, trackQuery.ColumnText(5)); + track->SetValue(Track::FILENAME, trackQuery.ColumnText(6)); + track->SetValue(Track::THUMBNAIL_ID, trackQuery.ColumnText(7)); + track->SetValue(Track::ALBUM_ID, trackQuery.ColumnText(8)); + track->SetValue(Track::DISPLAY_GENRE_ID, trackQuery.ColumnText(9)); + track->SetValue(Track::DISPLAY_ARTIST_ID, trackQuery.ColumnText(10)); + track->SetValue(Track::FILETIME, trackQuery.ColumnText(11)); - while (stmt.Step() == Row) { - DBID id = stmt.ColumnInt64(0); - TrackPtr track = TrackPtr(new LibraryTrack(id, this->library)); - track->SetValue("track", boost::lexical_cast(stmt.ColumnInt(1)).c_str()); - track->SetValue("title", stmt.ColumnText(2)); result->push_back(track); } diff --git a/src/musikbox/TrackListViewQuery.h b/src/musikbox/TrackListViewQuery.h index 73d60992c..bbddb839e 100755 --- a/src/musikbox/TrackListViewQuery.h +++ b/src/musikbox/TrackListViewQuery.h @@ -16,7 +16,6 @@ class TrackListViewQuery : public QueryBase { TrackListViewQuery(LibraryPtr library, const std::string& column, DBID id); ~TrackListViewQuery(); - std::string Name() { return "TrackListViewQuery"; } diff --git a/src/musikbox/musikbox.vcxproj b/src/musikbox/musikbox.vcxproj index a32d9f322..cce2d8dab 100755 --- a/src/musikbox/musikbox.vcxproj +++ b/src/musikbox/musikbox.vcxproj @@ -151,6 +151,7 @@ + diff --git a/src/musikbox/musikbox.vcxproj.filters b/src/musikbox/musikbox.vcxproj.filters index 2a2575eee..3ffb37734 100755 --- a/src/musikbox/musikbox.vcxproj.filters +++ b/src/musikbox/musikbox.vcxproj.filters @@ -177,6 +177,9 @@ curses\window + + curses +