24
24
namespace Unity.MusicLens {
26
public errordomain DatabaseError {
26
public errordomain DatabaseError {
31
* Abstracts talking to the banshee collection database
33
public class BansheeCollection : Object
35
private const int MAX_RESULTS = 100;
39
public BansheeCollection () throws DatabaseError
41
int rc = Database.open ("%s/banshee-1/banshee.db".printf (Environment.get_user_config_dir ()), out db);
43
if (rc != Sqlite.OK) {
44
printerr ("failed to open db, %d, %s\n", rc, db.errmsg ());
45
throw new DatabaseError.FAILED_TO_OPEN ("Failed to open banshee database");
50
* Performs a search on the banshee db
52
public void search (LensSearch? search,
53
Dee.Model results_model,
54
GLib.List<FilterParser>? filters = null,
57
const int TRACK_TITLE = 0;
58
const int TRACK_URI = 1;
59
const int TRACK_MIMETYPE = 2;
60
const int ALBUM_TITLE = 3;
61
const int ARTIST_NAME = 4;
66
// use a tree set to ensure we don't duplicate albums
67
TreeSet<string> albums = new TreeSet<string> ();
68
string filters_sql = build_sql_from_filters (filters);
70
// BUILD SQL STATEMENT
71
string sql = """SELECT CoreTracks.Title, CoreTracks.Uri, CoreTracks.MimeType, CoreAlbums.Title, CoreArtists.Name
73
CROSS JOIN CoreArtists, CoreAlbums
74
WHERE CoreArtists.ArtistID = CoreTracks.ArtistID AND CoreAlbums.AlbumID = CoreTracks.AlbumID
75
AND CoreTracks.PrimarySourceID =1
76
AND ((CoreArtists.NameLowered LIKE '%%%s%%' ESCAPE '\'
77
AND CoreArtists.NameLowered IS NOT NULL)
78
OR (CoreAlbums.TitleLowered LIKE '%%%s%%' ESCAPE '\'
79
AND CoreAlbums.TitleLowered IS NOT NULL)
80
OR (CoreTracks.TitleLowered LIKE '%%%s%%' ESCAPE '\'
81
AND CoreTracks.TitleLowered IS NOT NULL))
31
* Abstracts talking to the banshee collection database
33
public class BansheeCollection : Object
35
private const int MAX_RESULTS = 100000;
39
public BansheeCollection () throws DatabaseError
41
int rc = Database.open ("%s/banshee-1/banshee.db".printf (Environment.get_user_config_dir ()), out db);
43
if (rc != Sqlite.OK) {
44
printerr ("failed to open db, %d, %s\n", rc, db.errmsg ());
45
throw new DatabaseError.FAILED_TO_OPEN ("Failed to open banshee database");
50
* Performs a search on the banshee db
52
public void search (LensSearch? search,
53
Dee.Model results_model,
54
GLib.List<FilterParser>? filters = null,
57
const int TRACK_TITLE = 0;
58
const int TRACK_URI = 1;
59
const int TRACK_MIMETYPE = 2;
60
const int ALBUM_TITLE = 3;
61
const int ALBUM_ARTWORKID = 4;
62
const int ARTIST_NAME = 5;
66
string album_art_dir = "%s/media-art/".printf (Environment.get_user_cache_dir ());
68
// use a tree set to ensure we don't duplicate albums
69
TreeSet<string> albums = new TreeSet<string> ();
70
string filters_sql = build_sql_from_filters (filters);
72
// BUILD SQL STATEMENT
73
string sql = """SELECT CoreTracks.Title, CoreTracks.Uri, CoreTracks.MimeType, CoreAlbums.Title, CoreAlbums.ArtworkID, CoreArtists.Name FROM CoreTracks
74
CROSS JOIN CoreArtists, CoreAlbums
75
WHERE CoreArtists.ArtistID = CoreTracks.ArtistID
76
AND CoreAlbums.AlbumID = CoreTracks.AlbumID
77
AND CoreTracks.PrimarySourceID = 1
78
AND ((CoreArtists.NameLowered LIKE '%%%s%%' ESCAPE '\'
79
AND CoreArtists.NameLowered IS NOT NULL)
80
OR (CoreAlbums.TitleLowered LIKE '%%%s%%' ESCAPE '\'
81
AND CoreAlbums.TitleLowered IS NOT NULL)
82
OR (CoreTracks.TitleLowered LIKE '%%%s%%' ESCAPE '\'
83
AND CoreTracks.TitleLowered IS NOT NULL)
83
ORDER BY CoreTracks.Score DESC
84
LIMIT 0, %d;""".printf (search.search_string,
88
max_results == -1 ? MAX_RESULTS : max_results);
90
rc = execute_sql (sql, out stmt);
100
// translate the raw sql row into something we can use
101
Track track = new Track ();
102
track.Title = stmt.column_text (TRACK_TITLE);
103
track.Artist = stmt.column_text (ARTIST_NAME);
104
track.Uri = stmt.column_text (TRACK_URI);
105
track.MimeType = stmt.column_text (TRACK_MIMETYPE);
107
Album album = new Album ();
108
album.Title = stmt.column_text (ALBUM_TITLE);
109
album.Artist = stmt.column_text (ARTIST_NAME);
111
results_model.append (track.Uri, "audio-x-generic", 0, track.MimeType, track.Title, track.Artist, track.Uri);
113
if (albums.add (album.Artist + album.Title)) {
114
results_model.append ("album://%s/%s".printf (album.Artist, album.Title), "audio-x-generic", 1,
115
"audio-x-generic", album.Title, album.Artist);
122
} while (rc == Sqlite.ROW);
126
* returns an array like {uri://, uri://, ...}
128
public string[] get_track_uris (Album album)
130
const int URI_COLUMN = 0;
136
"SELECT CoreTracks.Uri
138
CROSS JOIN CoreAlbums, CoreArtists
139
WHERE CoreArtists.ArtistID = CoreTracks.ArtistID
140
AND CoreAlbums.AlbumID = CoreTracks.AlbumID
141
AND CoreAlbums.Title IS '%s'
142
AND CoreArtists.Name IS '%s'
143
AND CoreTracks.URI IS NOT NULL
144
ORDER BY CoreTracks.TrackNumber ASC"
145
.printf (album.Title, album.Artist);
147
rc = execute_sql (sql, out stmt);
149
ArrayList<string> uris = new ArrayList<string> ();
157
debug ("got a row that looks like %s\n", stmt.column_text (URI_COLUMN));
158
uris.add (stmt.column_text (URI_COLUMN));
163
} while (rc == Sqlite.ROW);
165
return uris.to_array ();
86
ORDER BY CoreTracks.Score DESC
87
LIMIT 0, %d;""".printf (search.search_string,
91
max_results == -1 ? MAX_RESULTS : max_results);
93
rc = execute_sql (sql, out stmt);
103
// translate the raw sql row into something we can use
104
string artwork_path = "%s/%s.jpg".printf (album_art_dir, stmt.column_text (ALBUM_ARTWORKID));
105
File artwork_file = File.new_for_path (artwork_path);
106
if (!artwork_file.query_exists ())
107
artwork_path = "audio-x-generic";
109
Track track = new Track ();
110
track.Title = stmt.column_text (TRACK_TITLE);
111
track.Artist = stmt.column_text (ARTIST_NAME);
112
track.Uri = stmt.column_text (TRACK_URI);
113
track.MimeType = stmt.column_text (TRACK_MIMETYPE);
115
Album album = new Album ();
116
album.Title = stmt.column_text (ALBUM_TITLE);
117
album.Artist = stmt.column_text (ARTIST_NAME);
119
results_model.append (track.Uri, artwork_path, 0, track.MimeType, track.Title, track.Artist);
121
if (albums.add (album.Artist + album.Title)) {
122
results_model.append ("album://%s/%s".printf (album.Artist, album.Title), artwork_path, 1,
123
"audio-x-generic", album.Title, album.Artist);
130
} while (rc == Sqlite.ROW);
134
* returns an array like {uri://, uri://, ...}
136
public string[] get_track_uris (Album album)
138
const int URI_COLUMN = 0;
143
string sql = "SELECT CoreTracks.Uri
145
CROSS JOIN CoreAlbums, CoreArtists
146
WHERE CoreArtists.ArtistID = CoreTracks.ArtistID
147
AND CoreAlbums.AlbumID = CoreTracks.AlbumID
148
AND CoreAlbums.Title IS '%s'
149
AND CoreArtists.Name IS '%s'
150
AND CoreTracks.URI IS NOT NULL
151
ORDER BY CoreTracks.TrackNumber ASC".printf (album.Title, album.Artist);
153
rc = execute_sql (sql, out stmt);
155
ArrayList<string> uris = new ArrayList<string> ();
163
debug ("got a row that looks like %s\n", stmt.column_text (URI_COLUMN));
164
uris.add (stmt.column_text (URI_COLUMN));
169
} while (rc == Sqlite.ROW);
171
return uris.to_array ();
169
175
* returns a string like "AND (Table.Column IS filter OR Table.OtherCol IS filter2)
170
176
* AND (Table.OtherColAgain IS AnotherFilter)"
172
private string build_sql_from_filters (GLib.List<FilterParser> filters)
174
if (filters == null || filters.length () == 0)
178
private string build_sql_from_filters (GLib.List<FilterParser> filters)
180
if (filters == null || filters.length () == 0)
177
183
var builder = new StringBuilder ();
179
185
foreach (FilterParser parser in filters)