Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Music thumbs to cache #1109

Merged
merged 46 commits into from

6 participants

@jmarshallnz
Owner

This is in no way complete - I'm sure there's areas that will no longer have thumbs after this, as music thumbs were all over the show all using slightly different techniques - I'll continue testing it and adding any fixes on top (to be rebased at the end). Hopefully I hit the majority, but I can't test everything, right? Further, with #1040 being cleaned up to go in, it makes sense to get this in at the same time so that things can be integrated.

Things to discuss are:

  1. This needs a rescan, which currently isn't implemented. The trick is going to be sorting out when the rescan can occur. ATM we update the db on first open, which could potentially occur before the skin is fully up (startup scripts) so this will need a bit of thought. Also, we only want to scan tags, not download album/artist info, so it needs a bit of work on the scanner (basically the scanner should take in a set of flags as to what we want it to do).

  2. This will almost certainly be slower (from the users perspective) at processing thumbs (though it's done off-thread) - in particular, items later in the list will wait on items earlier - this would almost certainly be noticeable in the Songs node which even in modest collections are quite long. There are several potential solutions to this:

    • Having an extra field in the songview/albumviews with the unnormalised art. This would bring it back to how the musicdb thumbs used to operate, though we're now capable of setting more than just the thumb.
    • Changing the bg thumbloader to run from the item during processing, rather than on the list from start to finish (i.e. when processing the UI during the render loop we'd run the thumbloader on the item if it hadn't already been run)
    • We could have a caching layer on the thumbloader that hits ram rather than the db.
  3. There's areas where we use only the pre-cached file thumb rather than the library thumb (upnp for ex) which will need some work - same applies to videos here - figured that @alcoheca would be changing things in this area so didn't spend much time here (plus have no way of testing easily atm).

  4. This deprecates two HTTP-API functions (fetching of album thumb based on album+albumartist, take screenshot).

Comments/criticisms most welcome.

@arnova
Collaborator

1) Can't we update when the user opens the Music window/library view?
2) Having the background loader run for each item totally makes sense. This would also improve the overall performance (and feel) for the video views as well, since certain items have to wait now before others eg. finished fetching/caching their thumbs. Also having some sort of caching would probably help a lot although this may cause problems on platforms which don't have an awful lot of ram(?)
3) We already noticed this in ticket #13052 as well ;-)
4-5) No comment.

@jmarshallnz
Owner

@arnova for 1, we could, but shitloads of stuff hits the thumbs (recently added + lots of scripts for example) before this. The problem is we need to know that an update is required, and the best place we know that is where we update the db. We could save a bool in guisettings.xml I guess, and then reset that bool once the scan is finished. This would also allow for the scan being interrupted by the user - we'd prompt again each time they enter music until the scan is finished. I suspect this is the best solution, so will pop the bools in place for both the music and video db's ready to go for later on when the rescan code is in place.

For 2 it's quite tricky to get this right - The denormalised approach doesn't work well I think as you need to have the artist and album art for songs as well, so denormalising at the song level doesn't buy you much unless you also store the artist and album song at that level as well, which would become a maintenance nightmare I suspect, so that rules out the first option. Having the item loader run per-item when the UI demands it has a lot of benefits, but needs some careful thinking to get it right - in particular, it's more efficient for music items that aren't in the library to run per path rather than per item - you need to do this in order to assign art with any accuracy for example. For library based items it's no problem per item.

@jmarshallnz
Owner

@theuni the last 2 commits restrict the size of cached images to 720, except for if the user has set to 1080 and there's a 1080p image being cached. On devices with smallers screens, it would make sense to set this to something smaller (eg ATV2 can set to 720). There's some argument to restrict to largest screen res as well perhaps, but I'm not sure we can reliably determine this (user runs xbmc in windowed mode for example, then later hooks up a 2560x1600 monitor)

@arnova 7ed96cc adds some settings so we have something to potentially check in the music window to queue up a scan. Will work on adding the necessary stuff to allow the rescan.

@Montellese, @night199uk, 4d541d9 removes idArtist from CSong/CMusicInfoTag. This means that retrieving fanart for items is a little more complicated (separate routines in CMusicDatabase for them). Further, it may have implications for JSON-RPC as some clients might be using them. An alternate is to define this as the primary artistid and joining the album_artist/song_artist tables in the respective views. Thoughts?

@ghost

i've been through it. no eye-brow-raising stuff found, but it's a lot of code... think we need to do as we did with vids. hit it..

@Montellese
Owner

Concerning idArtist in CMusicInfoTag et. al.: I added this specifically (on requests from JSON-RPC client developers) because it is the only way for JSON-RPC clients to cross-reference artists, albums and songs short of looping through all the albums and checking if an artists name is part of an album's list of artists. As an example if XBMC starts playing a song it sends an announcement with the songs ID. The JSON-RPC client can then call AudioLibrary.GetSongDetails and will be able to retrieve the albumid and (primary) artistid belonging to this song. Without the artistid, the client has to call AudioLibrary.GetArtists to retrieve a list of all artists and cross-check their names with the list of artists returned for the specific song (which is obviously more difficult to implement and also slower because of the extra request and the cross-checking. So this would break backwards compatibility with JSON-RPC as published in Eden (which is bound to happen in pre-Frodo) but not because there's an easier/better way to get the same thing done.

Is there any benefit in removing it or what is the motive behind it? (I'm guessing it's because there can be multiple artists linked to an album/song).

@night199uk
Collaborator

Can you get the ArtistID back somehow instead of using GetArtistsByName? (dup artists)

@Montellese for JSON-RPC can we replicate the new MusicDatabase.GetArtistsBySong and MusicDatabase.GetArtistsByAlbum calls through to JSON-RPC? So that the JSON-RPC client flow is like this:
AudioLibrary.GetSongDetails
AudioLibrary.GetArtistsBySong (or Album)...
AudioLibrary.GetArtistDetails

Dup artists & multiple artists per song/album is the motivation... Later we'll be able to parse stuff like this:
Mark Knopfler & Chet Atkins feat. Blah
(two primary artists and a featuring artist)

@jmarshallnz
Owner

@Montellese The alternate is to have a vector of artist id's (or a vector of id,name pairs) for the artists available on request from a song - it's an additional query as @night199uk points out.

Another alternate is to just store the primary artist id and make it clear that there may be more, as this can be fetched without an additional query (it's just a JOIN). The problem with this, is that the primary artist could actually be 2 or more artists (with other artists featuring on select tracks), though this is rare, and currently for fanart and the like it doesn't make much sense to do anything other than the first listed artist anyway, which is what we do.

The first alternate is more useful to the client, but is not something that can be done quickly when retrieving a bunch of songs.

Jonathan Mar... added some commits
Jonathan Marshall [musicdb] add m_type to CMusicInfoTag de75cc2
Jonathan Marshall [upnp art] fanart/thumb images over upnp to use previously cached art eb019ca
Jonathan Marshall [musicdb] add art table to the music database, and get/set art routines da03764
Jonathan Marshall [musicdb] export art from the texturecache (or as XML nodes) when exp…
…orting the music library
2592424
Jonathan Marshall [musicdb] AddSong should take a const CSong and return the id 06e7b4d
Jonathan Marshall [infoscanner] set artist artwork in the db during scan bdfbe52
Jonathan Marshall [thumbloader] we need only a single background thread for the music t…
…humbloader
3e594ad
Jonathan Marshall [thumbloader] retreive art for library music in the thumbloader a46667f
Jonathan Marshall [artist art] adds backcompat for artist art in the thumbloader 3c1178b
Jonathan Marshall [artist art] Musicvideo art is retrieved from the music database 43bdd51
Jonathan Marshall [thumbloader] use thumbloader for infomanager/recently added/json-rpc 0ce8c15
Jonathan Marshall [info dialogs] set thumb/fanart from the db in the song, album, and a…
…rtist dialogs
c089cc8
Jonathan Marshall [thumbloader] set fanart for albums/songs in the music thumbloader 24a5ea0
Jonathan Marshall [embedded art] adds EmbeddedArt members to CSong and CMusicInfoTag, a…
…nd adds art attribute to CAlbum
d21a298
Jonathan Marshall [embedded art] pass EmbeddedArt into IMusicInfoTagLoader::Load 268a0ab
Jonathan Marshall [embedded art] read coverart data in tags into the MusicInfoTag rathe…
…r than caching directly
fd0f626
Jonathan Marshall [embedded art] copy embedded art in underlying media item to cue shee…
…t items
8f9ba90
Jonathan Marshall [infoscanner] add CategoriseAlbums to MusicInfoScanner as an improved…
… version of CheckForVariousArtists
9f08d93
Jonathan Marshall [infoscanner] assign embedded art to the album if a single album is i…
…n the folder
8c4d9fb
Jonathan Marshall [infoscanner] add songs to database by album 7097064
Jonathan Marshall [infoscanner] add song and album art to the database on scan a29d994
Jonathan Marshall [infoscanner] remove old album categorisation and thumb updating func…
…tions from the infoscanner
58a38d8
Jonathan Marshall [imageloader] factor out LoadFromImage 55db267
Jonathan Marshall [imageloader] adds a static wrapper to CBaseTexture::LoadFromFile to …
…save worrying about deletion of the created texture object
cc5ed3c
Jonathan Marshall [imageloader] adds LoadFromFileInMemory to CBaseTexture 6f4ce3e
Jonathan Marshall [imageloader] switch flipped param in CTextureCacheJob to a string to…
… allow more values
06e1d96
Jonathan Marshall [imageloader] adds ability to cache embedded music art fd9df6a
Jonathan Marshall [thumbs] don't fallback to using folder.jpg for songs - it'll be done…
… during scan after reading tags if required.
840fa97
Jonathan Marshall [thumbs] song and album thumbs are retrieved using the thumbloader, s…
…o no need for them to be set when retrieving from the db.
27e3814
Jonathan Marshall [thumbs] use CMusicThumbLoader::FillThumb for setting music thumbs fo…
…r files/folders
852da99
Jonathan Marshall [thumbs] deprecate HTTP-API GetThumbFilename for albums e079b96
Jonathan Marshall [thumbs] remove unnecessary calls to SetMusicThumb from JSON-RPC/Anno…
…unceManager
dad0f19
Jonathan Marshall [thumbs] music share thumbs can use the texture database d63e8ff
Jonathan Marshall [infoloader] don't set the music thumbs in the musicplaylist OnItemLo…
…aded callback (TODO: needs to be done somewhere)
6d99ed5
Jonathan Marshall [infoloader] set album art for file items in a folder when finished l…
…oading tags for that folder
581fe30
Jonathan Marshall [httpapi] depracate TakeScreenshot that has paramaters 0f12c02
Jonathan Marshall [lastfm] no need to cache art - the texture cache will do it 452c254
Jonathan Marshall [cleanup] remove old thumb caching code as no longer used 3ae8891
Jonathan Marshall [dvd thumbs] no need to cache on insert 7e0a095
Jonathan Marshall [cleanup] drop unused functions from musicdatabase 402d5cb
Jonathan Marshall [cleanup] remove unused functions in cximage 4182f70
Jonathan Marshall [cleanup] remove unneeded Picture.h includes 24f1dc3
Jonathan Marshall [song/musicinfotag] remove artist id from CSong and CMusicInfoTag 2e56957
Jonathan Marshall [dbupdate] add settings indicating the db needs an update, so that la…
…ter update code can kick in and rescan as needed
392bf9c
Jonathan Marshall [texturecache] cache images by default at a max of 720p, except for 1…
…080p fanart images which default to 1080p - can be changed by <fanartres> and <imageres> advancedsettings - these replace the previous <fanartheight> and <imagesize> tags.
34f045a
Jonathan Marshall [jpegloader] load based on m_fanartRes/m_imageRes instead of based on…
… screen res
f878229
@jmarshallnz
Owner

Updated with fixes based on comments - thanks very much.

@night199uk, @Montellese The one thing I'd like resolved before this going in is how to handle artistId for JSON-RPC. If noone objects, I'll add it back into the song and album views for now and we can redo it later if required.

@night199uk
Collaborator
@jmarshallnz
Owner

@night199uk Go for it - I believe @Montellese is busy with other things. I suspect you'll need to add a vector to CSong/CMusicInfoTag and go from there? It would be nice to supplement the existing vector to vector instead if possible as I doubt there's much point having only the ids available - this would match with the cast list for movies which has both id and name (as well as other information) available.

In the meantime, I've done up a quick fix commit to get the idArtist back in for the meantime in case we find it's more difficult than initially thought - it's currently broken, after all - available in my restore_idArtist branch.

@night199uk
Collaborator
@jmarshallnz
Owner
@night199uk
Collaborator
@night199uk
Collaborator

yes :-)

