Merge lp:~fboucault/music-app/startup_time into lp:music-app
- startup_time
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andrew Hayzen |
Approved revision: | 1020 |
Merged at revision: | 1019 |
Proposed branch: | lp:~fboucault/music-app/startup_time |
Merge into: | lp:music-app |
Diff against target: |
481 lines (+81/-76) 17 files modified
app/components/CoverGrid.qml (+5/-1) app/components/Delegates/MusicListItem.qml (+1/-1) app/components/ListItemReorderComponent.qml (+1/-0) app/components/MusicToolbar.qml (+2/-0) app/components/NowPlayingToolbar.qml (+5/-0) app/components/Walkthrough/Slide1.qml (+1/-0) app/components/Walkthrough/Slide2.qml (+1/-0) app/components/Walkthrough/Slide3.qml (+1/-0) app/components/Walkthrough/Walkthrough.qml (+2/-0) app/music-app.qml (+51/-22) app/ui/Albums.qml (+0/-10) app/ui/Artists.qml (+0/-10) app/ui/Genres.qml (+0/-10) app/ui/LibraryEmptyState.qml (+3/-0) app/ui/Playlists.qml (+0/-10) app/ui/Recent.qml (+0/-10) tests/autopilot/music_app/__init__.py (+8/-2) |
To merge this branch: | bzr merge lp:~fboucault/music-app/startup_time |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jenkins Bot | continuous-integration | Approve | |
Andrew Hayzen | Approve | ||
Review via email: mp+301057@code.launchpad.net |
Commit message
Improve startup time (by around 900ms on BQ E4.5):
- load Icons asynchronously.
- load Images asynchronously.
- load Tabs on demand.
Description of the change
Improve startup time (by around 900ms on BQ E4.5):
- load Icons asynchronously.
- load Images asynchronously.
- load Tabs on demand.
Andrew Hayzen (ahayzen) wrote : | # |
Andrew Hayzen (ahayzen) wrote : | # |
This is the super old branch from before [0], you can see the discussions we had. The preferred solution in that was to load the selected tab and then the others in async, but not unload. As the flicker was a large distraction to the user, note that the branch was on a much older codebase (before moving to GridView etc).
0 - https:/
Andrew Hayzen (ahayzen) wrote : | # |
I think the way to progress forwards with this branch is to land the async changes to images and icons. But the loading tabs on demand should be put in a separate branch and changed to load the current tab and then load the others in the background, but with no unloading.
Then when we go through our redesign, which currently changes to the way tabs are used and changes the existing tabs to head sections, we can load (and unload) the head sections on demand - as then the whole of the header won't flicker while loading.
- 1015. By Florian Boucault
-
Merged from trunk
- 1016. By Florian Boucault
-
Fixed double loading of artists page
- 1017. By Florian Boucault
-
Reduce flicker by loading tabs synchronously
- 1018. By Florian Boucault
-
Use image scaling adequately for music-app-cover.png
- 1019. By Florian Boucault
-
Nicer tabs transition by fading in art
Andrew Hayzen (ahayzen) wrote : | # |
This is now looking visually much better and the code looks good as well. I just need to run autopilot on device and then it should be good to go :-) Thanks!
Andrew Hayzen (ahayzen) wrote : | # |
Running this against autopilot on my device I get many failures related to any test that change the tab, this is one of the failures [1].
It appears that it is failing because it tried to check self.autoClose [2] *after* clicking the action, which then fails because the tab has changed and the one autopilot is looking at has been unloaded.
Either, we need to write our own helper, or we could capture StateNotFoundError errors in our switch_
So probably the best solution for now is putting a try catch in the switch_
1 - http://
2 - http://
3 - http://
- 1020. By Florian Boucault
-
Fixed autopilot failures due to disappearing popovers
Andrew Hayzen (ahayzen) wrote : | # |
Thanks for fixing those issues. LGTM, all tests 'pass' (I seem to be a getting one random failure due to the mediascanner mocking failing [also occurs on trunk so my device might just be racey]).
Sorry this took a long time to land.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) : | # |
Preview Diff
1 | === modified file 'app/components/CoverGrid.qml' |
2 | --- app/components/CoverGrid.qml 2016-03-15 02:09:37 +0000 |
3 | +++ app/components/CoverGrid.qml 2016-10-25 13:44:39 +0000 |
4 | @@ -63,7 +63,7 @@ |
5 | ? (coverGrid.covers[index].art !== undefined |
6 | ? coverGrid.covers[index].art |
7 | : "image://albumart/artist=" + coverGrid.covers[index].author + "&album=" + coverGrid.covers[index].album) |
8 | - : Qt.resolvedUrl("../graphics/music-app-cover@30.png") |
9 | + : Qt.resolvedUrl("../graphics/music-app-cover.png") |
10 | |
11 | // TODO: This should be investigated once http://pad.lv/1391368 |
12 | // is resolved. Once it is, these can either be set to |
13 | @@ -89,6 +89,10 @@ |
14 | firstSource = source |
15 | } |
16 | } |
17 | + opacity: status == Image.Ready ? 1.0 : 0.0 |
18 | + Behavior on opacity { |
19 | + UbuntuNumberAnimation {} |
20 | + } |
21 | } |
22 | } |
23 | } |
24 | |
25 | === modified file 'app/components/Delegates/MusicListItem.qml' |
26 | --- app/components/Delegates/MusicListItem.qml 2016-02-26 03:16:35 +0000 |
27 | +++ app/components/Delegates/MusicListItem.qml 2016-10-25 13:44:39 +0000 |
28 | @@ -105,7 +105,7 @@ |
29 | |
30 | onStatusChanged: { |
31 | if (status === Image.Error) { |
32 | - source = Qt.resolvedUrl("../../graphics/music-app-cover@30.png") |
33 | + source = Qt.resolvedUrl("../../graphics/music-app-cover.png") |
34 | } |
35 | } |
36 | |
37 | |
38 | === modified file 'app/components/ListItemReorderComponent.qml' |
39 | --- app/components/ListItemReorderComponent.qml 2015-08-12 23:36:44 +0000 |
40 | +++ app/components/ListItemReorderComponent.qml 2016-10-25 13:44:39 +0000 |
41 | @@ -33,6 +33,7 @@ |
42 | name: "navigation-menu" // TODO: use proper image |
43 | height: width |
44 | width: units.gu(3) |
45 | + asynchronous: true |
46 | } |
47 | |
48 | MouseArea { |
49 | |
50 | === modified file 'app/components/MusicToolbar.qml' |
51 | --- app/components/MusicToolbar.qml 2016-01-16 17:46:59 +0000 |
52 | +++ app/components/MusicToolbar.qml 2016-10-25 13:44:39 +0000 |
53 | @@ -108,6 +108,7 @@ |
54 | "media-playback-pause" : "media-playback-start" |
55 | objectName: "disabledSmallPlayShape" |
56 | width: height |
57 | + asynchronous: true |
58 | } |
59 | |
60 | /* Click to shuffle music */ |
61 | @@ -203,6 +204,7 @@ |
62 | "media-playback-pause" : "media-playback-start" |
63 | objectName: "playShape" |
64 | width: height |
65 | + asynchronous: true |
66 | } |
67 | |
68 | /* Mouse area to jump to now playing */ |
69 | |
70 | === modified file 'app/components/NowPlayingToolbar.qml' |
71 | --- app/components/NowPlayingToolbar.qml 2016-03-07 20:01:22 +0000 |
72 | +++ app/components/NowPlayingToolbar.qml 2016-10-25 13:44:39 +0000 |
73 | @@ -54,6 +54,7 @@ |
74 | name: "media-playlist-repeat" |
75 | objectName: "repeatShape" |
76 | opacity: player.repeat ? 1 : .2 |
77 | + asynchronous: true |
78 | } |
79 | } |
80 | |
81 | @@ -78,6 +79,7 @@ |
82 | name: "media-skip-backward" |
83 | objectName: "previousShape" |
84 | opacity: parent.enabled ? 1 : .2 |
85 | + asynchronous: true |
86 | } |
87 | } |
88 | |
89 | @@ -98,6 +100,7 @@ |
90 | color: parent.pressed ? UbuntuColors.blue : "white" |
91 | name: player.mediaPlayer.playbackState === MediaPlayer.PlayingState ? "media-playback-pause" : "media-playback-start" |
92 | objectName: "playShape" |
93 | + asynchronous: true |
94 | } |
95 | } |
96 | |
97 | @@ -122,6 +125,7 @@ |
98 | name: "media-skip-forward" |
99 | objectName: "forwardShape" |
100 | opacity: parent.enabled ? 1 : .2 |
101 | + asynchronous: true |
102 | } |
103 | } |
104 | |
105 | @@ -145,6 +149,7 @@ |
106 | name: "media-playlist-shuffle" |
107 | objectName: "shuffleShape" |
108 | opacity: player.shuffle ? 1 : .2 |
109 | + asynchronous: true |
110 | } |
111 | } |
112 | |
113 | |
114 | === modified file 'app/components/Walkthrough/Slide1.qml' |
115 | --- app/components/Walkthrough/Slide1.qml 2015-10-18 17:45:48 +0000 |
116 | +++ app/components/Walkthrough/Slide1.qml 2016-10-25 13:44:39 +0000 |
117 | @@ -41,6 +41,7 @@ |
118 | source: Image { |
119 | id: centerImage |
120 | source: Qt.resolvedUrl("../../graphics/music-app@30.png") |
121 | + asynchronous: true |
122 | } |
123 | |
124 | width: height |
125 | |
126 | === modified file 'app/components/Walkthrough/Slide2.qml' |
127 | --- app/components/Walkthrough/Slide2.qml 2015-08-12 23:36:44 +0000 |
128 | +++ app/components/Walkthrough/Slide2.qml 2016-10-25 13:44:39 +0000 |
129 | @@ -39,6 +39,7 @@ |
130 | height: (parent.height - bodyText.contentHeight - introductionText.height - 4*units.gu(4))/2 |
131 | fillMode: Image.PreserveAspectFit |
132 | source: Qt.resolvedUrl("../../graphics/sd_phone_icon.png") |
133 | + asynchronous: true |
134 | } |
135 | |
136 | Label { |
137 | |
138 | === modified file 'app/components/Walkthrough/Slide3.qml' |
139 | --- app/components/Walkthrough/Slide3.qml 2015-08-12 23:36:44 +0000 |
140 | +++ app/components/Walkthrough/Slide3.qml 2016-10-25 13:44:39 +0000 |
141 | @@ -39,6 +39,7 @@ |
142 | height: (parent.height - introductionText.height - finalMessage.contentHeight - 4.5*units.gu(4))/2 |
143 | fillMode: Image.PreserveAspectFit |
144 | source: Qt.resolvedUrl("../../graphics/music_download_icon.png") |
145 | + asynchronous: true |
146 | } |
147 | |
148 | Label { |
149 | |
150 | === modified file 'app/components/Walkthrough/Walkthrough.qml' |
151 | --- app/components/Walkthrough/Walkthrough.qml 2015-10-28 01:05:33 +0000 |
152 | +++ app/components/Walkthrough/Walkthrough.qml 2016-10-25 13:44:39 +0000 |
153 | @@ -171,6 +171,7 @@ |
154 | height: width |
155 | source: listView.currentIndex == index ? "../../graphics/Ellipse@27.png" : "../../graphics/Ellipse_15_opacity@27.png" |
156 | width: units.gu(1.5) |
157 | + asynchronous: true |
158 | } |
159 | } |
160 | } |
161 | @@ -187,6 +188,7 @@ |
162 | name: "chevron" |
163 | visible: listView.currentIndex !== 2 |
164 | width: height |
165 | + asynchronous: true |
166 | } |
167 | |
168 | MouseArea { |
169 | |
170 | === renamed file 'app/graphics/music-app-cover@30.png' => 'app/graphics/music-app-cover@13.png' |
171 | === modified file 'app/music-app.qml' |
172 | --- app/music-app.qml 2016-08-15 22:27:23 +0000 |
173 | +++ app/music-app.qml 2016-10-25 13:44:39 +0000 |
174 | @@ -446,10 +446,8 @@ |
175 | |
176 | // TODO: improve in refactoring to be able detect when a track is removed |
177 | // Update playlists page |
178 | - if (playlistsPage.visible) { |
179 | + if (tabs.selectedTab == playlistsTab) { |
180 | playlistModel.filterPlaylists() |
181 | - } else { |
182 | - playlistsPage.changed = true |
183 | } |
184 | } |
185 | } |
186 | @@ -587,7 +585,7 @@ |
187 | // Go back up the stack if possible |
188 | function goBack() { |
189 | // Ensure in the case that goBack is called programmatically that any dialogs are closed |
190 | - if (mainPageStack.currentMusicPage.currentDialog !== null) { |
191 | + if (mainPageStack.currentMusicPage && mainPageStack.currentMusicPage.currentDialog !== null) { |
192 | PopupUtils.close(mainPageStack.currentMusicPage.currentDialog) |
193 | } |
194 | |
195 | @@ -677,6 +675,9 @@ |
196 | } |
197 | ] |
198 | |
199 | + property bool completed: false |
200 | + Component.onCompleted: completed = true |
201 | + |
202 | onSelectedTabChanged: { |
203 | // pause loading of the models in the old tab |
204 | if (lastTab !== null && lastTab !== selectedTab) { |
205 | @@ -717,11 +718,14 @@ |
206 | id: recentTab |
207 | objectName: "recentTab" |
208 | anchors.fill: parent |
209 | - title: page.title |
210 | + title: i18n.tr("Recent") |
211 | |
212 | // Tab content begins here |
213 | - page: Recent { |
214 | - id: recentPage |
215 | + page: Loader { |
216 | + width: mainPageStack.width |
217 | + height: mainPageStack.height |
218 | + active: tabs.selectedTab == recentTab |
219 | + source: Qt.resolvedUrl("ui/Recent.qml") |
220 | } |
221 | } |
222 | } |
223 | @@ -764,11 +768,16 @@ |
224 | id: artistsTab |
225 | objectName: "artistsTab" |
226 | anchors.fill: parent |
227 | - title: page.title |
228 | + title: i18n.tr("Artists") |
229 | |
230 | // tab content |
231 | - page: Artists { |
232 | - id: artistsPage |
233 | + page: Loader { |
234 | + width: mainPageStack.width |
235 | + height: mainPageStack.height |
236 | + // condition on tabs.completed necessary to avoid QTBUG 54657 |
237 | + // https://bugreports.qt.io/browse/QTBUG-54657 |
238 | + active: tabs.completed && tabs.selectedTab == artistsTab |
239 | + source: Qt.resolvedUrl("ui/Artists.qml") |
240 | } |
241 | } |
242 | |
243 | @@ -781,11 +790,16 @@ |
244 | id: albumsTab |
245 | objectName: "albumsTab" |
246 | anchors.fill: parent |
247 | - title: page.title |
248 | + title: i18n.tr("Albums") |
249 | |
250 | // Tab content begins here |
251 | - page: Albums { |
252 | - id: albumsPage |
253 | + page: Loader { |
254 | + width: mainPageStack.width |
255 | + height: mainPageStack.height |
256 | + // condition on tabs.completed necessary to avoid QTBUG 54657 |
257 | + // https://bugreports.qt.io/browse/QTBUG-54657 |
258 | + active: tabs.completed && tabs.selectedTab == albumsTab |
259 | + source: Qt.resolvedUrl("ui/Albums.qml") |
260 | } |
261 | } |
262 | |
263 | @@ -798,11 +812,16 @@ |
264 | id: genresTab |
265 | objectName: "genresTab" |
266 | anchors.fill: parent |
267 | - title: page.title |
268 | + title: i18n.tr("Genres") |
269 | |
270 | // Tab content begins here |
271 | - page: Genres { |
272 | - id: genresPage |
273 | + page: Loader { |
274 | + width: mainPageStack.width |
275 | + height: mainPageStack.height |
276 | + // condition on tabs.completed necessary to avoid QTBUG 54657 |
277 | + // https://bugreports.qt.io/browse/QTBUG-54657 |
278 | + active: tabs.completed && tabs.selectedTab == genresTab |
279 | + source: Qt.resolvedUrl("ui/Genres.qml") |
280 | } |
281 | } |
282 | |
283 | @@ -815,11 +834,16 @@ |
284 | id: songsTab |
285 | objectName: "songsTab" |
286 | anchors.fill: parent |
287 | - title: page.title |
288 | + title: i18n.tr("Tracks") |
289 | |
290 | // Tab content begins here |
291 | - page: Songs { |
292 | - id: tracksPage |
293 | + page: Loader { |
294 | + width: mainPageStack.width |
295 | + height: mainPageStack.height |
296 | + // condition on tabs.completed necessary to avoid QTBUG 54657 |
297 | + // https://bugreports.qt.io/browse/QTBUG-54657 |
298 | + active: tabs.completed && tabs.selectedTab == songsTab |
299 | + source: Qt.resolvedUrl("ui/Songs.qml") |
300 | } |
301 | } |
302 | |
303 | @@ -832,11 +856,16 @@ |
304 | id: playlistsTab |
305 | objectName: "playlistsTab" |
306 | anchors.fill: parent |
307 | - title: page.title |
308 | + title: i18n.tr("Playlists") |
309 | |
310 | // Tab content begins here |
311 | - page: Playlists { |
312 | - id: playlistsPage |
313 | + page: Loader { |
314 | + width: mainPageStack.width |
315 | + height: mainPageStack.height |
316 | + // condition on tabs.completed necessary to avoid QTBUG 54657 |
317 | + // https://bugreports.qt.io/browse/QTBUG-54657 |
318 | + active: tabs.completed && tabs.selectedTab == playlistsTab |
319 | + source: Qt.resolvedUrl("ui/Playlists.qml") |
320 | } |
321 | } |
322 | |
323 | |
324 | === modified file 'app/ui/Albums.qml' |
325 | --- app/ui/Albums.qml 2016-03-07 20:01:22 +0000 |
326 | +++ app/ui/Albums.qml 2016-10-25 13:44:39 +0000 |
327 | @@ -44,16 +44,6 @@ |
328 | } |
329 | ] |
330 | |
331 | - // FIXME: workaround for pad.lv/1531016 (gridview juddery) |
332 | - anchors { |
333 | - bottom: parent.bottom |
334 | - fill: undefined |
335 | - left: parent.left |
336 | - top: parent.top |
337 | - } |
338 | - height: mainPageStack.height |
339 | - width: mainPageStack.width |
340 | - |
341 | // Hack for autopilot otherwise Albums appears as MusicPage |
342 | // due to bug 1341671 it is required that there is a property so that |
343 | // qml doesn't optimise using the parent type |
344 | |
345 | === modified file 'app/ui/Artists.qml' |
346 | --- app/ui/Artists.qml 2016-03-07 20:01:22 +0000 |
347 | +++ app/ui/Artists.qml 2016-10-25 13:44:39 +0000 |
348 | @@ -48,16 +48,6 @@ |
349 | } |
350 | ] |
351 | |
352 | - // FIXME: workaround for pad.lv/1531016 (gridview juddery) |
353 | - anchors { |
354 | - bottom: parent.bottom |
355 | - fill: undefined |
356 | - left: parent.left |
357 | - top: parent.top |
358 | - } |
359 | - height: mainPageStack.height |
360 | - width: mainPageStack.width |
361 | - |
362 | // Hack for autopilot otherwise Artists appears as MusicPage |
363 | // due to bug 1341671 it is required that there is a property so that |
364 | // qml doesn't optimise using the parent type |
365 | |
366 | === modified file 'app/ui/Genres.qml' |
367 | --- app/ui/Genres.qml 2016-03-07 20:01:22 +0000 |
368 | +++ app/ui/Genres.qml 2016-10-25 13:44:39 +0000 |
369 | @@ -44,16 +44,6 @@ |
370 | } |
371 | ] |
372 | |
373 | - // FIXME: workaround for pad.lv/1531016 (gridview juddery) |
374 | - anchors { |
375 | - bottom: parent.bottom |
376 | - fill: undefined |
377 | - left: parent.left |
378 | - top: parent.top |
379 | - } |
380 | - height: mainPageStack.height |
381 | - width: mainPageStack.width |
382 | - |
383 | // Hack for autopilot otherwise Albums appears as MusicPage |
384 | // due to bug 1341671 it is required that there is a property so that |
385 | // qml doesn't optimise using the parent type |
386 | |
387 | === modified file 'app/ui/LibraryEmptyState.qml' |
388 | --- app/ui/LibraryEmptyState.qml 2015-12-20 00:10:13 +0000 |
389 | +++ app/ui/LibraryEmptyState.qml 2016-10-25 13:44:39 +0000 |
390 | @@ -75,6 +75,7 @@ |
391 | height: units.gu(10) |
392 | smooth: true |
393 | source: "../graphics/music_download_icon.png" |
394 | + asynchronous: true |
395 | } |
396 | } |
397 | |
398 | @@ -93,6 +94,7 @@ |
399 | height: units.gu(6) |
400 | smooth: true |
401 | source: "../graphics/div.png" |
402 | + asynchronous: true |
403 | } |
404 | } |
405 | |
406 | @@ -106,6 +108,7 @@ |
407 | height: units.gu(7) |
408 | smooth: true |
409 | source: "../graphics/sd_phone_icon.png" |
410 | + asynchronous: true |
411 | } |
412 | } |
413 | |
414 | |
415 | === modified file 'app/ui/Playlists.qml' |
416 | --- app/ui/Playlists.qml 2016-03-07 20:01:22 +0000 |
417 | +++ app/ui/Playlists.qml 2016-10-25 13:44:39 +0000 |
418 | @@ -49,16 +49,6 @@ |
419 | } |
420 | ] |
421 | |
422 | - // FIXME: workaround for pad.lv/1531016 (gridview juddery) |
423 | - anchors { |
424 | - bottom: parent.bottom |
425 | - fill: undefined |
426 | - left: parent.left |
427 | - top: parent.top |
428 | - } |
429 | - height: mainPageStack.height |
430 | - width: mainPageStack.width |
431 | - |
432 | property bool changed: false |
433 | property bool childrenChanged: false |
434 | |
435 | |
436 | === modified file 'app/ui/Recent.qml' |
437 | --- app/ui/Recent.qml 2016-08-15 23:15:01 +0000 |
438 | +++ app/ui/Recent.qml 2016-10-25 13:44:39 +0000 |
439 | @@ -73,16 +73,6 @@ |
440 | } |
441 | title: i18n.tr("Recent") |
442 | |
443 | - // FIXME: workaround for pad.lv/1531016 (gridview juddery) |
444 | - anchors { |
445 | - bottom: parent.bottom |
446 | - fill: undefined |
447 | - left: parent.left |
448 | - top: parent.top |
449 | - } |
450 | - height: mainPageStack.height |
451 | - width: mainPageStack.width |
452 | - |
453 | property bool changed: false |
454 | property bool childrenChanged: false |
455 | |
456 | |
457 | === modified file 'tests/autopilot/music_app/__init__.py' |
458 | --- tests/autopilot/music_app/__init__.py 2016-08-15 19:56:11 +0000 |
459 | +++ tests/autopilot/music_app/__init__.py 2016-10-25 13:44:39 +0000 |
460 | @@ -9,6 +9,7 @@ |
461 | from ubuntuuitoolkit import ( |
462 | MainView, UbuntuUIToolkitCustomProxyObjectBase, UCListItem |
463 | ) |
464 | +from autopilot.introspection import dbus |
465 | |
466 | |
467 | class MusicAppException(Exception): |
468 | @@ -482,6 +483,11 @@ |
469 | |
470 | def switch_to_tab_wrapper(self, objectName): |
471 | # We use leadingActionBar instead of Tabs so create wrapper |
472 | - self.wait_select_single( |
473 | + action_bar = self.wait_select_single( |
474 | "ActionBar", objectName="tabsLeadingActionBar", visible=True, |
475 | - ).click_action_button(objectName) |
476 | + ) |
477 | + try: |
478 | + action_bar.click_action_button(objectName) |
479 | + except dbus.StateNotFoundError: |
480 | + # the popover was deleted when clicking the button |
481 | + pass |
Thank you for looking into this :-)
FYI, we had a branch to do the tabs on demand and async before, but decided against it as it caused a flicker in the GridView and the thumbnailer needed to reload all the cover art (eg going from Artists- >Albums- >Artists) . I wonder if we can make it smoother by fading the items or something? But even then, before, we preferred smoothness of changing tabs over loading performance in that case.
I'll see if I can find the branch, because what we also tried was loading the selected tab in async, and then once that has loaded, load the other tabs in the background async and then not unloading them so that there is no flicker.
Also, we know that the localstorage solution for restoring the queue on startup is slow, I'm currently resolving this upstream by fixing the load and save methods of the new Playlist component within qtubuntu-media and qtmultimedia. So don't worry about trying to speed up that part if you find it is slow :-)
Furthermore, I've found if you go Artists- >Albums- >Artists and scroll, you seem to have a double GridView in the Artists tab for some reason - I don't remember seeing this before.