Author Topic: Plugin or Feature to snapshot entire library in current view to image file  (Read 2770 times)

SonicRings

  • Sr. Member
  • ****
  • Posts: 295
Might be a weird request to make, but I would really like to be able to essentially take a snapshot of my current library and have it save it to an image, to visually represent my library. Similar to taking a scrolling screenshot and stitching them all together. I was thinking there'd be an option below "View Library Stats" in File.

Any thoughts or ideas? Is there an easy way of accomplishing this? Perhaps a plugin if Steven doesn't find it worth making?
Last Edit: December 13, 2020, 09:57:48 AM by SonicRings

SonicRings

  • Sr. Member
  • ****
  • Posts: 295
Here are some example snapshots I manually made by stitching screenshots together in Photoshop:



It would be super convenient if we could make such screenshots with the press of a button.
Last Edit: April 20, 2021, 03:43:44 AM by phred

phred

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 10278
I deleted your other screenshots as they were terribly large and we get the idea with just the one I left.
Download the latest MusicBee v3.6 patch from here.
Unzip into your MusicBee directory and overwrite existing files.

----------
The FAQ
The Wiki
Custom Forum Search
Posting screenshots is here


BoringName

  • Sr. Member
  • ****
  • Posts: 920
This shouldn't be too complicated but I'm busy with other things. But I will supply some code that will probably come in handy for anyone that wants to take it on.

Use it at your own risk. It works for me but I'm not going to pretend I know what I'm doing.... there could be a better way.

This code iterates through all the songs in the musicbee library and creates a list (albums_) of all the albums. it then sorts the list based on the sortmask.

Code
namespace MusicBeePlugin
{
    //album structure
    public struct Album
    {
        public string artist;
        public string name;
        public string cover;
        public string sortMask;
        public string albumId;
        public bool isLoaded;

        public Album(string artist, string name, string cover, string sortMask, string albumId, bool isLoaded)
        {
            this.artist = artist;
            this.name = name;
            this.cover = cover;
            this.sortMask = sortMask;
            this.albumId = albumId;
            this.isLoaded = isLoaded;
        }
    }

    //-------------------
    // Class to handle loading albums
    //-------------------
    
    public class AlbumsLoader
    {
        // album list
        public static List<Album> albums_ = new();

        public static int GetAlbumsCount()
        {
            return albums_.Count;
        }

        public static string GetAlbumCover(int index)
        {
            return albums_[index].cover;
        }
        
        public static string GetAlbumName(int index)
        {
            return albums_[index].name;
        }

        public static string GetAlbumArtist(int index)
        {
           return albums_[index].artist;
        }

        public static string GetAlbumId(int index)
        {
            return albums_[index].albumId;
        }

        // ------------------------------------
        // Query Musicbee for all unique albums
        // ------------------------------------
        public static void LoadAlbums()
        {
            int index;
            
            // get a list of songs from musicbee
            Plugin.MbApiInterface.Library_QueryFilesEx("domain=Library", out string[]? files);

            //only load what is in the files element.
            //Plugin.MbApiInterface.Library_QueryFilesEx("domain=DisplayedFiles", out files);

            //find unique albums and add them to the albums_ list.
            if (files.Length != 0)
            {
                foreach (string file in files)
                {
                    string currentAlbum = Plugin.MbApiInterface.Library_GetFileTag(file, Plugin.MetaDataType.Album);
                    string currentArtist = Plugin.MbApiInterface.Library_GetFileTag(file, Plugin.MetaDataType.AlbumArtist);
                    string uniqueAlbumId = Plugin.MbApiInterface.Library_GetFileTag(file, Plugin.MetaDataType.AlbumUniqueId);
                    string sortMask = Plugin.MbApiInterface.Library_GetFileTag(file, Plugin.MetaDataType.SortAlbumArtist);
                    string sortAlbum = Plugin.MbApiInterface.Library_GetFileTag(file, Plugin.MetaDataType.SortAlbum);

                    // if sortalbum exists, append the first 3 letters to the sort mask to make sorting better for
                    //artists with multiple albums.
                    if (!string.IsNullOrEmpty(sortAlbum) && sortAlbum.Length > 2)
                    {
                        sortMask += sortAlbum.Substring(0, 3);
                    }

                    //check if album already exists
                    index = albums_.FindIndex(x => x.albumId == uniqueAlbumId); //currentAlbum

                    if(index == -1) {
                        Album a = new Album(currentArtist,currentAlbum,file,sortMask,uniqueAlbumId, false);
                        albums_.Add(a);
                    }
                }
            }
            albums_.Sort((x, y) => x.sortMask.CompareTo(y.sortMask));
            files = null;
        }
    }
}

Once you have the albums_ list populated, you just need to iterate through it to get all the covers out and mash them together to make your snapshot.

Something like
Code
foreach (Album a in albums_)
{
    Plugin.MbApiInterface.Library_GetArtworkEx(a.cover, 0, true, out Plugin.PictureLocations pictureLocation, out string pictureUrl, out byte[]? imageData);
    if (imageData != null)
    {
        using (var ms = new MemoryStream(imageData))
            {
                bmp = new Bitmap(ms);
            }
        // insert code here to format the bmp and append it to your snapshot image
        // you can use a.artist and a.name to get the artist and album name
        bmp = null;
    } else {
            // insert code here to handle albums that don't have artwork
    }
        imageData = null;
}

I don't know if it's necessary to set bmp and imageData to null afterwards but it seemed to work better for memory management.

You will need code to format the BMP to the right size, set number of albums per row etc and append them to a snapshot image then save it as a file.

The album name and artist will also need to be converted from a string to an image. Character encoding is a massive PITA.