~ubuntu-branches/ubuntu/oneiric/unity-lens-music/oneiric

« back to all changes in this revision

Viewing changes to src/banshee-collection.vala

  • Committer: Package Import Robot
  • Author(s): Didier Roche
  • Date: 2011-09-08 20:12:26 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: package-import@ubuntu.com-20110908201226-zpenogq93xqmwbfs
Tags: 0.1.4-0ubuntu1
* New upstream release.
  - Python PyGI support broken (LP: #844779)
* debian/control:
  - build-dep on latest libunity-dev for ABI/API break

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
namespace Unity.MusicLens {
25
25
 
26
 
        public errordomain DatabaseError {
27
 
                FAILED_TO_OPEN
28
 
        }
 
26
  public errordomain DatabaseError {
 
27
    FAILED_TO_OPEN
 
28
  }
29
29
        
30
 
        /**
31
 
         * Abstracts talking to the banshee collection database
32
 
         */
33
 
        public class BansheeCollection : Object
34
 
        {
35
 
                private const int MAX_RESULTS = 100;
36
 
 
37
 
                private Database db;
38
 
 
39
 
                public BansheeCollection () throws DatabaseError
40
 
                {
41
 
                        int rc = Database.open ("%s/banshee-1/banshee.db".printf (Environment.get_user_config_dir ()), out db);
42
 
                        
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");
46
 
                        }       
47
 
                }
48
 
 
49
 
                /**
50
 
                 * Performs a search on the banshee db
51
 
                 */
52
 
                public void search (LensSearch? search, 
53
 
                                                        Dee.Model results_model, 
54
 
                                                        GLib.List<FilterParser>? filters = null, 
55
 
                                                        int max_results = -1)
56
 
                {       
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;
62
 
 
63
 
                        int rc = 0;
64
 
                        Statement stmt;
65
 
 
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);
69
 
 
70
 
                        // BUILD SQL STATEMENT
71
 
                        string sql = """SELECT CoreTracks.Title, CoreTracks.Uri, CoreTracks.MimeType, CoreAlbums.Title, CoreArtists.Name 
72
 
                                                        FROM CoreTracks 
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))
 
30
  /**
 
31
   * Abstracts talking to the banshee collection database
 
32
   */
 
33
  public class BansheeCollection : Object
 
34
  {
 
35
    private const int MAX_RESULTS = 100000;
 
36
    
 
37
    private Database db;
 
38
 
 
39
    public BansheeCollection () throws DatabaseError
 
40
    {
 
41
      int rc = Database.open ("%s/banshee-1/banshee.db".printf (Environment.get_user_config_dir ()), out db);
 
42
      
 
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");
 
46
      } 
 
47
    }
 
48
 
 
49
    /**
 
50
     * Performs a search on the banshee db
 
51
     */
 
52
    public void search (LensSearch? search, 
 
53
                        Dee.Model results_model, 
 
54
                        GLib.List<FilterParser>? filters = null, 
 
55
                        int max_results = -1)
 
56
    {   
 
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;
 
63
 
 
64
      int rc = 0;
 
65
      Statement stmt;
 
66
      string album_art_dir = "%s/media-art/".printf (Environment.get_user_cache_dir ());
 
67
 
 
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);
 
71
 
 
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)
 
84
                                                       )
82
85
                                 %s
83
 
                            ORDER BY CoreTracks.Score DESC
84
 
                                                        LIMIT 0, %d;""".printf (search.search_string,
85
 
                                                                                                        search.search_string,
86
 
                                                                                                        search.search_string,
87
 
                                                                        filters_sql,
88
 
                                                                                                        max_results == -1 ? MAX_RESULTS : max_results);
89
 
                        
90
 
                        rc = execute_sql (sql, out stmt);
91
 
                        if (stmt == null)
92
 
                                return;
93
 
 
94
 
                        do {
95
 
                                rc = stmt.step ();
96
 
                                switch (rc) {
97
 
                                case Sqlite.DONE:
98
 
                                        break;
99
 
                                case Sqlite.ROW:
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);
106
 
 
107
 
                                        Album album = new Album ();
108
 
                                        album.Title = stmt.column_text (ALBUM_TITLE);
109
 
                                        album.Artist = stmt.column_text (ARTIST_NAME);
110
 
 
111
 
                                        results_model.append (track.Uri, "audio-x-generic", 0, track.MimeType, track.Title, track.Artist, track.Uri);
112
 
 
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);
116
 
                                        }
117
 
 
118
 
                                        break;
119
 
                                default:
120
 
                                        break;
121
 
                                }
122
 
                        } while (rc == Sqlite.ROW);
123
 
                }
124
 
 
125
 
                /**
126
 
                 * returns an array like {uri://, uri://, ...}
127
 
                 */
128
 
                public string[] get_track_uris (Album album)
129
 
                {
130
 
                        const int URI_COLUMN = 0;
131
 
                        
132
 
                        int rc;
133
 
                        Statement stmt;
134
 
 
135
 
                        string sql = 
136
 
                                "SELECT CoreTracks.Uri 
137
 
                                 FROM CoreTracks 
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);
146
 
 
147
 
                        rc = execute_sql (sql, out stmt);
