2 * SomePlayer - An alternate music player for Maemo 5
3 * Copyright (C) 2010 Nikolay (somebody) Tischenko <niktischenko@gmail.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "dbstorage.h"
24 using namespace SomePlayer::Storage;
25 using namespace SomePlayer::DataObjects;
27 DbStorage::DbStorage(QString path) {
28 QString dbname = path+_DATABASE_NAME_;
29 db = QSqlDatabase::addDatabase("QSQLITE");
30 db.setDatabaseName(dbname);
32 // throw big exception
34 // create database structure
35 _create_database_structure();
39 void DbStorage::_prepare_queries() {
40 _get_artists_query = new QSqlQuery(db);
41 _get_artists_query->prepare("SELECT name FROM artist ORDER BY uname");
43 _get_albums_for_artist_sort_name_query = new QSqlQuery(db);
44 _get_albums_for_artist_sort_name_query->prepare("SELECT name, year FROM album WHERE artist_id in (SELECT id from artist WHERE uname = :uname) ORDER BY uname;");
46 _get_albums_for_artist_sort_year_query = new QSqlQuery(db);
47 _get_albums_for_artist_sort_year_query->prepare("SELECT name, year FROM album WHERE artist_id in (SELECT id from artist WHERE uname = :uname) ORDER BY year;");
49 _get_tracks_for_album_query = new QSqlQuery(db);
50 _get_tracks_for_album_query->prepare("SELECT id, title, source, count, length FROM tracks WHERE artist_id IN "
51 "(SELECT id FROM artist WHERE uname = :artist_uname) AND album_id IN "
52 "(SELECT id FROM album WHERE uname = :album_uname);");
54 _get_favorites_query = new QSqlQuery(db);
55 _get_favorites_query->prepare("SELECT track_id as id, title, artist, album.name as album, source, count, length FROM "
56 "(SELECT tracks.id AS track_id, artist.name AS artist, title, count, source, tracks.album_id, length FROM "
57 "tracks JOIN artist ON tracks.artist_id = artist.id) "
58 "JOIN album ON album_id = album.id WHERE track_id IN "
59 "(SELECT track_id FROM favorites);");
61 _get_most_played_query = new QSqlQuery(db);
62 _get_most_played_query->prepare("SELECT track_id as id, title, artist, album.name as album, source, count, length FROM "
63 "(SELECT tracks.id AS track_id, artist.name AS artist, title, count, source, tracks.album_id, length FROM "
64 "tracks JOIN artist ON tracks.artist_id = artist.id) "
65 "JOIN album ON album_id = album.id ORDER BY count DESC "
68 _get_never_played_query = new QSqlQuery(db);
69 _get_never_played_query->prepare("SELECT track_id as id, title, artist, album.name as album, source, count, length FROM "
70 "(SELECT tracks.id AS track_id, artist.name AS artist, title, count, source, tracks.album_id, length FROM "
71 "tracks JOIN artist ON tracks.artist_id = artist.id) "
72 "JOIN album ON album_id = album.id "
75 _get_recently_added_query = new QSqlQuery(db);
76 _get_recently_added_query->prepare("SELECT track_id as id, title, artist, album.name as album, source, count, length FROM "
77 "(SELECT tracks.id AS track_id, artist.name AS artist, title, count, source, tracks.album_id, length FROM "
78 "tracks JOIN artist ON tracks.artist_id = artist.id) "
79 "JOIN album ON album_id = album.id "
81 "(SELECT track_id FROM adding_date ORDER BY date DESC LIMIT 0, :max)");
83 _get_track_count = new QSqlQuery(db);
84 _get_track_count->prepare("SELECT count from tracks WHERE id = :id");
86 _get_track_by_source_query = new QSqlQuery(db);
87 _get_track_by_source_query->prepare("SELECT track_id AS id, title, artist, album.name AS album, source, count, length FROM "
88 "(SELECT tracks.id AS track_id, artist.name AS artist, title, count, tracks.album_id, length FROM "
89 "tracks JOIN artist ON tracks.artist_id = artist.id AND source = :source) "
90 "JOIN album ON album_id = album.id LIMIT 1");
92 _check_artist_query = new QSqlQuery(db);
93 _check_artist_query->prepare("SELECT id FROM artist WHERE uname = :uname");
95 _check_album_query = new QSqlQuery(db);
96 _check_album_query->prepare("SELECT id FROM album WHERE uname = :uname AND artist_id = :artist_id");
98 _check_track_query = new QSqlQuery(db);
99 _check_track_query->prepare("SELECT id FROM tracks WHERE source = :source");
101 _insert_artist_query = new QSqlQuery(db);
102 _insert_artist_query->prepare("INSERT INTO artist (name, uname) values (:name, :uname)");
104 _insert_album_query = new QSqlQuery(db);
105 _insert_album_query->prepare("INSERT INTO album (name, uname, artist_id, year) values (:name, :uname, :artist_id, :year)");
107 _insert_track_query = new QSqlQuery(db);
108 _insert_track_query->prepare("INSERT INTO tracks (title, utitle, artist_id, album_id, source, length) values (:title, :utitle, :artist_id, :album_id, :source, :length)");
110 _insert_date_query = new QSqlQuery(db);
111 _insert_date_query->prepare("INSERT INTO adding_date (track_id, date) values (:track_id, strftime('%s', 'now'))");
113 _insert_favorites_query = new QSqlQuery(db);
114 _insert_favorites_query->prepare("INSERT INTO favorites (track_id) values (:track_id)");
116 _update_track_count_query = new QSqlQuery(db);
117 _update_track_count_query->prepare("UPDATE tracks SET count = :count where id = :id");
119 _remove_track_query = new QSqlQuery(db);
120 _remove_track_query->prepare("DELETE FROM tracks WHERE id = :id");
123 void DbStorage::_create_database_structure() {
124 QSqlQuery *query = new QSqlQuery(db);
125 query->exec("create table artist (id integer primary key, "
129 query->exec("create table album (id integer primary key, "
130 "artist_id integer, "
134 "foreign key(artist_id) references arist(id) "
136 query->exec("create table tracks (id integer primary key, "
137 "artist_id integer, "
142 "count integer default 0, "
143 "length integer default 0, "
144 "foreign key(artist_id) references artist(id), "
145 "foreign key(album_id) references album(id) "
147 query->exec("create table favorites (track_id integer, "
148 "foreign key(track_id) references tracks(id) "
150 query->exec("create table adding_date (track_id integer, "
152 "foreign key(track_id) references tracks(id) "
156 DbStorage::~DbStorage() {
157 delete _get_albums_for_artist_sort_name_query;
158 delete _get_albums_for_artist_sort_year_query;
159 delete _get_artists_query;
160 delete _get_favorites_query;
161 delete _get_most_played_query;
162 delete _get_never_played_query;
163 delete _get_recently_added_query;
164 delete _get_tracks_for_album_query;
165 delete _get_track_by_source_query;
166 delete _check_album_query;
167 delete _check_artist_query;
168 delete _check_track_query;
169 delete _insert_album_query;
170 delete _insert_artist_query;
171 delete _insert_date_query;
172 delete _insert_track_query;
173 delete _insert_favorites_query;
174 delete _update_track_count_query;
175 delete _remove_track_query;
179 QList<QString> DbStorage::getArtists() {
180 QList<QString> artists;
181 QSqlQuery *query = _get_artists_query;
183 while (query->next()) {
184 QString name = query->value(0).toString();
185 artists.append(name);
190 QMap<QString, int> DbStorage::getAlbumsForArtist(QString artist) {
191 QMap<QString, int> albums;
193 QString sort = config.getValue("ui/albumsorting").toString();
194 QSqlQuery *query = NULL;
195 if (sort == "date") {
196 query = _get_albums_for_artist_sort_year_query;
198 query = _get_albums_for_artist_sort_name_query;
200 query->bindValue(":uname", artist.toUpper());
202 while (query->next()) {
203 QString name = query->value(0).toString();
204 albums[name] = query->value(1).toInt();
209 QList<Track> DbStorage::getTracksForAlbum(QString album, QString artist) {
211 QSqlQuery *query = _get_tracks_for_album_query;
212 query->bindValue(":artist_uname", artist.toUpper());
213 query->bindValue(":album_uname", album.toUpper());
216 while (query->next()) {
217 int id = query->value(0).toInt();
218 QString title = query->value(1).toString();
219 QString source = query->value(2).toString();
220 int count = query->value(3).toInt();
221 int length = query->value(4).toInt();
222 TrackMetadata meta (title, artist, album, length);
223 Track track(id, meta, source);
224 track.setCount(count);
225 tracks.append(track);
231 Playlist DbStorage::getFavorites() {
233 QSqlQuery *query = _get_favorites_query;
235 while(query->next()) {
236 int id = query->value(0).toInt();
237 QString title = query->value(1).toString();
238 QString artist = query->value(2).toString();
239 QString album = query->value(3).toString();
240 QString source = query->value(4).toString();
241 int count = query->value(5).toInt();
242 int length = query->value(6).toInt();
243 TrackMetadata meta(title, artist, album, length);
244 Track track(id, meta, source);
245 track.setCount(count);
246 playlist.addTrack(track);
247 playlist.setName("Favorites");
252 Playlist DbStorage::getMostPlayed() {
254 QSqlQuery *query = _get_most_played_query;
255 query->bindValue(":max", _DYNAMIC_PLAYLIST_MAX_COUNT_);
257 while (query->next()) {
258 int id = query->value(0).toInt();
259 QString title = query->value(1).toString();
260 QString artist = query->value(2).toString();
261 QString album = query->value(3).toString();
262 QString source = query->value(4).toString();
263 int count = query->value(5).toInt();
264 int length = query->value(6).toInt();
265 TrackMetadata meta(title, artist, album, length);
266 Track track(id, meta, source);
267 track.setCount(count);
268 playlist.addTrack(track);
269 playlist.setName("Most popular");
274 Playlist DbStorage::getNeverPlayed() {
276 QSqlQuery *query = _get_never_played_query;
277 query->bindValue(":max", _DYNAMIC_PLAYLIST_MAX_COUNT_);
279 while (query->next()) {
280 int id = query->value(0).toInt();
281 QString title = query->value(1).toString();
282 QString artist = query->value(2).toString();
283 QString album = query->value(3).toString();
284 QString source = query->value(4).toString();
285 int count = query->value(5).toInt();
286 int length = query->value(6).toInt();
287 TrackMetadata meta(title, artist, album, length);
288 Track track(id, meta, source);
289 track.setCount(count);
290 playlist.addTrack(track);
291 playlist.setName("Never played");
296 Playlist DbStorage::getRecentlyAdded() {
298 QSqlQuery *query = _get_recently_added_query;
299 query->bindValue(":max", _DYNAMIC_PLAYLIST_MAX_COUNT_);
301 while (query->next()) {
302 int id = query->value(0).toInt();
303 QString title = query->value(1).toString();
304 QString artist = query->value(2).toString();
305 QString album = query->value(3).toString();
306 QString source = query->value(4).toString();
307 int count = query->value(5).toInt();
308 int length = query->value(6).toInt();
309 TrackMetadata meta(title, artist, album, length);
310 Track track(id, meta, source);
311 track.setCount(count);
312 playlist.addTrack(track);
313 playlist.setName("Recently added");
318 void DbStorage::removeTrack(Track track) {
320 QSqlQuery *query = new QSqlQuery(db);
321 query->prepare("DELETE FROM tracks WHERE id = :id;");
322 query->bindValue(":id", id);
324 query->prepare("DELETE FROM favorites WHERE track_id = :id;");
325 query->bindValue(":id", id);
327 query->prepare("DELETE FROM adding_date WHERE id = :id;");
328 query->bindValue(":id", id);
332 void DbStorage::addTrack(Track track) {
333 QString title = track.metadata().title();
334 QString artist = track.metadata().artist();
335 QString album = track.metadata().album();
336 QString source = track.source();
337 int year = track.metadata().year();
338 int artist_id = _check_add_artist(artist);
339 int album_id = _check_add_album(album, artist_id, year);
340 if (artist_id == -1 || album_id == -1) {
344 QSqlQuery *query = _check_track_query;
345 query->bindValue(":source", source);
348 // already in datebase, skip
351 query = _insert_track_query;
352 query->bindValue(":title", title);
353 query->bindValue(":utitle", title.toUpper());
354 query->bindValue(":artist_id", artist_id);
355 query->bindValue(":album_id", album_id);
356 query->bindValue(":source", source);
357 query->bindValue(":length", track.metadata().length());
360 query = _check_track_query;
361 query->bindValue(":source", source);
364 int id = query->value(0).toInt();
365 query = _insert_date_query;
366 query->bindValue(":track_id", id);
380 void DbStorage::addToFavorites(Track track) {
381 QSqlQuery *query = _insert_favorites_query;
382 query->bindValue(":track_id", track.id());
386 void DbStorage::updateTrackCount(Track track) {
387 QSqlQuery *query = _get_track_count;
388 query->bindValue(":id", track.id());
391 int count = query->value(0).toInt();
392 query = _update_track_count_query;
393 query->bindValue(":count", count+1);
394 query->bindValue(":id", track.id());
399 Track DbStorage::updateTrack(Track track) {
400 QSqlQuery *query = _remove_track_query;
401 query->bindValue(":id", track.id());
403 query = _get_track_by_source_query;
404 query->bindValue(":source", track.source());
407 int id = query->value(0).toInt();
408 QString title = query->value(1).toString();
409 QString artist = query->value(2).toString();
410 QString album = query->value(3).toString();
411 QString source = query->value(4).toString();
412 int count = query->value(5).toInt();
413 int length = query->value(6).toInt();
414 TrackMetadata meta(title, artist, album, length);
415 Track ntrack(id, meta, source);
416 ntrack.setCount(count);
422 int DbStorage::_check_add_artist(QString artist) {
423 QSqlQuery *query = _check_artist_query;
424 query->bindValue(":uname", artist.toUpper());
427 int id = query->value(0).toInt();
430 query = _insert_artist_query;
431 query->bindValue(":name", artist);
432 query->bindValue(":uname", artist.toUpper());
434 return _check_add_artist(artist);
442 int DbStorage::_check_add_album(QString album, int artist_id, int year) {
443 QSqlQuery *query = _check_album_query;
444 query->bindValue(":uname", album.toUpper());
445 query->bindValue(":artist_id", artist_id);
448 int id = query->value(0).toInt();
451 query = _insert_album_query;
452 query->bindValue(":name", album);
453 query->bindValue(":uname", album.toUpper());
454 query->bindValue(":artist_id", artist_id);
455 query->bindValue(":year", year);
457 return _check_add_album(album, artist_id, year);