fossfreedom / coverart-browser

Browse your cover-art albums in Rhythmbox v2.96 - 3.0+
http://xpressubuntu.wordpress.com/
GNU General Public License v3.0
74 stars 19 forks source link

Idea: change the current loading strategy for progressive one. #44

Closed asermax closed 11 years ago

asermax commented 12 years ago

This is a long term idea that have been on my head for a while now. The current loading strategy is quite slow on my collection + machine, and I suppose it may be the same for other people too (I would really love some feedback on that, lol). It would take a big refactoring to change the current strategy, but it would be nice to use a more progressive (or is it preemptive?) strategy, that would load into the model just the needed covers.

To make the idea a little clearer, I'll give some examples:

Problems:

fossfreedom commented 12 years ago

I cant test this myself since I dont have the same size collection (and my laptop is quite good :) ...), but can we do a "quick" test stripping out the data manipulations such as coverart_album "load cover" - how much does this speed up the initial display?

As you say - maybe then look at some-sort of implementation that loads the covers according to the viewport size - and then subsequently in the background.

asermax commented 12 years ago

While implementing some other features, I got to test the loading without adding the albums to the model and the it was way faster (let's say about 10 or 15 times faster) if we also remove the cover loading, I supect an initial, limited load would be almost instantaneous no matter the collection size. The big problem I see, as I said above, is the ordering. Anyway, let's leave this one for later, when the developing is more stable, since trying to solve this while at the same time adding more features will be a little hard. When we are done implementing most of the features we intend for the plugin, I can concentrate into this one at my own time d:

jrbastien commented 11 years ago

@asermax, I hope your exams went well. I don't know if you have some availabilities now but that would be nice, if the loading could be improved. In my library (over a NAS and with more than 500 albums), I have about 15 seconds of covers shuffling before everything gets stable.

Would it be possible to keep a local database and update the sort in the background. I'm wondering how it is done with Banshee? We don't see the cover being sorted in real time.

asermax commented 11 years ago

Hihi! Most of my exams went well, all it's left are a couple of presentations next week and I'll have some time to spare d: so wait a little more and I'll try to tackle this problem since it bothers me too lol.

We do keep all the album's info in memory in an structure that we can manipulate in the way you say, but the problem lays on the slowness of the widget we use to show the album covers. If we do a full sort and re-render the view, the whole ui freezes for a noticeable time. I have some ideas I'll test later this week to try to go around that problem tho. For now, the most interesting one is using a progressive loading technique (as stated on the title of this issue), that means to only load a couple of albums (enough to fill the viewport) and dinamically load the rest as the user scrolls down. IIRC that's the way banshee used to do it (sometime). That way we can do the background sorting and the re-renderind wouldn't take so long. It would take some mayor refactoring to achieve this tho, so we'll have to evaluate other posibilities as well. I'll report through here if I make some progress :3

jrbastien commented 11 years ago

Thank you!

fossfreedom commented 11 years ago

@asermax - some notes whilst looking at this - I'll add to this as I investigate further ( so it wont make much sense until I've finished :-) )

Note 1:

coverart_album.py", line 143, in _on_notify_cover_size
    Album.update_unknown_cover(self.cover_size)
  File "/home/dad/.local/share/rhythmbox/plugins/coverart_browser/coverart_album.py", line 1236, in update_unknown_cover
    cls.UNKNOWN_COVER.resize(cover_size)
AttributeError: 'Cover' object has no attribute 'resize'

When renaming the Cover.resize method this error was thrown. Looks like the resize method is being called despite the normal album loading method. I can only surmise that when the gsettings cover_size signal is connected, _on_notify_cover_size is called automatically - seems loading and reloading methods are being called on initial startup. Suggest this may cause unnecessary excess time.

Note 2:

commenting out this signal connect:

self.connect('notify::cover-size', self._on_notify_cover_size)

then ...

def __init__(self, size, file_path=None, pixbuf=None):
        '''
        Initialises a cover, creating it's pixbuf or adapting a given one.
        Either a file path or a pixbuf should be given to it's correct
        initialization.
        '''
        if pixbuf:
            self.original = pixbuf
            self.pixbuf = pixbuf.scale_simple(size, size,
                 GdkPixbuf.InterpType.BILINEAR)
        else:
            self.original = file_path
            #self.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(file_path,
            #    size, size)
            self.pixbuf = None