Whats your thought on using an enum type instead of a string? makes select{ case : } simpler in core (GUIWindowMusicBase needs this). Can be translated in e.g. JSON-RPC where we want a string?

Doesn't particularly worry me either way. JSON-RPC already sets a string based on other criteria, so that doesn't really matter as either way it would need support). The db doesn't require one (it could use an int instead, which would be slightly more efficient to hash perhaps?)

There's a slight advantage in that the type is often also related to the table name, which means slightly less code (eg see GetArtistArtByItem) though that could be done using a LUT instead easily enough.

@Montellese: your thoughts?

@Montellese
Owner

Concerning JSON-RPC: IMO it's not absolutely necessary to provide the IDs of the artists as long as there's a way to retrieve the artist based on a song/album (which could be done by adding parameters "songid" and "albumid" to AudioLibrary.GetArtists). I don't develop any JSON-RPC client myself so sometimes it's hard for me to say/know what all the clients out there do. Maybe ask joethefox if/how he handles this in the official iOS remote app? Not sure if freezy3k is still working on updating the official android remote to JSON-RPC.

All in all it sounds like this will break backwards compatibility to Eden one way or another. If so we might wanna consider also removing some of the other hacks we put in place to keep backwards compatibility.

Concerning making those types into an enum. I first considered that as well when the video thumb stuff was merged but although it's easier to have enums in the code (because you can use switch statements and there's some compile-time checking) but it also makes it less flexible. Sure you can add a new enum value when you have a new type of media but if we ever move towards a more flexible database layout (which would e.g. allow singles, compilations, soundtracks, concerts etc) those types could actually be defined in the database without having to change the code. But that's far off so just wanted to throw it in ;-)

@jmarshallnz jmarshallnz merged commit f70b7d7 into xbmc:master
@ipitcher

Just tested this. Views aren't being created when using a MySQL back-end.

@jmarshallnz
Owner

Thanks for the informative message :p

@ipitcher

Hahaha, sorry. I'll try to recreate the conditions and get a debug log.

But, in summary: I had a version 25 music database, built from git after these commits were merged, got many "the table does not exist" messages, looked at the database with mysql command line client, database existed and was populated, views weren't there, dropped the database, restarted XBMC to allow it to create a fresh database, scanned music source, views weren't there, modified advancedsettings to use sqlite, rescanned source to sqlite, looked fine and everything showed up in the gui, modified advancedsettings to use mysql, restarted XBMC, version 27 database was create and populated -- views still not there.

@jmarshallnz
Owner

Odd, as all that was changed with the views is that strThumb and the thumb table are no longer joined. Are the triggers created (song, artist, album tables have a trigger on delete to clear the art table)?

@ipitcher

Looks like tgrAlbumInfo is the only one there.

@jmarshallnz
Owner

Ah - I know what it is - silly mysql and it's text indicies needing a length (index on art table). Fixed in ae6508e

@ipitcher

Okay, thanks. That's working well now. One last thing: are Album Artist tags going to be required now? Newly scraped albums without the Album Artist tag are ending up with empty strArtists fields. I suppose I could just add the Album Artist tags, but I thought it was worth asking.

@MartijnKaijser

Yes they are required or else they end up without artist. You must also check/uncheck the compilation flag for albums or compilations

@night199uk
Collaborator

ipitcher: do you see the same in yesterdays master? I want to check if that is from the musicdb changes or from these changes.

@ipitcher

Yes, this was from yesterday's master. Sorry, I should have thought about the other musicdb changes before commenting.

I recall strArtists populating correctly without Album Artist tags since that music db change, but I don't remember if it was on a db upgrade or a fresh scrape.

@night199uk
Collaborator
@ipitcher

Sorry, the log is long gone as is the old DB. This is MySQL, and though I'm not certain, I think the same behavior was seen on SQLite.

@night199uk
Collaborator
@ipitcher

I've since copied the Artist tags to the Album Artist tags on all of my mp3s with empty Album Artists, but if I have some time later I can create a small test case and send you a log.

@Montellese

Am I missing something here? This was the only place that filled strThumb which is used further down to fill the ListItem.X.Thumb for recently added album songs. How is this achieved now?

Fixed in 7bb063a

@MartijnKaijser

Are these folders and subfolders still needed (because they are still generated again at every start-up)?:
Thumbnails/
generated
Music
Video

@jmarshallnz
Owner

20fcaae removes those @MartijnKaijser

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 3, 2012
  1. [musicdb] add m_type to CMusicInfoTag

    Jonathan Marshall authored
  2. [musicdb] export art from the texturecache (or as XML nodes) when exp…

    Jonathan Marshall authored
    …orting the music library
  3. [musicdb] AddSong should take a const CSong and return the id

    Jonathan Marshall authored
  4. [infoscanner] set artist artwork in the db during scan

    Jonathan Marshall authored
  5. [thumbloader] we need only a single background thread for the music t…

    Jonathan Marshall authored
    …humbloader
  6. [thumbloader] retreive art for library music in the thumbloader

    Jonathan Marshall authored
  7. [artist art] adds backcompat for artist art in the thumbloader

    Jonathan Marshall authored
  8. [info dialogs] set thumb/fanart from the db in the song, album, and a…

    Jonathan Marshall authored
    …rtist dialogs
  9. [embedded art] adds EmbeddedArt members to CSong and CMusicInfoTag, a…

    Jonathan Marshall authored
    …nd adds art attribute to CAlbum
  10. [embedded art] read coverart data in tags into the MusicInfoTag rathe…

    Jonathan Marshall authored
    …r than caching directly
  11. [embedded art] copy embedded art in underlying media item to cue shee…

    Jonathan Marshall authored
    …t items
  12. [infoscanner] add CategoriseAlbums to MusicInfoScanner as an improved…

    Jonathan Marshall authored
    … version of CheckForVariousArtists
  13. [infoscanner] assign embedded art to the album if a single album is i…

    Jonathan Marshall authored
    …n the folder
  14. [infoscanner] add songs to database by album

    Jonathan Marshall authored
  15. [infoscanner] add song and album art to the database on scan

    Jonathan Marshall authored
  16. [infoscanner] remove old album categorisation and thumb updating func…

    Jonathan Marshall authored
    …tions from the infoscanner
  17. [imageloader] factor out LoadFromImage

    Jonathan Marshall authored
  18. [imageloader] adds a static wrapper to CBaseTexture::LoadFromFile to …

    Jonathan Marshall authored
    …save worrying about deletion of the created texture object
  19. [imageloader] adds LoadFromFileInMemory to CBaseTexture

    Jonathan Marshall authored
  20. [imageloader] switch flipped param in CTextureCacheJob to a string to…

    Jonathan Marshall authored
    … allow more values
  21. [imageloader] adds ability to cache embedded music art

    Jonathan Marshall authored
  22. [thumbs] don't fallback to using folder.jpg for songs - it'll be done…

    Jonathan Marshall authored
    … during scan after reading tags if required.
  23. [thumbs] song and album thumbs are retrieved using the thumbloader, s…

    Jonathan Marshall authored
    …o no need for them to be set when retrieving from the db.
  24. [thumbs] use CMusicThumbLoader::FillThumb for setting music thumbs fo…

    Jonathan Marshall authored
    …r files/folders
  25. [thumbs] deprecate HTTP-API GetThumbFilename for albums

    Jonathan Marshall authored
  26. [thumbs] remove unnecessary calls to SetMusicThumb from JSON-RPC/Anno…

    Jonathan Marshall authored
    …unceManager
  27. [thumbs] music share thumbs can use the texture database

    Jonathan Marshall authored
  28. [infoloader] don't set the music thumbs in the musicplaylist OnItemLo…

    Jonathan Marshall authored
    …aded callback (TODO: needs to be done somewhere)
  29. [infoloader] set album art for file items in a folder when finished l…

    Jonathan Marshall authored
    …oading tags for that folder
  30. [httpapi] depracate TakeScreenshot that has paramaters

    Jonathan Marshall authored
  31. [lastfm] no need to cache art - the texture cache will do it

    Jonathan Marshall authored
  32. [cleanup] remove old thumb caching code as no longer used

    Jonathan Marshall authored
  33. [dvd thumbs] no need to cache on insert

    Jonathan Marshall authored
  34. [cleanup] drop unused functions from musicdatabase

    Jonathan Marshall authored
  35. [cleanup] remove unused functions in cximage

    Jonathan Marshall authored
  36. [cleanup] remove unneeded Picture.h includes

    Jonathan Marshall authored
  37. [dbupdate] add settings indicating the db needs an update, so that la…

    Jonathan Marshall authored
    …ter update code can kick in and rescan as needed
  38. [texturecache] cache images by default at a max of 720p, except for 1…

    Jonathan Marshall authored
    …080p fanart images which default to 1080p - can be changed by <fanartres> and <imageres> advancedsettings - these replace the previous <fanartheight> and <imagesize> tags.
  39. [jpegloader] load based on m_fanartRes/m_imageRes instead of based on…

    Jonathan Marshall authored
    … screen res
