1 #include <QtDebug>
2 #include <QStandardPaths>
3 #include <QSettings>
4 #include <QFile>
5 #include <QFileInfo>
6 #include <QSqlError>
7
8 #include "library/queryutil.h"
9 #include "library/banshee/bansheedbconnection.h"
10 #include "util/performancetimer.h"
11
BansheeDbConnection()12 BansheeDbConnection::BansheeDbConnection() {
13 }
14
~BansheeDbConnection()15 BansheeDbConnection::~BansheeDbConnection() {
16 qDebug() << "Close Banshee database";
17 m_database.close();
18 }
19
open(const QString & databaseFile)20 bool BansheeDbConnection::open(const QString& databaseFile) {
21 m_database = QSqlDatabase::addDatabase("QSQLITE", "BANSHE_DB_CONNECTION");
22 m_database.setHostName("localhost");
23 m_database.setDatabaseName(databaseFile);
24 m_database.setConnectOptions("SQLITE_OPEN_READONLY");
25
26 //Open the database connection in this thread.
27 if (!m_database.open()) {
28 m_database.setConnectOptions(); // clear options
29 qWarning() << "Failed to open Banshee database." << m_database.lastError();
30 return false;
31 } else {
32 // TODO(DSC): Verify schema
33 // Banshee Schema file:
34 // https://git.gnome.org/browse/banshee/tree/src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs
35 // "Grouping" was introduced in schema 19 2008-08-19
36 // Tested from 39 to 45
37 qDebug() << "Successful opened Banshee database";
38 return true;
39 }
40 }
41
getSchemaVersion()42 int BansheeDbConnection::getSchemaVersion() {
43 QSqlQuery query(m_database);
44 query.prepare("SELECT Value FROM CoreConfiguration WHERE Key = \"DatabaseVersion\"");
45
46 if (query.exec()) {
47 if (query.next()) {
48 return query.value(0).toInt();
49 }
50 } else {
51 LOG_FAILED_QUERY(query);
52 }
53 return -1;
54 }
55
getPlaylists()56 QList<BansheeDbConnection::Playlist> BansheeDbConnection::getPlaylists() {
57
58 QList<BansheeDbConnection::Playlist> list;
59 BansheeDbConnection::Playlist playlist;
60
61 QSqlQuery query(m_database);
62 query.prepare("SELECT PlaylistID, Name FROM CorePlaylists ORDER By Name");
63
64 if (query.exec()) {
65 while (query.next()) {
66 playlist.playlistId = query.value(0).toString();
67 playlist.name = query.value(1).toString();
68 list.append(playlist);
69 }
70 } else {
71 LOG_FAILED_QUERY(query);
72 }
73 return list;
74 }
75
getPlaylistEntries(int playlistId)76 QList<BansheeDbConnection::PlaylistEntry> BansheeDbConnection::getPlaylistEntries(int playlistId) {
77
78 PerformanceTimer time;
79 time.start();
80
81 QList<BansheeDbConnection::PlaylistEntry> list;
82 BansheeDbConnection::PlaylistEntry entry;
83
84 QSqlQuery query(m_database);
85 query.setForwardOnly(true); // Saves about 50% time
86
87 QString queryString;
88
89 if (playlistId == 0) {
90 // Create Master Playlist
91 queryString = QString(
92 "SELECT "
93 "CoreTracks.TrackID, " // 0
94 "CoreTracks.TrackID, " // 1
95 "CoreTracks.Title, " // 2
96 "CoreTracks.Uri, " // 3
97 "CoreTracks.Duration, " // 4
98 "CoreTracks.ArtistID, " // 5
99 "CoreArtists.Name, " // 6
100 "CoreTracks.Year, " // 7
101 "CoreTracks.AlbumID, " // 8
102 "CoreAlbums.Title, " // 9
103 "CoreTracks.Rating, " // 10
104 "CoreTracks.Genre, " // 11
105 "CoreTracks.TrackNumber, " // 12
106 "CoreTracks.DateAddedStamp, " // 13
107 "CoreTracks.BPM, " // 14
108 "CoreTracks.BitRate, " // 15
109 "CoreTracks.Comment, " // 16
110 "CoreTracks.PlayCount, " // 17
111 "CoreTracks.Composer, " // 18
112 "CoreTracks.Grouping, " // 19
113 "CoreAlbums.ArtistID, " // 20
114 "AlbumArtists.Name " // 21
115 "FROM CoreTracks "
116 "INNER JOIN CoreArtists ON CoreArtists.ArtistID = CoreTracks.ArtistID "
117 "INNER JOIN CoreArtists AlbumArtists ON AlbumArtists.ArtistID = CoreAlbums.ArtistID "
118 "INNER JOIN CoreAlbums ON CoreAlbums.AlbumID = CoreTracks.AlbumID ");
119 } else {
120 // SELECT playlist from CorePlaylistEntries
121 queryString = QString(
122 "SELECT "
123 "CorePlaylistEntries.TrackID, " // 0
124 "CorePlaylistEntries.ViewOrder, " // 1
125 "CoreTracks.Title, " // 2
126 "CoreTracks.Uri, " // 3
127 "CoreTracks.Duration, " // 4
128 "CoreTracks.ArtistID, " // 5
129 "CoreArtists.Name, " // 6
130 "CoreTracks.Year, " // 7
131 "CoreTracks.AlbumID, " // 8
132 "CoreAlbums.Title, " // 9
133 "CoreTracks.Rating, " // 10
134 "CoreTracks.Genre, " // 11
135 "CoreTracks.TrackNumber, " // 12
136 "CoreTracks.DateAddedStamp, " // 13
137 "CoreTracks.BPM, " // 14
138 "CoreTracks.BitRate, " // 15
139 "CoreTracks.Comment, " // 16
140 "CoreTracks.PlayCount, " // 17
141 "CoreTracks.Composer, " // 18
142 "CoreTracks.Grouping, " // 19
143 "CoreAlbums.ArtistID, " // 20
144 "AlbumArtists.Name " // 21
145 "FROM CorePlaylistEntries "
146 "INNER JOIN CoreTracks ON CoreTracks.TrackID = CorePlaylistEntries.TrackID "
147 "INNER JOIN CoreArtists ON CoreArtists.ArtistID = CoreTracks.ArtistID "
148 "INNER JOIN CoreArtists AlbumArtists ON AlbumArtists.ArtistID = CoreAlbums.ArtistID "
149 "INNER JOIN CoreAlbums ON CoreAlbums.AlbumID = CoreTracks.AlbumID "
150 "WHERE CorePlaylistEntries.PlaylistID = %1")
151 .arg(playlistId);
152 }
153
154 query.prepare(queryString);
155
156 if (query.exec()) {
157 while (query.next()) {
158 entry.trackId = query.value(0).toInt();
159 entry.viewOrder = query.value(1).toInt();
160 m_trackMap[entry.trackId].title = query.value(2).toString();
161 m_trackMap[entry.trackId].uri = QUrl::fromEncoded(query.value(3).toByteArray(), QUrl::StrictMode);
162 m_trackMap[entry.trackId].duration = query.value(4).toInt();
163
164 int artistId = query.value(5).toInt();
165 m_artistMap[artistId].name = query.value(6).toString();
166 m_trackMap[entry.trackId].year = query.value(7).toInt();
167 int albumId = query.value(8).toInt();
168 m_albumMap[albumId].title = query.value(9).toString();
169 int albumArtistId = query.value(20).toInt();
170 m_artistMap[albumArtistId].name = query.value(21).toString();
171 m_trackMap[entry.trackId].rating = query.value(10).toInt();
172 m_trackMap[entry.trackId].genre = query.value(11).toString();
173 m_trackMap[entry.trackId].grouping = query.value(19).toString();
174 m_trackMap[entry.trackId].tracknumber = query.value(12).toInt();
175 m_trackMap[entry.trackId].dateadded = query.value(13).toInt();
176 m_trackMap[entry.trackId].bpm = query.value(14).toInt();
177 m_trackMap[entry.trackId].bitrate = query.value(15).toInt();
178 m_trackMap[entry.trackId].comment = query.value(16).toString();
179 m_trackMap[entry.trackId].playcount = query.value(17).toInt();
180 m_trackMap[entry.trackId].composer = query.value(18).toString();
181
182 entry.pTrack = &m_trackMap[entry.trackId];
183 entry.pArtist = &m_artistMap[artistId];
184 entry.pAlbum = &m_albumMap[albumId];
185 entry.pAlbumArtist = &m_artistMap[albumArtistId];
186 list.append(entry);
187 }
188 } else {
189 LOG_FAILED_QUERY(query);
190 }
191
192 qDebug() << "BansheeDbConnection::getPlaylistEntries(), took"
193 << time.elapsed().debugMillisWithUnit();
194
195 return list;
196 }
197
198 // static
getDatabaseFile()199 QString BansheeDbConnection::getDatabaseFile() {
200
201 QString dbfile;
202
203 // Banshee Application Data Path
204 // on Windows - "%APPDATA%\banshee-1" ("<Drive>:\Documents and Settings\<login>\<Application Data>\banshee-1")
205 // on Unix and Mac OS X - "$HOME/.config/banshee-1"
206
207 QSettings ini(QSettings::IniFormat, QSettings::UserScope,
208 "banshee-1","banshee");
209 dbfile = QFileInfo(ini.fileName()).absolutePath();
210 dbfile += "/banshee.db";
211 if (QFile::exists(dbfile)) {
212 return dbfile;
213 }
214
215 // Legacy Banshee Application Data Path
216 QSettings ini2(QSettings::IniFormat, QSettings::UserScope,
217 "banshee","banshee");
218 dbfile = QFileInfo(ini2.fileName()).absolutePath();
219 dbfile += "/banshee.db";
220 if (QFile::exists(dbfile)) {
221 return dbfile;
222 }
223
224 // Legacy Banshee Application Data Path
225 dbfile = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
226 dbfile += "/.gnome2/banshee/banshee.db";
227 if (QFile::exists(dbfile)) {
228 return dbfile;
229 }
230
231 return QString();
232 }
233