Archive / / / / / Library.cc
2008-10-21 13:56:18 UTC
previous next
/* Echo Media Player * Copyright (C) 2008 Shane O'Connell * * [ The original file includes a copyright header in this location describing * the file as being released under the terms of the GNU General Public * License. It has been removed in order to display the file as part of the * archive. ] */ #include "Library.h" #include "Database.h" #include <mpegfile.h> #include <tag.h> #include <cassert> #include <iostream> using namespace std; Library::Library(long long library_id, const Glib::ustring& name, const Glib::ustring& icon) : db(*Database::m_instance), m_library_id(library_id), m_name(name), m_icon(icon) { assert(Database::m_instance); SQLstmt stmt; db.prepare(stmt, Glib::ustring::compose( "SELECT COUNT(*) FROM LibraryTracks " "WHERE LibraryID = %1", m_library_id)); bool is_row = stmt.step(); assert(is_row); m_tracks.reserve(stmt.get_column_int(0)); db.prepare(stmt, Glib::ustring::compose( "SELECT Artists.ArtistID, Albums.AlbumID, TrackName, TrackNumber, TrackRating, TrackURI" " FROM LibraryTracks, Tracks, Artists, Albums" " WHERE LibraryTracks.TrackID = Tracks.TrackID" " AND Tracks.AlbumID = Albums.AlbumID" " AND Albums.ArtistID = Artists.ArtistID" " AND LibraryTracks.LibraryID = %1" " ORDER BY ArtistName, AlbumReleaseDate, AlbumName, TrackNumber", m_library_id)); while (stmt.step()) { StringRef album = db.get_album_from_id(stmt.get_column_int(1)); StringRef artist = db.get_artist_from_id(stmt.get_column_int(0)); m_tracks.push_back(TrackRef(new Track( stmt.get_column_text(5), // URI stmt.get_column_text(2), // Name artist, album, stmt.get_column_int(3) // Track number ))); } } TrackRef Library::get_track(int index) const { assert(index >= 0); assert(index < (int)m_tracks.size()); return m_tracks[index]; } void Library::refresh() { SQLstmt stmt; db.prepare(stmt, Glib::ustring::compose( "SELECT LibraryURI FROM Libraries " "WHERE LibraryID = %1", m_library_id)); bool is_row = stmt.step(); assert(is_row); std::string base_uri = stmt.get_column_text(0); refresh_from_uri(base_uri); // TODO signal stuff has been updated } void Library::refresh_from_uri(const std::string& uri) { while (Glib::MainContext::get_default()->pending()) Glib::MainContext::get_default()->iteration(false); try { Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(uri); Glib::RefPtr<Gio::FileInfo> file_info = file->query_info( "standard::type,standard::fast-content-type"); if (file_info->get_file_type() == Gio::FILE_TYPE_DIRECTORY) { signal_refesh_pulse().emit(file->get_parse_name()); Glib::RefPtr<Gio::FileEnumerator> children = file->enumerate_children( "standard::name,standard::display-name"); Glib::RefPtr<Gio::FileInfo> child; while (child = children->next_file()) { if (child->get_display_name().size() >= 1 && child->get_display_name().at(0) != '.') { // TODO add some kind of protection against infinitely recursive directories refresh_from_uri(file->get_child(child->get_name())->get_uri()); } } } else { string content_type = file_info->get_attribute_string("standard::fast-content-type"); if (file->is_native() && content_type == "audio/mpeg") // MP3 { // TODO trim whitespace at either side of the mp3 title/artist/album etc. TagLib::MPEG::File file_tags(file->get_path().c_str()); TrackRef track = TrackRef(new Track( uri, file_tags.tag()->title().to8Bit(true), file_tags.tag()->artist().to8Bit(true), file_tags.tag()->album().to8Bit(true), file_tags.tag()->track())); // TODO make sure tags are okay before accepting // if they aren't okay use the filename as the title update_refreshed_track(track); } } } catch (Gio::Error e) { // TODO show error message to user when this happens } } void Library::update_refreshed_track(TrackRef track) { long long artist_id = db.get_artist_id(track->get_artist()); long long album_id = db.get_album_id(artist_id, track->get_album()); long long track_id = db.get_track_id(track->get_uri()); // TODO can we just insert a track into Tracks without checking if it's there first // by using the UNIQUE contraint on TrackURI with a REPLACE conflict clause? // The only problem is if that changes the TrackID or just uses the one the original had if (track_id == -1) { /* db.run("CREATE TABLE IF NOT EXISTS Tracks (" " TrackID INTEGER PRIMARY KEY," " AlbumID INTEGER," " TrackName TEXT," " TrackNumber INTEGER," " TrackRating INTEGER," " TrackURI TEXT" ")"); */ SQLstmt stmt; db.prepare(stmt, "INSERT INTO Tracks (AlbumID, TrackName, TrackNumber, TrackURI) " "VALUES(?, ?, ?, ?)"); stmt.bind(1, album_id); stmt.bind(2, track->get_title()); stmt.bind(3, track->get_track_number()); stmt.bind(4, track->get_uri()); stmt.step(); track_id = db.last_rowid(); } else { SQLstmt stmt; db.prepare(stmt, "UPDATE Tracks SET " "AlbumID = ?, TrackName = ?, TrackNumber = ? WHERE TrackID = ?"); stmt.bind(1, album_id); stmt.bind(2, track->get_title()); stmt.bind(3, track->get_track_number()); stmt.bind(4, track_id); stmt.step(); } /* db.run("CREATE TABLE IF NOT EXISTS LibraryTracks (" " LibraryID INTEGER," " TrackID INTEGER," " UNIQUE(LibraryID, TrackID) REPLACE" ")");*/ //long long track_id = db.last_rowid(); SQLstmt stmt; db.prepare(stmt, "INSERT INTO LibraryTracks (LibraryID, TrackID) VALUES(?, ?)"); stmt.bind(1, m_library_id); stmt.bind(2, track_id); stmt.step(); }