This page is out of date. Refresh to see the latest.
Showing with 1,411 additions and 2,313 deletions.
  1. +42 −308 lib/cximage-6.0/CxImage/DllInterface.cpp
  2. +8 −0 lib/cximage-6.0/CxImage/ximaenc.cpp
  3. +8 −1 lib/cximage-6.0/CxImage/ximage.h
  4. +0 −1  xbmc/Application.cpp
  5. +1 −1  xbmc/ApplicationMessenger.cpp
  6. +2 −203 xbmc/FileItem.cpp
  7. +1 −32 xbmc/FileItem.h
  8. +8 −10 xbmc/GUIInfoManager.cpp
  9. +2 −7 xbmc/GUILargeTextureManager.cpp
  10. +31 −25 xbmc/TextureCacheJob.cpp
  11. +4 −4 xbmc/TextureCacheJob.h
  12. +132 −5 xbmc/ThumbLoader.cpp
  13. +28 −0 xbmc/ThumbLoader.h
  14. +0 −162 xbmc/ThumbnailCache.cpp
  15. +0 −16 xbmc/ThumbnailCache.h
  16. +0 −21 xbmc/Util.cpp
  17. +0 −4 xbmc/Util.h
  18. +2 −2 xbmc/cores/dvdplayer/DVDFileInfo.cpp
  19. +4 −17 xbmc/dialogs/GUIDialogContextMenu.cpp
  20. +7 −109 xbmc/filesystem/DirectoryCache.cpp
  21. +0 −9 xbmc/filesystem/DirectoryCache.h
  22. +12 −4 xbmc/guilib/JpegIO.cpp
  23. +1 −1  xbmc/guilib/JpegIO.h
  24. +80 −8 xbmc/guilib/Texture.cpp
  25. +31 −2 xbmc/guilib/Texture.h
  26. +2 −2 xbmc/guilib/TextureManager.cpp
  27. +0 −1  xbmc/interfaces/AnnouncementManager.cpp
  28. +3 −83 xbmc/interfaces/http-api/XBMChttp.cpp
  29. +0 −2  xbmc/interfaces/json-rpc/AudioLibrary.cpp
  30. +18 −15 xbmc/interfaces/json-rpc/FileItemHandler.cpp
  31. +2 −0  xbmc/music/Album.h
  32. +0 −30 xbmc/music/LastFmManager.cpp
  33. +214 −241 xbmc/music/MusicDatabase.cpp
  34. +73 −9 xbmc/music/MusicDatabase.h
  35. +29 −6 xbmc/music/MusicInfoLoader.cpp
  36. +15 −3 xbmc/music/Song.cpp
  37. +13 −6 xbmc/music/Song.h
  38. +62 −104 xbmc/music/dialogs/GUIDialogMusicInfo.cpp
  39. +0 −2  xbmc/music/dialogs/GUIDialogMusicInfo.h
  40. +26 −27 xbmc/music/dialogs/GUIDialogSongInfo.cpp
  41. +214 −183 xbmc/music/infoscanner/MusicInfoScanner.cpp
  42. +41 −4 xbmc/music/infoscanner/MusicInfoScanner.h
  43. +8 −24 xbmc/music/tags/FlacTag.cpp
  44. +5 −25 xbmc/music/tags/Id3Tag.cpp
  45. +2 −1  xbmc/music/tags/ImusicInfoTagLoader.h
  46. +68 −12 xbmc/music/tags/MusicInfoTag.cpp
  47. +33 −3 xbmc/music/tags/MusicInfoTag.h
  48. +1 −1  xbmc/music/tags/MusicInfoTagLoaderASAP.cpp
  49. +1 −1  xbmc/music/tags/MusicInfoTagLoaderASAP.h
  50. +1 −1  xbmc/music/tags/MusicInfoTagLoaderApe.cpp
  51. +1 −1  xbmc/music/tags/MusicInfoTagLoaderApe.h
  52. +1 −1  xbmc/music/tags/MusicInfoTagLoaderCDDA.cpp
  53. +1 −1  xbmc/music/tags/MusicInfoTagLoaderCDDA.h
  54. +1 −1  xbmc/music/tags/MusicInfoTagLoaderDatabase.cpp
  55. +1 −1  xbmc/music/tags/MusicInfoTagLoaderDatabase.h
  56. +2 −1  xbmc/music/tags/MusicInfoTagLoaderFlac.cpp
  57. +1 −1  xbmc/music/tags/MusicInfoTagLoaderFlac.h
  58. +2 −1  xbmc/music/tags/MusicInfoTagLoaderMP3.cpp
  59. +1 −1  xbmc/music/tags/MusicInfoTagLoaderMP3.h
  60. +18 −40 xbmc/music/tags/MusicInfoTagLoaderMP4.cpp
  61. +3 −5 xbmc/music/tags/MusicInfoTagLoaderMP4.h
  62. +1 −1  xbmc/music/tags/MusicInfoTagLoaderMidi.cpp
  63. +1 −1  xbmc/music/tags/MusicInfoTagLoaderMidi.h
  64. +1 −1  xbmc/music/tags/MusicInfoTagLoaderMod.cpp
  65. +1 −1  xbmc/music/tags/MusicInfoTagLoaderMod.h
  66. +1 −1  xbmc/music/tags/MusicInfoTagLoaderNSF.cpp
  67. +1 −1  xbmc/music/tags/MusicInfoTagLoaderNSF.h
  68. +2 −1  xbmc/music/tags/MusicInfoTagLoaderOgg.cpp
  69. +1 −1  xbmc/music/tags/MusicInfoTagLoaderOgg.h
  70. +1 −1  xbmc/music/tags/MusicInfoTagLoaderSPC.cpp
  71. +1 −1  xbmc/music/tags/MusicInfoTagLoaderSPC.h
  72. +1 −1  xbmc/music/tags/MusicInfoTagLoaderShn.cpp
  73. +1 −1  xbmc/music/tags/MusicInfoTagLoaderShn.h
  74. +8 −35 xbmc/music/tags/MusicInfoTagLoaderWMA.cpp
  75. +2 −2 xbmc/music/tags/MusicInfoTagLoaderWMA.h
  76. +1 −1  xbmc/music/tags/MusicInfoTagLoaderWav.cpp
  77. +1 −1  xbmc/music/tags/MusicInfoTagLoaderWav.h
  78. +1 −1  xbmc/music/tags/MusicInfoTagLoaderYM.cpp
  79. +1 −1  xbmc/music/tags/MusicInfoTagLoaderYM.h
  80. +3 −1 xbmc/music/tags/Tag.h
  81. +8 −52 xbmc/music/windows/GUIWindowMusicBase.cpp
  82. +0 −1  xbmc/music/windows/GUIWindowMusicBase.h
  83. +14 −10 xbmc/music/windows/GUIWindowMusicNav.cpp
  84. +1 −0  xbmc/music/windows/GUIWindowMusicNav.h
  85. +0 −8 xbmc/music/windows/GUIWindowMusicPlaylist.cpp
  86. +0 −5 xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp
  87. +0 −2  xbmc/music/windows/GUIWindowMusicSongs.cpp
  88. +3 −4 xbmc/network/UPnP.cpp
  89. +4 −13 xbmc/pictures/DllImageLib.h
  90. +0 −1  xbmc/pictures/GUIWindowPictures.cpp
  91. +0 −1  xbmc/pictures/GUIWindowSlideShow.cpp
  92. +22 −128 xbmc/pictures/Picture.cpp
  93. +0 −8 xbmc/pictures/Picture.h
  94. +2 −2 xbmc/pictures/PictureThumbLoader.cpp
  95. +4 −4 xbmc/settings/AdvancedSettings.cpp
  96. +6 −2 xbmc/settings/AdvancedSettings.h
  97. +7 −1 xbmc/settings/Settings.cpp
  98. +3 −3 xbmc/settings/Settings.h
  99. +0 −26 xbmc/storage/DetectDVDType.cpp
  100. +0 −41 xbmc/utils/Fanart.cpp
  101. +0 −20 xbmc/utils/Fanart.h
  102. +9 −8 xbmc/utils/RecentlyAddedJob.cpp
  103. +0 −37 xbmc/utils/ScraperUrl.cpp
  104. +0 −1  xbmc/utils/ScraperUrl.h
  105. +3 −11 xbmc/video/VideoDatabase.cpp
  106. +0 −20 xbmc/video/VideoInfoScanner.cpp
  107. +0 −9 xbmc/video/VideoInfoScanner.h
  108. +1 −1  xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp
  109. +7 −7 xbmc/video/dialogs/GUIDialogVideoInfo.cpp
  110. +20 −40 xbmc/video/windows/GUIWindowVideoNav.cpp
  111. +0 −1  xbmc/windows/GUIWindowFileManager.cpp