commenting out the second self.pixbuf assignment as shown increases the speed of loading - but more importantly I didnt see any shuffling.

I suppose one "quick win" could be to add yet another idle method called after the model is fully populated that then creates the album cover icons. Probably the cover loading should be done respecting the sort-order chosen - that way the "flicker" will not occur.

Note 3:

I posed this Q on stackoverflow - thoughts?

asermax commented 11 years ago

I'll check out what you mentioned when I start working on this later this week foss. Sadly, I don't remember pretty well how we structured the plugin, so it'll take me some time to re-read the code and get the hang of it again xD

asermax commented 11 years ago

Just a heads up, I'm working on this, but I'm taking my time. I'm currently refactoring the album module, dividing it into more classes to make it more easy to understand and modify. I'm thinking of using a structure with a main AlbumManager (that would replace the AlbumLoader) and a couple of other helpers of managers that will each take care of a different aspect of the managment (e.g. AlbumLoader -> loads the albums and takes care of new entries or removed entries, CoverManager -> takes care of loading covers, updating covers). It currently is very unstable and it's kinda worse than before xD but I'll see if I can fix it up and make it presentable (so at least it behaves as the master branch's structure). I was thinking of uploading the changes once I'm sure it works (I don't want to upload something i will throw away later), but if you want me to put it up so you can see the progress, let me know.

Once I'm done with the refactoring, I'll go into the loading details. Gonna take your notes into account, and that answer on stackoverflow seems exaclty what we need. I'm not sure about the proxy pattern tho, since what we would need to do is a Pixbuf proxy, since that's what the view works with, not the cover itself, and idk how hard it would be to implement. Gonna look into it anyway, it's a good idea.

asermax commented 11 years ago

Note to myself: connecting the row_changed signal to update_iconview_callback is a BAD idea. It seems like that was one of the primary causes of slowness while loading covers. There haves to be a better solution to update covers (or at least a better workaround).

fossfreedom commented 11 years ago

The answer on the SO question here looks interesting,

could help - thoughts?

asermax commented 11 years ago

When resizing the view there's no problem, we can call update_iconview_callback without problem, so the current solution for that doesn't need to change for now. The problem arises when using the row-changed signal from the cover_model to trigger the update_iconview_callback. When loading the model, the row-changed signal is throwed multiple times, and the view is updated for each album added, even if it's not necesary, adding a lot of dead time. I'm working on it, I'll let you know how it goes. I think the refactoring is coming up pretty nicely now, gonna upload it soon enough.

asermax commented 11 years ago

Ok, I think this thing is ready to be uploaded d: I'm still working on adapting all the old functionality to the structure of the album module, but the basic is there, and working over the new structure seems a lot easier than modifying the old gigantic AlbumLoader. Some highlights:

I'll add anything else that I find important to the list as it comes to mind d: for now, you can check the code on the loading branch. If there's something you don't understand or think is misplaced or poorly designed, let me know.

fossfreedom commented 11 years ago

Looks good :+1:

Lets merge this - yes I know this will cause instability for a while (the stuff below), but myself/you/both can work on this over the next few days/weeks to iron out the wrinkles.

The stuff you've written above is excellent - when I'll get some time I'll add a developer wiki entry so that others can also understand the structures better - hopefully will encourage commits from others.

ok - a quick wiz through the functionality - please dont take this as criticism - just some issues that I'm sure can be quickly resolved - in no particular order:

  1. error on start:

    Traceback (most recent call last):
     File "/usr/lib/python2.7/dist-packages/gi/overrides/Gtk.py", line 348, in _full_callback
       raise AttributeError('Handler %s not found' % handler_name)
    AttributeError: Handler genre_fill_combo not found
    
  2. rating sort - adding an album or track rating doesnt resort immediately - takes effect after toggling ascending/descending button the reordering was working only when sorting by name, but that was just luck. I fixed it to work doesn't matter which sort mode is set
  3. calculated year sort doesnt work I don't know exactly what to look for - looks like other changes has fixed this :)
  4. right click and choose coverart menu option for playqueue/playlists/music source library

    Traceback (most recent call last):
     File "/home/dad/.local/share/rhythmbox/plugins/coverart_browser/coverart_browser.py", line 146, in display_covers_for_source
       self.source.reset_coverview(model)
    AttributeError: 'CoverArtBrowserSource' object has no attribute 'reset_coverview'
    
  5. Was on rating with descending - then clicked on album. The sort was changed "by album name" but it was in ascending order ... in-fact clicking around on the sort orders, the ascending/descending seems pretty random
  6. Filter by tracks seem to empty the coverart view - i.e. doesnt filter by track title
  7. Filter by track artists seems to search by track title instead the filter uses the album artist. Maybe it's because I changed the startegy to determine the album artist... check it out and let me know what you think ... ok happy.
  8. Having the toolbar on the left hand pane - shutdown RB and restart - toolbar doesnt reappear in left hand pane.
  9. Favourites threshold - right click to add to new playlist - seems to add random tracks to the playlist. I think it's fixed - yes - great :)
  10. Double click album to play:

    Traceback (most recent call last):
      File "/home/dad/.local/share/rhythmbox/plugins/coverart_browser/coverart_browser_source.py", line 787, in item_activated_callback
        self.play_selected_album()
      File "/home/dad/.local/share/rhythmbox/plugins/coverart_browser/coverart_browser_source.py", line 815, in play_selected_album
        play_queue.clear()
    AttributeError: '__main__.RBPlayQueueSource' object has no attribute 'clear'
    
asermax commented 11 years ago

Wow, that's a lot of bugs xD I knew there were still things unfinished but hadn't though it was this many. Ok, I think we should first fix all this problems and any other big issue we may encounter before merging it into master, I prefer to keep the inestability on this branch only for now. Some notes about the issues you mentioned:

The other issues I will investigate and fix, you can dive in as well. Gonna be posting the fixes over here!

EDIT: Oh btw, I removed a lot of debug strings, I was getting crazy looking for what I needed on the sea of prints. We should just keep some of them, the most importants and those that don't repeat constantly, otherwise it renders the whole log kinda useless :/ And the whole module needs new docstrings xD

EDIT 2: Gonna mark down those issues I think that are resolved on your post!

asermax commented 11 years ago

Sorry foss, but that's what I didn't want to do with the playlists :( cleaning and reloading are heavy procedures, at least on my collection. I think that we should use what's already there instead of recreating the structure (actually, the problem isn't when choosing a playlist to show in the coverview, but when going back to the base_model, since it haves to reload all the albums again). I took the liberty to make some changes and implement it as a filter (as I proposed before) and I think is working really well, with the exception that in this way, Tracks aren't filtered. I really don't have a problem with that, since the plugin is made to deal with albums, not individual tracks; but if it's a must-be, I can find another way to implement it or go back to the previous strategy.

asermax commented 11 years ago

Well, I think that's it, the branch seems a lot more stable now with lots of bugfixes. I'll clean up the settings (take out those options that doesn't make sense anymore, and merge the branch into master.

jrbastien commented 11 years ago

I don't know if it was ready yet but I updated my installation with the latest master branch and RB can no longer load the coverart plugin. Here are the logs from Ubuntu 12.10 32 bits:

jrbastien@jrbastien-Vostro-1500:~$ rhythmbox Traceback (most recent call last): File "/home/jrbastien/.local/share/rhythmbox/plugins/coverart_browser/coverart_browser.py", line 36, in from coverart_album_search import CoverAlbumSearch File "/home/jrbastien/.local/share/rhythmbox/plugins/coverart_browser/coverart_album_search.py", line 34, in import discogs_client as discogs File "/home/jrbastien/.local/share/rhythmbox/plugins/coverart_browser/discogs_client.py", line 4, in import requests ImportError: No module named requests

(rhythmbox:3562): libpeas-WARNING **: Error loading plugin 'coverart_browser'

(rhythmbox:3562): libdmapsharing-WARNING **: DACP browsing not started

(rhythmbox:3562): Gtk-CRITICAL **: gtk_builder_get_object: assertion `GTK_IS_BUILDER (builder)' failed

asermax commented 11 years ago

That problem isn't related with the changes we made here, but with the discogs album provider that foss is working on. You need to install python-requests to be able to use it (sudo apt-get install python-requests).

Btw, if you get to make it work, I would really apreciate your feedback on the overall behavior of this new approach. I'm liking it a lot more (more responsive, no shuffling), but I would like to hear what you think about it, since you probably will see things that I do not xD

jrbastien commented 11 years ago

Ok, thank you again for your prompt response. Installing python-requests fixed the issue.

My first assessment is yes, this is faster and the shuffling is gone. I will test further and let you know of any issue.

jrbastien commented 11 years ago

On Ubuntu 12.04 64 bits, I am less successful. RB does not crash but does not display any cover. I went to the usual procedure: downloading the master branch, installing and then commenting out the changed_Id string.

In the log I have an error with /dev/radio0 but that was working in the same session before the update so I suspect it was there also before.

(rhythmbox:17158): Rhythmbox-WARNING **: Could not open device /dev/radio0

Other then this, nothing else in the terminal.

fossfreedom commented 11 years ago

@jrbastien - rhythmbox v2.98 on ubuntu 12.04? i.e. the one from the webupd8 PPA? I despair with the webupd8 guys releasing that for 12.04 - it just doesnt work with python plugins!

You see the plugin name in the side-bar but on clicking - just an empty screen?

If you switch on in the preferences to display the cover text below the cover icon - do you then see your albums text but with no covers icons?

jrbastien commented 11 years ago

Yes, ubuntu 12.04 64 bits with RB v2.98 from webupd8 PPA. And yes, the plugin name is there but the album pane is empty. Switching the text under the album ON and OFF has no effect. Still nothing.

I did a ppa-purge and rollbacked to RB 2.96 and the problem persists.

fossfreedom commented 11 years ago

I found that ppa-purge doesnt actually remove all the offending bits of v2.98 :(

I wrote this up on Ask Ubuntu. Can you try this?

http://askubuntu.com/questions/201093/how-do-i-downgrade-rhythmbox-v2-98

jrbastien commented 11 years ago

OK, I have followed your procedure that you have given on Askubunut.com. Still no luck on 12.04 with now RB 2.96. Notice that if I revert to the release 0.6, it is working fine.

fossfreedom commented 11 years ago

@jrbastien - then I'm stumped - @asermax any ideas?

@jrbastien - please can you paste.ubuntu.com a link with the output of

rhythmbox -D coverart

Lets see if there is anything obvious in the debug statements in the code.

jrbastien commented 11 years ago

I'm currently building a fresh Virtual Machine to make sure I'm not making you loosing time. I will send a pastebin if the problem is in this vm too.

asermax commented 11 years ago

Nup, I don't know why this can be happening. The only thing that comes to mind is the missing pixbuf-column property for the iconview on the ui file, but it doesn't seem to be the case on the master branch, so I'm out of ideas o-o

jrbastien commented 11 years ago

Well, I have to admit that the problem might be in my system. My virtual machine does not have this issue. It is either 3 things:

1 - My system is corrupted 2 - The plugin does not work on a 64 bits system 3 - Something needs to be cleaned up before upgrading from release 0.6 to this new version.

I have pasted the log here but I don't see any problem in it: http://paste.ubuntu.com/1426585/

Empty_album_pane

fossfreedom commented 11 years ago

I think this should really be in a separate thread...

anyway

I'm using 12.04 64bits - so dont think 2) is correct re 3) - I've tested this on my 12.04 moving from 0.6 to 0.7 (development) - so again dont think so. 1) agree - but what?

ok - lets try some stuff.

If that doesnt work then try the following

rm -rf ~/.local/share/rhythmbox/plugins/coverart_browser
nautilus ~/.local/share/rhythmbox/plugins

check through nautilus that there are no similar coverart-browser plugins installed.

Check if you have installed the deb package previously i.e.

sudo apt-get purge rhythmbox-plugin-coverart-browser
nautilus /usr/lib/rhythmbox/plugins/
nautilus /usr/share/rhythmbox/plugins

re-install the plugin

then reset gsettings

gsettings reset-recursively org.gnome.rhythmbox.plugins.coverart_browser
rm -rf ~/.cache/rhythmbox

This will remove all cached covers & ratings - so you'll need to reload this afterwards and redo ratings.

jrbastien commented 11 years ago

OK thanks a lot for the extensive support. Resetting gsettings fixed my issue. I could not make it work until I got to that step.

Actually, if I simply re-install, the issue re-appear. I definitely needs to reset gsettings every time to have it working.

fossfreedom commented 11 years ago

@jrbastien - thanks for the feedback. I've created a wiki page with the above so at least this is now more visible.

I'll create an issue to remember to add to the install routine a gsettings reset procedure.