148
 
                                
149
 
                        ArrayList<string> uris = new ArrayList<string> ();
150
 
 
151
 
                        do {
152
 
                                rc = stmt.step ();
153
 
                                switch (rc) {
154
 
                                case Sqlite.DONE:
155
 
                                        break;
156
 
                                case Sqlite.ROW:
157
 
                                        debug ("got a row that looks like %s\n", stmt.column_text (URI_COLUMN));
158
 
                                        uris.add (stmt.column_text (URI_COLUMN));
159
 
                                        break;
160
 
                                default:
161
 
                                        break;
162
 
                                }
163
 
                        } while (rc == Sqlite.ROW);
164
 
                        
165
 
                        return uris.to_array ();
166
 
                }
167
 
 
 
86
                      ORDER BY CoreTracks.Score DESC
 
87
                      LIMIT 0, %d;""".printf (search.search_string,
 
88
                                              search.search_string,
 
89
                                              search.search_string,
 
90
                                              filters_sql,
 
91
                                              max_results == -1 ? MAX_RESULTS : max_results);
 
92
                        
 
93
      rc = execute_sql (sql, out stmt);
 
94
      if (stmt == null)
 
95
        return;
 
96
      
 
97
      do {
 
98
        rc = stmt.step ();
 
99
        switch (rc) {
 
100
        case Sqlite.DONE:
 
101
          break;
 
102
        case Sqlite.ROW:
 
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";
 
108
 
 
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);          
 
114
          
 
115
          Album album = new Album ();
 
116
          album.Title = stmt.column_text (ALBUM_TITLE);
 
117
          album.Artist = stmt.column_text (ARTIST_NAME);
 
118
          
 
119
          results_model.append (track.Uri, artwork_path, 0, track.MimeType, track.Title, track.Artist);
 
120
          
 
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);
 
124
          }
 
125
          
 
126
          break;
 
127
        default:
 
128
          break;
 
129
        }
 
130
      } while (rc == Sqlite.ROW);
 
131
    }
 
132
 
 
133
    /**
 
134
     * returns an array like {uri://, uri://, ...}
 
135
     */
 
136
    public string[] get_track_uris (Album album)
 
137
    {
 
138
      const int URI_COLUMN = 0;
 
139
      
 
140
      int rc;
 
141
      Statement stmt;
 
142
      
 
143
      string sql = "SELECT CoreTracks.Uri 
 
144
                    FROM CoreTracks 
 
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);
 
152
 
 
153
      rc = execute_sql (sql, out stmt);
 
154
      
 
155
      ArrayList<string> uris = new ArrayList<string> ();
 
156
      
 
157
      do {
 
158
        rc = stmt.step ();
 
159
        switch (rc) {
 
160
        case Sqlite.DONE:
 
161
          break;
 
162
        case Sqlite.ROW:
 
163
          debug ("got a row that looks like %s\n", stmt.column_text (URI_COLUMN));
 
164
          uris.add (stmt.column_text (URI_COLUMN));
 
165
          break;
 
166
        default:
 
167
          break;
 
168
        }
 
169
      } while (rc == Sqlite.ROW);
 
170
      
 
171
      return uris.to_array ();
 
172
    }
 
173
    
168
174
    /**
169
175
     * returns a string like "AND (Table.Column IS filter OR Table.OtherCol IS filter2) 
170
176
     * AND (Table.OtherColAgain IS AnotherFilter)" 
171
177
     */
172
 
                private string build_sql_from_filters (GLib.List<FilterParser> filters)
173
 
                {
174
 
                  if (filters == null || filters.length () == 0)
175
 
                          return "";
176
 
 
 
178
    private string build_sql_from_filters (GLib.List<FilterParser> filters)
 
179
    {
 
180
      if (filters == null || filters.length () == 0)
 
181
        return "";
 
182
      
177
183
      var builder = new StringBuilder ();
178
184
      
179
185
      foreach (FilterParser parser in filters)
182
188
 
183
189
        if (parsed == null || parsed == "")
184
190
          continue;
185
 
 
 
191
        
186
192
        builder.append (" AND ");
187
193
        builder.append (parsed);
188
194
      }
189
195
 
190
196
      builder.append (" ");
191
197
      return builder.str;
192
 
                }
193
 
 
194
 
                private int execute_sql (string sql, out Statement stmt)
195
 
                {
196
 
                        int rc;
197
 
                        debug ("preparing to execute sql %s\n", sql);
198
 
 
199
 
                        if ((rc = db.prepare_v2 (sql, -1, out stmt, null)) == 1)
200
 
                          {
201
 
                                error ("SQL Error: %d, %s\n", rc, db.errmsg ());
 
198
    }
 
199
 
 
200
    private int execute_sql (string sql, out Statement stmt)
 
201
    {
 
202
      int rc;
 
203
      debug ("preparing to execute sql %s\n", sql);
 
204
      
 
205
      if ((rc = db.prepare_v2 (sql, -1, out stmt, null)) == 1)
 
206
        {
 
207
          error ("SQL Error: %d, %s\n", rc, db.errmsg ());
202
208
        }
203
209
      
204
210
      return rc;
205
 
                }
206
 
        }
 
211
    }
 
212
  }
207
213
}