View
350 lib/cximage-6.0/CxImage/DllInterface.cpp
@@ -17,12 +17,6 @@
#define RESAMPLE_QUALITY 0
#undef USE_EXIF_THUMBS
-// MS DirectX routines don't like loading .jpg less than 8x8 pixels.
-#define MIN_THUMB_WIDTH 8
-#define MIN_THUMB_HEIGHT 8
-#define MAX_WIDTH 4096
-#define MAX_HEIGHT 4096
-
extern "C" struct ImageInfo
{
unsigned int width;
@@ -35,13 +29,6 @@ extern "C" struct ImageInfo
BYTE *alpha;
};
-#if defined(_LINUX) || defined(__APPLE__)
-static void DeleteFile(const char* name)
-{
- unlink(name);
-}
-#endif
-
// helper functions
// determines based on file extension the type of file
@@ -110,45 +97,7 @@ int DetectFileType(const BYTE* pBuffer, int nBufSize)
return CXIMAGE_FORMAT_UNKNOWN;
}
-bool CopyFile(const char *src, const char *dest)
-{
- const unsigned int bufferSize = 16384;
- char buffer[bufferSize];
- FILE *hSrc = fopen(src, "rb");
- if (!hSrc) return false;
- FILE *hDest = fopen(dest, "wb");
- if (!hDest)
- {
- fclose(hSrc);
- return false;
- }
- bool ret = true;
- while (ret)
- {
- int sizeRead = fread(buffer, 1, bufferSize, hSrc);
- if (sizeRead > 0)
- {
- int sizeWritten = fwrite(buffer, 1, sizeRead, hDest);
- if (sizeWritten != sizeRead)
- {
- printf("PICTURE:Error writing file in copy");
- ret = false;
- }
- }
- else if (sizeRead < 0)
- {
- printf("PICTURE:Error reading file for copy");
- ret = false;
- }
- else
- break; // we're done
- }
- fclose(hSrc);
- fclose(hDest);
- return ret;
-}
-
-int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height, bool checkTooSmall = false)
+int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height)
{
bool bResize = false;
float fAspect = ((float)image.GetWidth()) / ((float)image.GetHeight());
@@ -166,18 +115,6 @@ int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height,
newheight = height;
newwidth = (DWORD)( fAspect * ( (float)newheight) );
}
- if (checkTooSmall && newwidth < MIN_THUMB_WIDTH)
- {
- bResize = true;
- newwidth = MIN_THUMB_HEIGHT;
- newheight = (DWORD)( ( (float)newwidth) / fAspect);
- }
- if (checkTooSmall && newheight < MIN_THUMB_HEIGHT)
- {
- bResize = true;
- newheight = MIN_THUMB_HEIGHT;
- newwidth = (DWORD)( fAspect * ( (float)newheight) );
- }
if (bResize)
{
if (!image.Resample(newwidth, newheight, RESAMPLE_QUALITY) || !image.IsValid())
@@ -189,70 +126,6 @@ int ResampleKeepAspect(CxImage &image, unsigned int width, unsigned int height,
return bResize ? 1 : 0;
}
-int ResampleKeepAspectArea(CxImage &image, unsigned int area)
-{
- float fAspect = ((float)image.GetWidth()) / ((float)image.GetHeight());
- unsigned int width = (unsigned int)sqrt(area * fAspect);
- unsigned int height = (unsigned int)sqrt(area / fAspect);
- if (width > MAX_WIDTH) width = MAX_WIDTH;
- if (height > MAX_HEIGHT) height = MAX_HEIGHT;
- return ResampleKeepAspect(image, width, height, true);
-}
-
-bool SaveThumb(CxImage &image, const char *file, const char *thumb, int maxWidth, int maxHeight, bool bNeedToConvert = true, bool autoRotate = true)
-{
- // ok, now resample the image down if necessary
- int ret = ResampleKeepAspectArea(image, maxWidth * maxHeight);
- if (ret < 0) return false;
- if (ret) bNeedToConvert = true;
-
- // if we don't have a png but have a < 24 bit image, then convert to 24bits
- if ( image.GetNumColors())
- {
- if (!image.IncreaseBpp(24) || !image.IsValid())
- {
- printf("PICTURE::SaveThumb: Unable to convert to 24bpp: Error:%s\n", image.GetLastError());
- return false;
- }
- bNeedToConvert = true;
- }
-
- if ( autoRotate && image.GetExifInfo()->Orientation > 1)
- {
- image.RotateExif(image.GetExifInfo()->Orientation);
- bNeedToConvert = true;
- }
-
-#ifndef _LINUX
- ::DeleteFile(thumb);
-#else
- unlink(thumb);
-#endif
-
- // only resave the image if we have to (quality of the JPG saver isn't too hot!)
- if (bNeedToConvert)
- {
- // May as well have decent quality thumbs
- image.SetJpegQuality(90);
- if (!image.Save(thumb, image.AlphaIsValid() ? CXIMAGE_FORMAT_PNG : CXIMAGE_FORMAT_JPG))
- {
- printf("PICTURE::SaveThumb: Unable to save image: %s Error:%s\n", thumb, image.GetLastError());
- ::DeleteFile(thumb);
- return false;
- }
- }
- else
- { // Don't need to convert the file - copy it instead
- if (!CopyFile(file, thumb))
- {
- printf("PICTURE::SaveThumb: Unable to copy file %s\n", file);
- ::DeleteFile(thumb);
- return false;
- }
- }
- return true;
-}
-
#ifdef LoadImage
#undef LoadImage
#endif
@@ -344,166 +217,74 @@ extern "C"
return (info->texture != NULL);
};
-
- __declspec(dllexport) bool CreateThumbnail(const char *file, const char *thumb, int maxWidth, int maxHeight, bool rotateExif)
+ __declspec(dllexport) bool LoadImageFromMemory(const BYTE *buffer, unsigned int size, const char *mime, unsigned int maxwidth, unsigned int maxheight, ImageInfo *info)
{
- if (!file || !thumb) return false;
-
- if (IsDir(file))
- return false;
+ if (!buffer || !size || !mime || !info) return false;
// load the image
- DWORD dwImageType = GetImageType(file);
- CxImage image(dwImageType);
- int actualwidth = maxWidth * maxHeight;
- int actualheight = 0;
- try
- {
- // jpeg's may contain an EXIF preview image
- // we don't use it though, as the resolution is normally too low
-#ifdef USE_EXIF_THUMBS
- if ((dwImageType == CXIMAGE_FORMAT_JPG || dwImageType == CXIMAGE_FORMAT_RAW) && image.GetExifThumbnail(file, thumb, dwImageType))
- {
- return true;
- }
-#endif
-
- if (!image.Load(file, dwImageType, actualwidth, actualheight) || !image.IsValid())
- {
- printf("PICTURE::CreateThumbnail: Unable to open image: %s Error:%s\n", file, image.GetLastError());
- return false;
- }
- }
- catch (...)
- {
- printf("PICTURE::CreateThumbnail: Unable to open image: %s\n", file);
- return false;
- }
-
- // we need to convert if we don't have a jpeg or png.
- bool bNeedToConvert = (dwImageType != CXIMAGE_FORMAT_JPG && dwImageType != CXIMAGE_FORMAT_PNG);
- if (actualwidth > maxWidth || actualheight > maxHeight)
- bNeedToConvert = true;
-
- // save png thumbs as png, but all others as jpeg
- return SaveThumb(image, file, thumb, maxWidth, maxHeight, bNeedToConvert, rotateExif);
- };
-
- __declspec(dllexport) bool CreateThumbnailFromMemory(BYTE *buffer, unsigned int size, const char *ext, const char *thumb, int maxWidth, int maxHeight)
- {
- if (!buffer || !size || !ext || !thumb) return false;
- // load the image
DWORD dwImageType = CXIMAGE_FORMAT_UNKNOWN;
- if (strlen(ext)) {
- dwImageType = GetImageType(ext);
- if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
- dwImageType = DetectFileType(buffer, size);
- }
- else
+ if (strlen(mime))
+ dwImageType = GetImageType(mime);
+ if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
dwImageType = DetectFileType(buffer, size);
if (dwImageType == CXIMAGE_FORMAT_UNKNOWN)
{
- printf("PICTURE::CreateThumbnailFromMemory: Unable to determine image type.");
+ printf("PICTURE::LoadImageFromMemory: Unable to determine image type.");
return false;
}
- CxImage image(dwImageType);
+
+ CxImage *image = new CxImage(dwImageType);
+ if (!image)
+ return false;
+
+ int actualwidth = maxwidth;
+ int actualheight = maxheight;
+
try
{
- bool success = image.Decode(buffer, size, dwImageType);
+ bool success = image->Decode((BYTE*)buffer, size, dwImageType, actualwidth, actualheight);
if (!success && dwImageType != CXIMAGE_FORMAT_UNKNOWN)
{ // try to decode with unknown imagetype
- success = image.Decode(buffer, size, CXIMAGE_FORMAT_UNKNOWN);
+ success = image->Decode((BYTE*)buffer, size, CXIMAGE_FORMAT_UNKNOWN);
}
- if (!success || !image.IsValid())
+ if (!success || !image->IsValid())
{
- printf("PICTURE::CreateThumbnailFromMemory: Unable to decode image. Error:%s\n", image.GetLastError());
+ printf("PICTURE::LoadImageFromMemory: Unable to decode image. Error:%s\n", image->GetLastError());
+ delete image;
return false;
}
}
catch (...)
{
- printf("PICTURE::CreateThumbnailFromMemory: Unable to decode image.");
+ printf("PICTURE::LoadImageFromMemory: Unable to decode image.");
+ delete image;
return false;
}
- return SaveThumb(image, "", thumb, maxWidth, maxHeight);
- };
-
- __declspec(dllexport) bool CreateFolderThumbnail(const char **file, const char *thumb, int maxWidth, int maxHeight)
- {
- if (!file || !file[0] || !file[1] || !file[2] || !file[3] || !thumb) return false;
-
- CxImage folderimage(maxWidth, maxHeight, 32, CXIMAGE_FORMAT_PNG);
- folderimage.AlphaCreate();
- int iWidth = maxWidth / 2;
- int iHeight = maxHeight / 2;
- for (int i = 0; i < 2; i++)
- {
- for (int j = 0; j < 2; j++)
- {
- int width = iWidth;
- int height = iHeight;
- bool bBlank = false;
- if (strlen(file[i*2 + j]) == 0)
- bBlank = true;
- if (!bBlank)
- {
- CxImage image;
- if (image.Load(file[i*2 + j], CXIMAGE_FORMAT_JPG, width, height))
- {
- // resize image to iWidth
- if (ResampleKeepAspect(image, iWidth - 2, iHeight - 2) >= 0)
- {
- int iOffX = (iWidth - 2 - image.GetWidth()) / 2;
- int iOffY = (iHeight - 2 - image.GetHeight()) / 2;
- for (int x = 0; x < iWidth; x++)
- {
- for (int y = 0; y < iHeight; y++)
- {
- RGBQUAD rgb;
- if (x < iOffX || x >= iOffX + (int)image.GetWidth() || y < iOffY || y >= iOffY + (int)image.GetHeight())
- {
- rgb.rgbBlue = 0; rgb.rgbGreen = 0; rgb.rgbRed = 0; rgb.rgbReserved = 0;
- }
- else
- {
- rgb = image.GetPixelColor(x - iOffX, y - iOffY);
- rgb.rgbReserved = 255;
- }
- folderimage.SetPixelColor(x + j*iWidth, y + (1 - i)*iHeight, rgb, true);
- }
- }
- }
- else
- bBlank = true;
- }
- else
- bBlank = true;
- }
- if (bBlank)
- { // no image - just fill with black alpha
- for (int x = 0; x < iWidth; x++)
- {
- for (int y = 0; y < iHeight; y++)
- {
- RGBQUAD rgb;
- rgb.rgbBlue = 0; rgb.rgbGreen = 0; rgb.rgbRed = 0; rgb.rgbReserved = 0;
- folderimage.SetPixelColor(x + j*iWidth, y + (1 - i)*iHeight, rgb, true);
- }
- }
- }
- }
- }
- ::DeleteFile(thumb);
- if (!folderimage.Save(thumb, CXIMAGE_FORMAT_PNG))
+ // ok, now resample the image down if necessary
+ if (ResampleKeepAspect(*image, maxwidth, maxheight) < 0)
{
- printf("Unable to save thumb file");
- ::DeleteFile(thumb);
+ printf("PICTURE::LoadImage: Unable to resample picture\n");
+ delete image;
return false;
}
- return true;
- };
+ // make sure our image is 24bit minimum
+ image->IncreaseBpp(24);
+
+ // fill in our struct
+ info->width = image->GetWidth();
+ info->height = image->GetHeight();
+ info->originalwidth = actualwidth;
+ info->originalheight = actualheight;
+ memcpy(&info->exifInfo, image->GetExifInfo(), sizeof(EXIFINFO));
+
+ // create our texture
+ info->context = image;
+ info->texture = image->GetBits();
+ info->alpha = image->AlphaGetBits();
+ return (info->texture != NULL);
+ };
__declspec(dllexport) bool CreateThumbnailFromSurface(BYTE *buffer, unsigned int width, unsigned int height, unsigned int stride, const char *thumb)
{
@@ -549,53 +330,6 @@ extern "C"
}
return true;
};
- __declspec(dllexport) int ConvertFile(const char *srcfile, const char *destfile, float rotateDegrees, int destwidth, int destheight, unsigned int destquality, bool mirror)
- {
- if (!srcfile || !destfile || (destwidth ==-1 && destheight==-1)) return false;
- DWORD dwImageType = GetImageType(srcfile);
- DWORD dwDestImageType = GetImageType(destfile);
- CxImage image(dwImageType);
- try
- {
- if (!image.Load(srcfile, dwImageType) || !image.IsValid())
- {
- printf("PICTURE::ConvertFile: Unable to open image: %s Error:%s\n", srcfile, image.GetLastError());
- return 7;
- }
- }
- catch (...)
- {
- printf("PICTURE::ConvertFile: Unable to open image: %s\n", srcfile);
- return 2;
- }
- if (destheight==-1) {
- destheight = (int) ((float)destwidth * ((float)image.GetHeight()/ (float)image.GetWidth())) ;
- }
- if (destwidth==-1)
- destwidth = (int) ((float)destheight * ((float)image.GetWidth()/(float)image.GetHeight())) ;
- if (!image.Resample(destwidth, destheight, RESAMPLE_QUALITY) || !image.IsValid())
- {
- printf("PICTURE::ConvertFile: Unable to resample picture: Error:%s\n", image.GetLastError());
- return 3;
- }
- if (!rotateDegrees==0.0)
- if (!image.Rotate(rotateDegrees) || !image.IsValid())
- {
- printf("PICTURE::ConvertFile: Unable to rotate picture: Error:%s\n", image.GetLastError());
- return 4;
- }
- if (mirror)
- image.Mirror(false,false);
- if (dwDestImageType==CXIMAGE_FORMAT_JPG)
- image.SetJpegQuality(destquality);
- if (!image.Save(destfile, dwDestImageType))
- {
- printf("PICTURE::ConvertFile: Unable to save image: %s Error:%s\n", destfile, image.GetLastError());
- ::DeleteFile(destfile);
- return 5;
- }
- return 0;
- };
}
#endif
View
8 lib/cximage-6.0/CxImage/ximaenc.cpp
@@ -695,11 +695,19 @@ CxImage::CxImage(BYTE * buffer, DWORD size, DWORD imagetype)
* \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
* \return true if everything is ok
*/
+#ifdef XBMC
+bool CxImage::Decode(BYTE * buffer, DWORD size, DWORD imagetype, int &width, int &height)
+{
+ CxMemFile file(buffer,size);
+ return Decode(&file,imagetype,width,height);
+}
+#else
bool CxImage::Decode(BYTE * buffer, DWORD size, DWORD imagetype)
{
CxMemFile file(buffer,size);
return Decode(&file,imagetype);
}
+#endif
////////////////////////////////////////////////////////////////////////////////
/**
* Loads an image from file handle.
View
9 lib/cximage-6.0/CxImage/ximage.h
@@ -520,6 +520,7 @@ typedef struct tagCxTextInfo
bool Load(const char * filename, DWORD imagetype, int &iWidth, int &iHeight);
bool Decode(FILE * hFile, DWORD imagetype, int &iWidth, int &iHeight);
bool Decode(CxFile * hFile, DWORD imagetype, int &iWidth, int &iHeight);
+ bool Decode(BYTE *buffer, DWORD size, DWORD imagetype, int &iWidth, int &iHeight);
bool Load(const char * filename, DWORD imagetype)
{
int iWidth=0;
@@ -538,12 +539,18 @@ typedef struct tagCxTextInfo
int iHeight=0;
return Decode(hFile, imagetype, iWidth, iHeight);
};
+ bool Decode(BYTE *buffer, unsigned int size, DWORD imagetype)
+ {
+ int iWidth=0;
+ int iHeight=0;
+ return Decode(buffer, size, imagetype, iWidth, iHeight);
+ };
#else
bool Load(const char * filename, DWORD imagetype);
bool Decode(FILE * hFile, DWORD imagetype);
bool Decode(CxFile * hFile, DWORD imagetype);
-#endif
bool Decode(BYTE * buffer, DWORD size, DWORD imagetype);
+#endif
bool CheckFormat(CxFile * hFile, DWORD imagetype = 0);
bool CheckFormat(BYTE * buffer, DWORD size, DWORD imagetype = 0);
View
1  xbmc/Application.cpp
@@ -28,7 +28,6 @@
#include "input/KeyboardLayoutConfiguration.h"
#include "LangInfo.h"
#include "Util.h"
-#include "pictures/Picture.h"
#include "guilib/TextureManager.h"
#include "cores/dvdplayer/DVDFileInfo.h"
#include "cores/AudioEngine/AEFactory.h"
View
2  xbmc/ApplicationMessenger.cpp
@@ -828,7 +828,7 @@ void CApplicationMessenger::MediaPlay(string filename)
{
CFileItem item(filename, false);
if (item.IsAudio())
- item.SetMusicThumb();
+ CMusicThumbLoader::FillThumb(item);
else
CVideoThumbLoader::FillThumb(item);
item.FillInDefaultIcon();
View
205 xbmc/FileItem.cpp
@@ -24,7 +24,6 @@
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "Util.h"
-#include "pictures/Picture.h"
#include "playlists/PlayListFactory.h"
#include "utils/Crc32.h"
#include "filesystem/DirectoryCache.h"
@@ -55,7 +54,6 @@
#include "utils/log.h"
#include "utils/Variant.h"
#include "music/karaoke/karaokelyricsfactory.h"
-#include "ThumbnailCache.h"
#include "utils/Mime.h"
#include "utils/CharsetConverter.h"
@@ -91,10 +89,6 @@ CFileItem::CFileItem(const CStdString &path, const CAlbum& album)
m_strLabel2 = StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator);
URIUtils::AddSlashAtEnd(m_strPath);
GetMusicInfoTag()->SetAlbum(album);
- if (album.thumbURL.m_url.size() > 0)
- m_strThumbnailImage = album.thumbURL.m_url[0].m_url;
- else
- m_strThumbnailImage.clear();
m_bIsAlbum = true;
CMusicDatabase::SetPropertiesFromAlbum(*this,album);
}
@@ -110,7 +104,6 @@ CFileItem::CFileItem(const CMusicInfoTag& music)
m_bIsFolder = URIUtils::HasSlashAtEnd(m_strPath);
*GetMusicInfoTag() = music;
FillInDefaultIcon();
- SetCachedMusicThumb();
}
CFileItem::CFileItem(const CVideoInfoTag& movie)
@@ -1013,31 +1006,6 @@ void CFileItem::FillInDefaultIcon()
}
}
-CStdString CFileItem::GetCachedArtistThumb() const
-{
- return CThumbnailCache::GetArtistThumb(*this);
-}
-
-void CFileItem::SetCachedArtistThumb()
-{
- CStdString thumb(GetCachedArtistThumb());
- if (CFile::Exists(thumb))
- {
- // found it, we are finished.
- SetThumbnailImage(thumb);
- }
-}
-
-// set the album thumb for a file or folder
-void CFileItem::SetMusicThumb(bool alwaysCheckRemote /* = true */)
-{
- if (HasThumbnail()) return;
-
- SetCachedMusicThumb();
- if (!HasThumbnail())
- SetUserMusicThumb(alwaysCheckRemote);
-}
-
void CFileItem::RemoveExtension()
{
if (m_bIsFolder)
@@ -1829,21 +1797,6 @@ void CFileItemList::FillInDefaultIcons()
}
}
-void CFileItemList::SetMusicThumbs()
-{
- CSingleLock lock(m_lock);
- //cache thumbnails directory
- g_directoryCache.InitMusicThumbCache();
-
- for (int i = 0; i < (int)m_items.size(); ++i)
- {
- CFileItemPtr pItem = m_items[i];
- pItem->SetMusicThumb();
- }
-
- g_directoryCache.ClearMusicThumbCache();
-}
-
int CFileItemList::GetFolderCount() const
{
CSingleLock lock(m_lock);
@@ -1992,6 +1945,8 @@ void CFileItemList::FilterCueItems()
SYSTEMTIME dateTime;
tag.GetReleaseDate(dateTime);
if (dateTime.wYear) song.iYear = dateTime.wYear;
+ if (song.embeddedArt.empty() && !tag.GetCoverArtInfo().empty())
+ song.embeddedArt = tag.GetCoverArtInfo();
}
if (!song.iDuration && tag.GetDuration() > 0)
{ // must be the last song
@@ -2444,84 +2399,6 @@ bool CFileItemList::AlwaysCache() const
return false;
}
-void CFileItemList::SetCachedMusicThumbs()
-{
- CSingleLock lock(m_lock);
- // TODO: Investigate caching time to see if it speeds things up
- for (unsigned int i = 0; i < m_items.size(); ++i)
- {
- CFileItemPtr pItem = m_items[i];
- pItem->SetCachedMusicThumb();
- }
-}
-
-void CFileItem::SetCachedMusicThumb()
-{
- // if it already has a thumbnail, then return
- if (HasThumbnail() || m_bIsShareOrDrive) return ;
-
- // streams do not have thumbnails
- if (IsInternetStream()) return ;
-
- // music db items already have thumbs or there is no thumb available
- if (IsMusicDb()) return;
-
- // ignore the parent dir items
- if (IsParentFolder()) return;
-
- CStdString cachedThumb(GetPreviouslyCachedMusicThumb());
- if (!cachedThumb.IsEmpty())
- SetThumbnailImage(cachedThumb);
- // SetIconImage(cachedThumb);
-}
-
-CStdString CFileItem::GetPreviouslyCachedMusicThumb() const
-{
- // look if an album thumb is available,
- // could be any file with tags loaded or
- // a directory in album window
- CStdString strAlbum, strArtist;
- if (HasMusicInfoTag() && m_musicInfoTag->Loaded())
- {
- strAlbum = m_musicInfoTag->GetAlbum();
- if (!m_musicInfoTag->GetAlbumArtist().empty())
- strArtist = StringUtils::Join(m_musicInfoTag->GetAlbumArtist(), g_advancedSettings.m_musicItemSeparator);
- else
- strArtist = StringUtils::Join(m_musicInfoTag->GetArtist(), g_advancedSettings.m_musicItemSeparator);
- }
- if (!strAlbum.IsEmpty() && !strArtist.IsEmpty())
- {
- // try permanent album thumb using "album name + artist name"
- CStdString thumb(CThumbnailCache::GetAlbumThumb(strAlbum, strArtist));
- if (CFile::Exists(thumb))
- return thumb;
- }
-
- // if a file, try to find a cached filename.tbn
- if (!m_bIsFolder)
- {
- // look for locally cached tbn
- CStdString thumb(CThumbnailCache::GetMusicThumb(m_strPath));
- if (CFile::Exists(thumb))
- return thumb;
- }
-
- // try and find a cached folder thumb (folder.jpg or folder.tbn)
- CStdString strPath;
- if (!m_bIsFolder)
- URIUtils::GetDirectory(m_strPath, strPath);
- else
- strPath = m_strPath;
- // music thumbs are cached without slash at end
- URIUtils::RemoveSlashAtEnd(strPath);
-
- CStdString thumb(CThumbnailCache::GetMusicThumb(strPath));
- if (CFile::Exists(thumb))
- return thumb;
-
- return "";
-}
-
CStdString CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */) const
{
if (m_strPath.IsEmpty()
@@ -2554,37 +2431,10 @@ CStdString CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */) co
}
}
}
- // this adds support for files which inherit a folder.jpg icon which has not been cached yet.
- // this occurs when queueing a top-level folder which has not been traversed yet.
- else if (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs"))
- {
- CStdString strFolder, strFile;
- URIUtils::Split(m_strPath, strFolder, strFile);
- if (!m_strPath.Equals(strFolder)) // any more parents to inherit from?
- {
- CFileItem folderItem(strFolder, true);
- folderItem.SetMusicThumb(alwaysCheckRemote);
- if (folderItem.HasThumbnail())
- return folderItem.GetThumbnailImage();
- }
- }
// No thumb found
return "";
}
-void CFileItem::SetUserMusicThumb(bool alwaysCheckRemote /* = false */)
-{
- // caches as the local thumb
- CStdString thumb(GetUserMusicThumb(alwaysCheckRemote));
- if (!thumb.IsEmpty())
- {
- CStdString cachedThumb(CThumbnailCache::GetMusicThumb(m_strPath));
- CPicture::CreateThumbnail(thumb, cachedThumb);
- }
-
- SetCachedMusicThumb();
-}
-
// Gets the .tbn filename from a file or folder name.
// <filename>.ext -> <filename>.tbn
// <foldername>/ -> <foldername>.tbn
@@ -2798,20 +2648,6 @@ bool CFileItem::testGetBaseMoviePath()
}
#endif
-bool CFileItem::CacheLocalFanart() const
-{
- // first check for an already cached fanart image
- CStdString cachedFanart(GetCachedFanart());
- if (CFile::Exists(cachedFanart))
- return true;
-
- // we don't have a cached image, so let's see if the user has a local image, and cache it if so
- CStdString localFanart(GetLocalFanart());
- if (!localFanart.IsEmpty())
- return CPicture::CacheFanart(localFanart, cachedFanart);
- return false;
-}
-
CStdString CFileItem::GetLocalFanart() const
{
if (IsVideoDb())
@@ -2912,43 +2748,6 @@ CStdString CFileItem::GetLocalMetadataPath() const
return parent;
}
-CStdString CFileItem::GetCachedFanart() const
-{
- return CThumbnailCache::GetFanart(*this);
-}
-
-CStdString CFileItem::GetCachedThumb(const CStdString &path, const CStdString &path2, bool split)
-{
- return CThumbnailCache::GetThumb(path, path2, split);
-}
-
-/*void CFileItem::SetThumb()
-{
- // we need to know the type of file at this point
- // as differing views have differing inheritance rules for thumbs:
-
- // Videos:
- // Folders only use <foldername>/folder.jpg or <foldername>.tbn
- // Files use <filename>.tbn
- // * Thumbs are cached from here using file or folder path
-
- // Music:
- // Folders only use <foldername>/folder.jpg or <foldername>.tbn
- // Files use <filename>.tbn or the album/path cached thumb or inherit from the folder
- // * Thumbs are cached from here using file or folder path
-
- // Programs:
- // Folders only use <foldername>/folder.jpg or <foldername>.tbn
- // Files use <filename>.tbn or the embedded xbe. Shortcuts have the additional step of the <thumbnail> tag to check
- // * Thumbs are cached from here using file or folder path
-
- // Pictures:
- // Folders use <foldername>/folder.jpg or <foldername>.tbn, or auto-generated from 4 images in the folder
- // Files use <filename>.tbn or a resized version of the picture
- // * Thumbs are cached from here using file or folder path
-
-}*/
-
bool CFileItem::LoadMusicTag()
{
// not audio
View
33 xbmc/FileItem.h
@@ -153,7 +153,6 @@ class CFileItem :
void RemoveExtension();
void CleanString();
void FillInDefaultIcon();
- void SetMusicThumb(bool alwaysCheckRemote = false);
void SetFileSizeLabel();
virtual void SetLabel(const CStdString &strLabel);
CURL GetAsUrl() const;
@@ -200,33 +199,13 @@ class CFileItem :
CPictureInfoTag* GetPictureInfoTag();
- // Gets the cached thumb filename (no existence checks)
- CStdString GetCachedArtistThumb() const;
- /*!
- \brief Get the cached fanart path for this item if it exists
- \return path to the cached fanart for this item, or empty if none exists
- \sa CacheLocalFanart, GetLocalFanart
- */
- CStdString GetCachedFanart() const;
- static CStdString GetCachedThumb(const CStdString &path, const CStdString& strPath2, bool split=false);
-
- /*!
- \brief Cache a copy of the local fanart for this item if we don't already have an image cached
- \return true if we already have cached fanart or if the caching was successful, false if no image is cached.
- \sa GetLocalFanart, GetCachedFanart
- */
- bool CacheLocalFanart() const;
/*!
\brief Get the local fanart for this item if it exists
\return path to the local fanart for this item, or empty if none exists
- \sa CacheLocalFanart, GetCachedFanart
+ \sa GetFolderThumb, GetTBNFile
*/
CStdString GetLocalFanart() const;
- // Sets the cached thumb for the item if it exists
- void SetCachedArtistThumb();
- void SetCachedMusicThumb();
-
// Gets the .tbn file associated with this item
CStdString GetTBNFile() const;
// Gets the folder image associated with this item (defaults to folder.jpg)
@@ -251,9 +230,6 @@ class CFileItem :
CStdString GetUserVideoThumb() const;
CStdString GetUserMusicThumb(bool alwaysCheckRemote = false) const;
- // Caches the user thumb and assigns it to the item
- void SetUserMusicThumb(bool alwaysCheckRemote = false);
-
/*! \brief Get the path where we expect local metadata to reside.
For a folder, this is just the existing path (eg tvshow folder)
For a file, this is the parent path, with exceptions made for VIDEO_TS and BDMV files
@@ -296,11 +272,7 @@ class CFileItem :
bool IsSamePath(const CFileItem *item) const;
bool IsAlbum() const;
-private:
- // Gets the previously cached thumb file (with existence checks)
- CStdString GetPreviouslyCachedMusicThumb() const;
-public:
bool m_bIsShareOrDrive; ///< is this a root share/drive
int m_iDriveType; ///< If \e m_bIsShareOrDrive is \e true, use to get the share type. Types see: CMediaSource::m_iDriveType
CDateTime m_dateTime; ///< file creation date & time
@@ -405,7 +377,6 @@ class CFileItemList : public CFileItem
void Reserve(int iCount);
void Sort(SORT_METHOD sortMethod, SortOrder sortOrder);
void Randomize();
- void SetMusicThumbs();
void FillInDefaultIcons();
int GetFolderCount() const;
int GetFileCount() const;
@@ -464,8 +435,6 @@ class CFileItemList : public CFileItem
void RemoveDiscCache(int windowID = 0) const;
bool AlwaysCache() const;
- void SetCachedMusicThumbs();
-
void Swap(unsigned int item1, unsigned int item2);
/*! \brief Update an item in the item list
View
18 xbmc/GUIInfoManager.cpp
@@ -75,6 +75,7 @@
#include "addons/AddonManager.h"
#include "interfaces/info/InfoBool.h"
#include "TextureCache.h"
+#include "ThumbLoader.h"
#include "cores/AudioEngine/Utils/AEUtil.h"
#define SYSHEATUPDATEINTERVAL 60000
@@ -3118,8 +3119,8 @@ const CStdString CGUIInfoManager::GetMusicPlaylistInfo(const GUIInfo& info)
// try to set a thumbnail
if (!playlistItem->HasThumbnail())
{
- playlistItem->SetMusicThumb();
- // still no thumb? then just the set the default cover
+ CMusicThumbLoader::FillThumb(*playlistItem);
+ // still no thumb? then just the set the default cover TODO: remove me?
if (!playlistItem->HasThumbnail())
playlistItem->SetThumbnailImage("DefaultAlbumCover.png");
}
@@ -3544,18 +3545,15 @@ void CGUIInfoManager::SetCurrentSong(CFileItem &item)
{
CLog::Log(LOGDEBUG,"Streaming media detected... using %s to find a thumb", g_application.m_strPlayListFile.c_str());
CFileItem streamingItem(g_application.m_strPlayListFile,false);
- streamingItem.SetMusicThumb();
- CStdString strThumb = streamingItem.GetThumbnailImage();
- if (CFile::Exists(strThumb))
- m_currentFile->SetThumbnailImage(strThumb);
+ CMusicThumbLoader::FillThumb(streamingItem);
+ if (streamingItem.HasThumbnail())
+ m_currentFile->SetThumbnailImage(streamingItem.GetThumbnailImage());
}
}
else
- m_currentFile->SetMusicThumb();
- if (!m_currentFile->HasProperty("fanart_image"))
{
- if (m_currentFile->CacheLocalFanart())
- m_currentFile->SetProperty("fanart_image", m_currentFile->GetCachedFanart());
+ CMusicThumbLoader loader;
+ loader.LoadItem(m_currentFile);
}
m_currentFile->FillInDefaultIcon();
View
9 xbmc/GUILargeTextureManager.cpp
@@ -21,7 +21,6 @@
#include "threads/SystemClock.h"
#include "GUILargeTextureManager.h"
-#include "pictures/Picture.h"
#include "settings/GUISettings.h"
#include "FileItem.h"
#include "guilib/Texture.h"
@@ -64,14 +63,10 @@ bool CImageLoader::DoWork()
if (!loadPath.IsEmpty())
{
// direct route - load the image
- m_texture = new CTexture();
unsigned int start = XbmcThreads::SystemClockMillis();
- if (!m_texture->LoadFromFile(loadPath, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), g_guiSettings.GetBool("pictures.useexifrotation")))
- {
- delete m_texture;
- m_texture = NULL;
+ m_texture = CBaseTexture::LoadFromFile(loadPath, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), g_guiSettings.GetBool("pictures.useexifrotation"));
+ if (!m_texture)
return false;
- }
if (XbmcThreads::SystemClockMillis() - start > 100)
CLog::Log(LOGDEBUG, "%s - took %u ms to load %s", __FUNCTION__, XbmcThreads::SystemClockMillis() - start, loadPath.c_str());
View
56 xbmc/TextureCacheJob.cpp
@@ -33,6 +33,8 @@
#include "utils/StringUtils.h"
#include "URL.h"
#include "FileItem.h"
+#include "ThumbLoader.h"
+#include "music/tags/MusicInfoTag.h"
CTextureCacheJob::CTextureCacheJob(const CStdString &url, const CStdString &oldHash)
{
@@ -74,11 +76,11 @@ bool CTextureCacheJob::DoWork()
bool CTextureCacheJob::CacheTexture(CBaseTexture **out_texture)
{
// unwrap the URL as required
- bool flipped;
+ std::string additional_info;
unsigned int width, height;
- CStdString image = DecodeImageURL(m_url, width, height, flipped);
+ CStdString image = DecodeImageURL(m_url, width, height, additional_info);
- m_details.updateable = UpdateableURL(image);
+ m_details.updateable = additional_info != "music" && UpdateableURL(image);
// generate the hash
m_details.hash = GetImageHash(image);
@@ -87,7 +89,7 @@ bool CTextureCacheJob::CacheTexture(CBaseTexture **out_texture)
else if (m_details.hash == m_oldHash)
return true;
- CBaseTexture *texture = LoadImage(image, width, height, flipped);
+ CBaseTexture *texture = LoadImage(image, width, height, additional_info);
if (texture)
{
if (texture->HasAlpha())
@@ -95,12 +97,7 @@ bool CTextureCacheJob::CacheTexture(CBaseTexture **out_texture)
else
m_details.file = m_cachePath + ".jpg";
- if (width > 0 && height > 0)
- CLog::Log(LOGDEBUG, "%s image '%s' at %dx%d with orientation %d as '%s'", m_oldHash.IsEmpty() ? "Caching" : "Recaching", image.c_str(),
- width, height, texture->GetOrientation(), m_details.file.c_str());
- else
- CLog::Log(LOGDEBUG, "%s image '%s' fullsize with orientation %d as '%s'", m_oldHash.IsEmpty() ? "Caching" : "Recaching", image.c_str(),
- texture->GetOrientation(), m_details.file.c_str());
+ CLog::Log(LOGDEBUG, "%s image '%s' to '%s':", m_oldHash.IsEmpty() ? "Caching" : "Recaching", image.c_str(), m_details.file.c_str());
if (CPicture::CacheTexture(texture, width, height, CTextureCache::GetCachedPath(m_details.file)))
{
@@ -117,20 +114,24 @@ bool CTextureCacheJob::CacheTexture(CBaseTexture **out_texture)
return false;
}
-CStdString CTextureCacheJob::DecodeImageURL(const CStdString &url, unsigned int &width, unsigned int &height, bool &flipped)
+CStdString CTextureCacheJob::DecodeImageURL(const CStdString &url, unsigned int &width, unsigned int &height, std::string &additional_info)
{
// unwrap the URL as required
CStdString image(url);
- flipped = false;
- width = g_advancedSettings.m_fanartHeight * 16/9;
- height = g_advancedSettings.m_fanartHeight;
+ additional_info.clear();
+ width = height = 0;
if (url.compare(0, 8, "image://") == 0)
{
// format is image://[type@]<url_encoded_path>?options
CURL thumbURL(url);
if (!thumbURL.GetUserName().IsEmpty())
- return ""; // we don't re-cache special images (eg picturefolder/video embedded thumbs)
+ {
+ if (thumbURL.GetUserName() == "music")
+ additional_info = "music";
+ else
+ return ""; // we don't re-cache special images (eg picturefolder/video embedded thumbs)
+ }
image = thumbURL.GetHostName();
CURL::Decode(image);
@@ -156,35 +157,40 @@ CStdString CTextureCacheJob::DecodeImageURL(const CStdString &url, unsigned int
}
if (option == "size" && value == "thumb")
{
- width = height = g_advancedSettings.m_thumbSize;
+ width = height = g_advancedSettings.GetThumbSize();
}
else if (option == "flipped")
{
- flipped = true;
+ additional_info = "flipped";
}
}
}
return image;
}
-CBaseTexture *CTextureCacheJob::LoadImage(const CStdString &image, unsigned int width, unsigned int height, bool flipped)
+CBaseTexture *CTextureCacheJob::LoadImage(const CStdString &image, unsigned int width, unsigned int height, const std::string &additional_info)
{
+ if (additional_info == "music")
+ { // special case for embedded music images
+ MUSIC_INFO::EmbeddedArt art;
+ if (CMusicThumbLoader::GetEmbeddedThumb(image, art))
+ return CBaseTexture::LoadFromFileInMemory(&art.data[0], art.size, art.mime, width, height);
+ }
+
// Validate file URL to see if it is an image
CFileItem file(image, false);
if (!(file.IsPicture() && !(file.IsZIP() || file.IsRAR() || file.IsCBR() || file.IsCBZ() ))
&& !file.GetMimeType().Left(6).Equals("image/")) // ignore non-pictures
return NULL;
- CTexture *texture = new CTexture();
- if (!texture->LoadFromFile(image, width, height, g_guiSettings.GetBool("pictures.useexifrotation")))
- {
- delete texture;
+ CBaseTexture *texture = CBaseTexture::LoadFromFile(image, width, height, g_guiSettings.GetBool("pictures.useexifrotation"));
+ if (!texture)
return NULL;
- }
+
// EXIF bits are interpreted as: <flipXY><flipY*flipX><flipX>
// where to undo the operation we apply them in reverse order <flipX>*<flipY*flipX>*<flipXY>
- // When flipped = true we have an additional <flipX> on the left, which is equivalent to toggling the last bit
- if (flipped)
+ // When flipped we have an additional <flipX> on the left, which is equivalent to toggling the last bit
+ if (additional_info == "flipped")
texture->SetOrientation(texture->GetOrientation() ^ 1);
return texture;
View
8 xbmc/TextureCacheJob.h
@@ -100,10 +100,10 @@ class CTextureCacheJob : public CJob
\param url wrapped URL of the image
\param width width derived from URL
\param height height derived from URL
- \param flipped whether the image is flipped horizontally
+ \param additional_info additional information, such as "flipped" to flip horizontally
\return URL of the underlying image file.
*/
- static CStdString DecodeImageURL(const CStdString &url, unsigned int &width, unsigned int &height, bool &flipped);
+ static CStdString DecodeImageURL(const CStdString &url, unsigned int &width, unsigned int &height, std::string &additional_info);
/*! \brief Load an image at a given target size and orientation.
@@ -113,10 +113,10 @@ class CTextureCacheJob : public CJob
\param image the URL of the image file.
\param width the desired maximum width.
\param height the desired maximum height.
- \param flipped whether the image should be flipped horizontally.
+ \param additional_info extra info for loading, such as whether to flip horizontally.
\return a pointer to a CBaseTexture object, NULL if failed.
*/
- static CBaseTexture *LoadImage(const CStdString &image, unsigned int width, unsigned int height, bool flipped);
+ static CBaseTexture *LoadImage(const CStdString &image, unsigned int width, unsigned int height, const std::string &additional_info);
CStdString m_cachePath;
};
View
137 xbmc/ThumbLoader.cpp
@@ -23,7 +23,6 @@
#include "ThumbLoader.h"
#include "utils/URIUtils.h"
#include "URL.h"
-#include "pictures/Picture.h"
#include "filesystem/File.h"
#include "filesystem/DirectoryCache.h"
#include "FileItem.h"
@@ -37,10 +36,15 @@
#include "video/VideoDatabase.h"
#include "cores/dvdplayer/DVDFileInfo.h"
#include "video/VideoInfoScanner.h"
+#include "music/tags/MusicInfoTag.h"
+#include "music/tags/MusicInfoTagLoaderFactory.h"
+#include "music/infoscanner/MusicInfoScanner.h"
+#include "music/Artist.h"
using namespace XFILE;
using namespace std;
using namespace VIDEO;
+using namespace MUSIC_INFO;
CThumbLoader::CThumbLoader(int nThreads) :
CBackgroundInfoLoader(nThreads)
@@ -295,6 +299,22 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem *pItem)
m_database->Open();
if (m_database->GetArtForItem(tag.m_iDbId, tag.m_type, artwork))
pItem->SetArt(artwork);
+ else if (pItem->GetVideoInfoTag()->m_type == "artist")
+ { // we retrieve music video art from the music database (no backward compat)
+ CMusicDatabase database;
+ database.Open();
+ int idArtist = database.GetArtistByName(pItem->GetLabel());
+ if (database.GetArtForItem(idArtist, "artist", artwork))
+ pItem->SetArt(artwork);
+ }
+ else if (pItem->GetVideoInfoTag()->m_type == "album")
+ { // we retrieve music video art from the music database (no backward compat)
+ CMusicDatabase database;
+ database.Open();
+ int idAlbum = database.GetAlbumByName(pItem->GetLabel(), pItem->GetVideoInfoTag()->m_artist);
+ if (database.GetArtForItem(idAlbum, "album", artwork))
+ pItem->SetArt(artwork);
+ }
else
{
if (tag.m_type == "movie" || tag.m_type == "episode" ||
@@ -321,7 +341,7 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem *pItem)
pItem->SetArt(items[0]->GetArt());
}
}
- else if (tag.m_type == "actor" || tag.m_type == "artist" ||
+ else if (tag.m_type == "actor" ||
tag.m_type == "writer" || tag.m_type == "director")
{
// We can't realistically get the local thumbs (as we'd need to check every movie that contains this actor)
@@ -485,19 +505,126 @@ CStdString CProgramThumbLoader::GetLocalThumb(const CFileItem &item)
return "";
}
-CMusicThumbLoader::CMusicThumbLoader()
+CMusicThumbLoader::CMusicThumbLoader() : CThumbLoader(1)
{
+ m_database = new CMusicDatabase;
}
CMusicThumbLoader::~CMusicThumbLoader()
{
+ delete m_database;
+}
+
+void CMusicThumbLoader::OnLoaderStart()
+{
+ m_database->Open();
+}
+
+void CMusicThumbLoader::OnLoaderFinish()
+{
+ m_database->Close();
}
bool CMusicThumbLoader::LoadItem(CFileItem* pItem)
{
- if (pItem->m_bIsShareOrDrive) return true;
+ if (pItem->m_bIsShareOrDrive)
+ return true;
+
+ if (pItem->HasMusicInfoTag() && pItem->GetArt().empty())
+ {
+ if (FillLibraryArt(*pItem))
+ return true;
+ if (pItem->GetMusicInfoTag()->GetType() == "artist")
+ return true; // no fallback
+ }
+
+ if (!pItem->HasProperty("fanart_image"))
+ {
+ if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetArtist().empty())
+ {
+ std::string artist = pItem->GetMusicInfoTag()->GetArtist()[0];
+ m_database->Open();
+ int idArtist = m_database->GetArtistByName(artist);
+ if (idArtist >= 0)
+ {
+ string fanart = m_database->GetArtForItem(idArtist, "artist", "fanart");
+ if (!fanart.empty())
+ pItem->SetProperty("fanart_image", fanart);
+ }
+ m_database->Close();
+ }
+ }
+
if (!pItem->HasThumbnail())
- pItem->SetUserMusicThumb();
+ FillThumb(*pItem);
+
return true;
}
+bool CMusicThumbLoader::FillThumb(CFileItem &item)
+{
+ if (item.HasThumbnail())
+ return true;
+ CStdString thumb = GetCachedImage(item, "thumb");
+ if (thumb.IsEmpty())
+ {
+ thumb = item.GetUserMusicThumb();
+ if (!thumb.IsEmpty())
+ SetCachedImage(item, "thumb", thumb);
+ }
+ item.SetThumbnailImage(thumb);
+ return !thumb.IsEmpty();
+}
+
+bool CMusicThumbLoader::FillLibraryArt(CFileItem &item)
+{
+ CMusicInfoTag &tag = *item.GetMusicInfoTag();
+ if (tag.GetDatabaseId() > -1 && !tag.GetType().empty())
+ {
+ m_database->Open();
+ map<string, string> artwork;
+ if (m_database->GetArtForItem(tag.GetDatabaseId(), tag.GetType(), artwork))
+ item.SetArt(artwork);
+ else if (tag.GetType() == "song")
+ { // no art for the song, try the album
+ if (m_database->GetArtForItem(tag.GetAlbumId(), "album", artwork))
+ item.SetArt(artwork);
+ }
+ else if (tag.GetType() == "artist")
+ {
+ { // Need the artist thumb/fanart which isn't grabbed during normal directory fetches
+ CArtist artist;
+ m_database->GetArtistInfo(tag.GetDatabaseId(), artist, false);
+ CMusicInfoScanner scanner;
+ artwork = scanner.GetArtistArtwork(tag.GetDatabaseId(), &artist);
+ item.SetArt(artwork);
+ }
+ // add to the database for next time around
+ map<string, string> artwork = item.GetArt();
+ if (!artwork.empty())
+ {
+ m_database->SetArtForItem(tag.GetDatabaseId(), tag.GetType(), artwork);
+ for (map<string, string>::iterator i = artwork.begin(); i != artwork.end(); ++i)
+ CTextureCache::Get().BackgroundCacheImage(i->second);
+ }
+ else // nothing found - set an empty thumb so that next time around we don't hit here again
+ m_database->SetArtForItem(tag.GetDatabaseId(), tag.GetType(), "thumb", "");
+ }
+ if (tag.GetType() == "song" || tag.GetType() == "album")
+ { // fanart from the artist
+ item.SetProperty("fanart_image", m_database->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart"));
+ }
+ m_database->Close();
+ }
+ return !item.GetArt().empty();
+}
+
+bool CMusicThumbLoader::GetEmbeddedThumb(const std::string &path, EmbeddedArt &art)
+{
+ auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(path));
+ CMusicInfoTag tag;
+ if (NULL != pLoader.get())
+ pLoader->Load(path, tag, &art);
+
+ return !art.empty();
+}
View
28 xbmc/ThumbLoader.h
@@ -30,6 +30,7 @@
class CStreamDetails;
class IStreamDetailsObserver;
class CVideoDatabase;
+class CMusicDatabase;
/*!
\ingroup thumbs,jobs
@@ -155,11 +156,38 @@ class CProgramThumbLoader : public CThumbLoader
static CStdString GetLocalThumb(const CFileItem &item);
};
+namespace MUSIC_INFO
+{
+ class EmbeddedArt;
+};
+
class CMusicThumbLoader : public CThumbLoader
{
public:
CMusicThumbLoader();
virtual ~CMusicThumbLoader();
virtual bool LoadItem(CFileItem* pItem);
+
+ /*! \brief helper function to fill the art for a video library item
+ \param item a video CFileItem
+ \return true if we fill art, false otherwise
+ */
+ bool FillLibraryArt(CFileItem &item);
+
+ /*! \brief Fill the thumb of a music file/folder item
+ First uses a cached thumb from a previous run, then checks for a local thumb
+ and caches it for the next run
+ \param item the CFileItem object to fill
+ \return true if we fill the thumb, false otherwise
+ */
+ static bool FillThumb(CFileItem &item);
+
+ static bool GetEmbeddedThumb(const std::string &path, MUSIC_INFO::EmbeddedArt &art);
+
+protected:
+ virtual void OnLoaderStart();
+ virtual void OnLoaderFinish();
+
+ CMusicDatabase *m_database;
};
#endif
View
162 xbmc/ThumbnailCache.cpp
@@ -60,165 +60,3 @@ CThumbnailCache* CThumbnailCache::GetThumbnailCache()
return m_pCacheInstance;
}
-
-bool CThumbnailCache::ThumbExists(const CStdString& strFileName, bool bAddCache /*=false*/)
-{
- CSingleLock lock (m_cs);
-
- if (strFileName.size() == 0) return false;
- map<CStdString, bool>::iterator it;
- it = m_Cache.find(strFileName);
- if (it != m_Cache.end())
- return it->second;
-
- bool bExists = CFile::Exists(strFileName);
-
- if (bAddCache)
- Add(strFileName, bExists);
- return bExists;
-}
-
-bool CThumbnailCache::IsCached(const CStdString& strFileName)
-{
- CSingleLock lock (m_cs);
-
- map<CStdString, bool>::iterator it;
- it = m_Cache.find(strFileName);
- return it != m_Cache.end();
-}
-
-void CThumbnailCache::Clear()
-{
- CSingleLock lock (m_cs);
-
- if (m_pCacheInstance != NULL)
- {
- m_Cache.erase(m_Cache.begin(), m_Cache.end());
- delete m_pCacheInstance;
- }
-
- m_pCacheInstance = NULL;
-}
-
-void CThumbnailCache::Add(const CStdString& strFileName, bool bExists)
-{
- CSingleLock lock (m_cs);
-
- map<CStdString, bool>::iterator it;
- it = m_Cache.find(strFileName);
- if (it != m_Cache.end())
- it->second = bExists;
- else
- m_Cache.insert(pair<CStdString, bool>(strFileName, bExists));
-}
-
-CStdString CThumbnailCache::GetAlbumThumb(const CFileItem &item)
-{
- return GetAlbumThumb(item.GetMusicInfoTag());
-}
-
-CStdString CThumbnailCache::GetAlbumThumb(const CMusicInfoTag *musicInfo)
-{
- if (!musicInfo)
- return CStdString();
-
- return GetAlbumThumb(musicInfo->GetAlbum(), StringUtils::Join(!musicInfo->GetAlbumArtist().empty() ? musicInfo->GetAlbumArtist() : musicInfo->GetArtist(), g_advancedSettings.m_musicItemSeparator));
-}
-
-CStdString CThumbnailCache::GetAlbumThumb(const CAlbum &album)
-{
- return GetAlbumThumb(album.strAlbum, StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator));
-}
-
-CStdString CThumbnailCache::GetAlbumThumb(const CStdString& album, const CStdString& artist)
-{
- if (album.IsEmpty())
- return GetMusicThumb("unknown" + artist);
- if (artist.IsEmpty())
- return GetMusicThumb(album + "unknown");
- return GetMusicThumb(album + artist);
-}
-
-CStdString CThumbnailCache::GetArtistThumb(const CFileItem &item)
-{
- return GetArtistThumb(item.GetLabel());
-}
-
-CStdString CThumbnailCache::GetArtistThumb(const CArtist &artist)
-{
- return GetArtistThumb(artist.strArtist);
-}
-
-CStdString CThumbnailCache::GetArtistThumb(const CStdString &label)
-{
- return GetThumb("artist" + label, g_settings.GetMusicArtistThumbFolder());
-}
-
-CStdString CThumbnailCache::GetFanart(const CFileItem &item)
-{
- // get the locally cached thumb
- if (item.IsVideoDb() || (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->IsEmpty()))
- {
- if (!item.HasVideoInfoTag())
- return "";
- if (!item.GetVideoInfoTag()->m_artist.empty())
- return GetThumb(StringUtils::Join(item.GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator),g_settings.GetMusicFanartFolder());
- if (!item.m_bIsFolder && !item.GetVideoInfoTag()->m_strShowTitle.IsEmpty())
- {
- CStdString showPath;
- if (!item.GetVideoInfoTag()->m_strShowPath.IsEmpty())
- showPath = item.GetVideoInfoTag()->m_strShowPath;
- else
- {
- CVideoDatabase database;
- database.Open();
- int iShowId = item.GetVideoInfoTag()->m_iIdShow;
- if (iShowId <= 0)
- iShowId = database.GetTvShowId(item.GetVideoInfoTag()->m_strPath);
- CStdString showPath;
- database.GetFilePathById(iShowId,showPath,VIDEODB_CONTENT_TVSHOWS);
- }
- return GetThumb(showPath,g_settings.GetVideoFanartFolder());
- }
- CStdString path = item.GetVideoInfoTag()->GetPath();
- if (path.empty())
- return "";
- return GetThumb(path,g_settings.GetVideoFanartFolder());
- }
- if (item.HasMusicInfoTag())
- return GetThumb(StringUtils::Join(item.GetMusicInfoTag()->GetArtist(), g_advancedSettings.m_musicItemSeparator),g_settings.GetMusicFanartFolder());
-
- return GetThumb(item.GetPath(),g_settings.GetVideoFanartFolder());
-}
-
-CStdString CThumbnailCache::GetThumb(const CStdString &path, const CStdString &path2, bool split /* = false */)
-{
- // get the locally cached thumb
- Crc32 crc;
- crc.ComputeFromLowerCase(path);
-
- CStdString thumb;
- if (split)
- {
- CStdString hex;
- hex.Format("%08x", (__int32)crc);
- thumb.Format("%c\\%08x.tbn", hex[0], (unsigned __int32)crc);
- }
- else
- thumb.Format("%08x.tbn", (unsigned __int32)crc);
-
- return URIUtils::AddFileToFolder(path2, thumb);
-}
-
-CStdString CThumbnailCache::GetMusicThumb(const CStdString& path)
-{
- Crc32 crc;
- CStdString noSlashPath(path);
- URIUtils::RemoveSlashAtEnd(noSlashPath);
- crc.ComputeFromLowerCase(noSlashPath);
- CStdString hex;
- hex.Format("%08x", (unsigned __int32) crc);
- CStdString thumb;
- thumb.Format("%c/%s.tbn", hex[0], hex.c_str());
- return URIUtils::AddFileToFolder(g_settings.GetMusicThumbFolder(), thumb);
-}
View
16 xbmc/ThumbnailCache.h
@@ -42,26 +42,10 @@ class CThumbnailCache
virtual ~CThumbnailCache();
static CThumbnailCache* GetThumbnailCache();
- bool ThumbExists(const CStdString& strFileName, bool bAddCache = false);
- void Add(const CStdString& strFileName, bool bExists);
- void Clear();
- bool IsCached(const CStdString& strFileName);
- static CStdString GetMusicThumb(const CStdString &path);
- static CStdString GetAlbumThumb(const CFileItem &item);
- static CStdString GetAlbumThumb(const MUSIC_INFO::CMusicInfoTag *musicInfo);
- static CStdString GetAlbumThumb(const CAlbum &album);
- static CStdString GetAlbumThumb(const CStdString &album, const CStdString &artist);
- static CStdString GetArtistThumb(const CArtist &artist);
- static CStdString GetArtistThumb(const CFileItem &item);
- static CStdString GetArtistThumb(