Author Topic: Get unique Albums and Artwork  (Read 6296 times)

BoringName

  • Full Member
  • ***
  • Posts: 201
For the coverflow plugin I'm working on, I need to get a list of unique Albums with a source to their artwork so I can generate the scroll of albums.

At this stage my plan was to use Library_QueryFilesEx and iterate through it to grab all the unique albums and use the first song of each unique album found as a reference to link to the artwork for that album.
Changing the query to only grab files with a track and disc number of 1 would be perfect but it falls over if the those fields are blank.
I tried grabbing all files with a track and disc number less than 2. This grabs all the track number 1 songs and those with blank fields but obviously this still needs to be iterated over to remove duplicate albums.

Is there a better way I'm missing?

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
this is a query you could use. You can use the xml from an auto-playlist if you want to tweak things
Code
<Conditions CombineMethod="All">
  <Condition Field="TrackNo" Comparison="Is" Value="1" />
  <Condition Field="DiscNo" Comparison="IsNull">
<Or CombineMethod="Any">
  <Condition Field="DiscNo" Comparison="Is" Value="1" />
</Or>
  </Condition>
</Conditions>
keep in mind tracks for some albums could be numbered like 'A1', 'A2'

Lastly I suggest using the field: AlbumUniqueId = 108 to identify albums which incorporates configuration from the user's album grouping preferences

BoringName

  • Full Member
  • ***
  • Posts: 201
keep in mind tracks for some albums could be numbered like 'A1', 'A2'

Lastly I suggest using the field: AlbumUniqueId = 108 to identify albums which incorporates configuration from the user's album grouping preferences

I hadn't considered different album numbering formats. That could be problematic.

I'm not sure it really matters anyway. I just grabbed the whole library with Library_QueryFilesEx and iterated through it. My test library is a bit trash but it's 846 songs and my iteration was basically instant. I'll test it on my partners library (30,000 songs) when I've cleaned it up a bit more

I tried filtering out duplicates but it wasn't the best result, albums with various artists got added a few times as I compared artist and album for uniqueness. (different artists can have albums with the same name).  I guess I need to reference album artist as well and users will just have to tidy up their libraries.

I'll nut it out.

I don't have an "AlbumUniqueId" field when creating an auto playlist. What does it do exactly?

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
use AlbumUniqueId instead of AlbumName to split files by album

BoringName

  • Full Member
  • ***
  • Posts: 201
use AlbumUniqueId instead of AlbumName to split files by album

Thanks. I just needed to get a newer version of MusicBeeInterface.cs

I can see that tag now.

FYI - The plugin is actually working. It's in it's own separate window at the moment but it's displaying all the albums with artwork and I can scroll from one end to the other with no problems. It's pretty cool.
The album art is fairly low res, the higher quality images look better. I need to clean the library up a bit and get more artwork. It's just an old library I kept for dads ipod nano so it's had no love at all.


edit: hmm, image link didn't work, let's try again....

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
screenshot looks really good

if you use Library_GetArtworkEx then the raw byte data is returned without any resolution adjustment
if you prefer to deal with url's for the artwork then use:
Library_GetArtworkUrl(fileUrl, 0)
although this is less efficient for artwork embedded in music files and i don't recommend it

also let me know if you want to implement an embedded panel or its own tab

BoringName

  • Full Member
  • ***
  • Posts: 201
Yep, I'm using GetArtworkEx, my comments about the quality were more to do with the low quality artwork I have used on this library. Some of the albums have good quality artwork and it looks good when rendered.

The AlbumUniqueId field was a total winner. It does exactly what I need without having to worry about track numbers etc....

I currently have it scrolling to the correct album when a song is played via the TrackChanged notification. Is there any way to interact with the files element on the Main Panel? In iTunes you could just select a song (highlight it without playing) and it would scroll to it's album cover, or if you scrolled to an album in the cover flow it would select the first song from that album in the files list. If I can get that working I think I'm pretty much done functionality wise.

As for embedding or tab..... I initially thought it could go in the top panel, that would make it similar to iTunes. I guess it could work in it's own tab as well...

The issue is I'm winging most of this so I really have no idea how to implement that, I'm amazed I've gotten it this far. It's a WPF class library with a SharpGL control, I'm not sure if I can just run that inside a forms panel. If I can that should make things easier, I think... I'd just hide the title bar.

Looks like I need to read up on the ElementHost class and use it with Plugin.MbApiInterface.MB_AddPanel(null , PluginPanelDock.ApplicationWindow)?

edit: or maybe OnDockablePanelCreated.... i'll do some research.
Last Edit: January 14, 2023, 05:26:58 AM by BoringName

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
if you want to include a file list showing the files associated with the in-focus album that is integrated with musicbee eg. skin colouring, right click context menus etc then i can add support to the api - let me know if you want that.

i recommend using
mbApiInterface.MB_AddPanel(panel, PluginPanelDock.MainPanel)
where panel is a win forms control class or derivative such as UserControl or Panel where MB supports it as a dedicated tab that is automatically resized

PluginPanelDock.ApplicationWindow was created for the theatre mode plugin where the window takes over the full application window

BoringName

  • Full Member
  • ***
  • Posts: 201
So it wasn't as hard as I thought it was going to be, I just changed everything in the project that said "Window" to "UserControl". Then used an ElementHost with the panel created by OnDockablePanelCreated.



It works in any of the panels but I can't change the height in certain spots, like if I put it above files in the main panel (pictured). If I put it underneath the files panel it fills the screen to the right and I can adjust it's height. I guess I can just set the height in the code and show it as an option in the config panel.

Mouse wheel events are not registering. I have it programmed to move one album left or right when the mouse wheel was rolled but it's not doing anything, I think its something do with it not getting focus. Not a big deal. Mouse clicks work fine. I have a right click context menu that is showing up allowing the user to change how the albums flow and the skin. So I don't need any special mouse controls.

What would be good is having the same behaviour as the "Track Information" panel. When you click on a song it changes to the show the track info. If I could set this plugin up so when the user clicks on a song, the cover flow scrolls to that album it will be exactly how iTunes cover flow used to work. Currently its only doing that when a song is played.

One downside is CPU usage sits on 10-12% even if musicbee is minimised, basically because it's drawing that window constantly even when it's just static. Limiting FPS to 30 instead of 60 gets it to 6%. But I have a feeling it's going to be a bit worse with higher quality artwork. When it's unlimited it's maxing out around 100fps and it should be a lot higher than that with my current hardware, I need to go over the code again.

Still a few more things to fix up in the background but it's almost ready for release. Pretty happy with it so far.


Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
MB already notifies when the selected file in the main panel changes but i see i forgot to add to the interface file.
Just manually add these 2 enums to NotificationType
Code
PlaylistMoved = 40,
SelectedFileChanged = 41
when you receive the notification, to get the selected file(s) call
Code
string[] files;
Library_QueryFilesEx("domain=SelectedFiles", files)
if you want to make the cover flow sensitive to the displayed files eg. user is viewing audiobooks
Code
string[] files;
Library_QueryFilesEx("domain=DisplayedFiles", files)

BoringName

  • Full Member
  • ***
  • Posts: 201
MB already notifies when the selected file in the main panel changes but i see i forgot to add to the interface file.
Just manually add these 2 enums to NotificationType
Code
PlaylistMoved = 40,
SelectedFileChanged = 41

I've added these into the MusicBeeInterface.cs and added SelectedFileChanged into the notification handler but it doesn't appear to be triggering. I have ReceiveNotificatonFlags.PlayerEvents set. I tried changing this to the other options but it didn't work. I tried on the music tab and also any other tab that showed files. It didn't trigger on any of them.

I tracked what events triggered and SelectedFileChanged didn't show up at all but I did find some events that seem to be triggering more than they should.

When I right click a song and select "Play Now", these notifications trigger in this order -
PlayStateChanged
NowPlayingListChanged
PlayingTracksChanged
PlayStateChanged
TrackChanged
NowPlayingListChanged
PlayingTracksChanged

Thanks for all your help with this!

edit: I'm using 3.5.8402 which appears to be the latest version.
Last Edit: January 15, 2023, 09:47:15 PM by BoringName

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
my mistake - that enum is internal to MB. Instead create a public function in the plugin
Code
public void OnSelectedFilesChanged(string[] urls)

BoringName

  • Full Member
  • ***
  • Posts: 201
That did the trick. Thanks.

Now I just need to sort out the CPU usage, iTunes drops to zero when the cover flow isn't scrolling so there must be a way stop OpenGL drawing and display the scene as a static image when it isn't changing. I have more reading to do....

edit: figured out the CPU but it's going to take a bit of re-coding. Anyway, on the home stretch to getting this done.
Last Edit: January 15, 2023, 10:56:04 PM by BoringName

BoringName

  • Full Member
  • ***
  • Posts: 201
CPU usage is sorted.
I also got the mouse wheel working. For some reason I had to set the moue wheel event on the panel even though I didn't need to do that for clicks.

I just have one last problem that I spent all day on and just can't figure it out.

I have a timer setup to run the render command when certain things happen. I currently have a trigger setup in OnSelectedFilesChanged which works perfectly. When I select a song in the file list or in the autoDJ list, the cover flow will rotate through to the selected album with no problems.

I also have the exact same trigger setup in the ReceiveNotification void set to trigger when it receives the TrackChanged event. I had to set this one up as an Invoke as I would occasionally get errors about it being a different thread.... probably relevant to the issue.

This trigger loops the openGL render command on a tick timer to a set FPS until the animation has finished reaching the selected album and then it stops the timer to wait for the next trigger.

Here is the bit I can't figure out.
If the timer is currently stopped when the autoDJ changes to the next track, the openGL wont move at all until I move the mouse over it and then it will do the full animation. So the trigger is working but it just doesn't start until I move the mouse over the panel.
If the timer is active from the previous song and the autoDJ changes to the next track, the cover flow moves to the album like it should. Eg) If I right click a track and select play now, the cover flow will start moving to that album and then if I move the slider to the end of the song so the next one plays almost immediately it works.

So I think it's some kind of weird focus issue with the panel. When the autoDJ changes tracks it's like the panel is paused until I mouse over it. There is every chance it's my terrible coding but I have tried everything today and hit a brick wall every time. I've tried using Invoke and BeginInvoke but it's the same result.

It's just super weird the trigger in OnSelectedFilesChanged works fine but the trigger on the notification one doesn't. They are both in the Plugin Class but I'm guessing it's some kind of thread issue?

Steven

  • Administrator
  • Sr. Member
  • *****
  • Posts: 34313
It's just super weird the trigger in OnSelectedFilesChanged works fine but the trigger on the notification one doesn't. They are both in the Plugin Class but I'm guessing it's some kind of thread issue?
The OnSelectedFilesChanged event is called on the GUI thread. Other notifications are sent in a separate plugin thread, so you might need to invoke those events on to the GUI thread if OnSelectedFilesChanged  works