Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - deviluke

Pages: 1
1
MusicBee doesn't provide any way to check which view or playlist etc. is currently active.
So even outside this specific scenario about monthly play counts, you couldn't have a virtual tag that displayed different values depending on the active context.

Oh okay bummer. I guess I will request for that in the API section.

2
Hi frankz, thanks for replying. For that usecase, I would take care of tracking playing counts myself :D
I just wanted to know whether it was possible to display dynamic values like that.

3
I know it's a wild shot.
Basically, I'm asking for a way to attach/display different values on a song depending on which playlist I am viewing the song in.
A simple usecase example:
For a playlist named "Songs played in February", you could show the play counts only for that month, while in "Songs played in March", the value would be different for the same song.

Is this possible to do with virtual tags?
I don't necessarily need to know the expression needed, just whether it's possible or not.
Thanks!

4
Plugins / Re: Additional Tagging & Reporting Tools
« on: December 19, 2023, 04:51:00 PM »
I love this plugin! I'm using v7, latest downloadable from the plugin page.
Wishlist:
- Add the <Custom Text>'s to the list of tags you can search/save values into. This allows easy modifying of the input for slight variations.
It also allows easily doing things like replacing placeholders in the <Custom Text>, for example for the "Generate "Displayed Artist" separated by <Custom text> from multi-artist field":
"feat. (<?>)" where <?> can be set to be replaced with a value, resulting in "feat. (Artist1 & Artist2)"

- Add a conditional input in the Preset Editor. Basically, imagine in between every step there was a toggable input field, that allowed to write conditional statements like '<Temp 1> == "some value"', and if it results in a false expression, the steps terminate or skips (should be an option). If in between every step is too much, then maybe just one at end.

- Same as above but just for the processing and simpler. It just evaluates a regex expression in a chosen tag, if the expr doesn't match, the track gets skipped. I think this one is more important. It would allow pre-filtering the tracks that gets processed.
Many times I would have to do a few passes with slight variations and/or with similar presets to get all the tracks. An option like this would help a lot!

5
MusicBee API / I created a template for making plugins
« on: December 16, 2023, 05:23:53 PM »
After going through a slew of trouble getting up and running, I now want to save others the trouble.
Here is a template with a workflow that I think is quite nice.
Some conveniences has been added, and it should quickly allow someone to start developing right away.
https://github.com/iSplasher/musicbee-plugin

Maybe it can be linked on https://getmusicbee.com/help/api/?

6
I managed to load DLLs put in a different folder with this snippet:

Code
public sealed class SetupDLLDependencies
    {

        static string DLLDirectory = "";

        static public void Run(string dependencyDirName)
        {
            DLLDirectory = Path.Combine(AppContext.BaseDirectory, dependencyDirName);

            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly;
            AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
        }

        static private Assembly ResolveAssembly(Object sender, ResolveEventArgs e)
        {
            string name = Path.Combine(DLLDirectory, $"{e.Name.Split(',')[0]}.dll");
            Assembly res = null;
            try
            {
                res = System.Reflection.Assembly.LoadFile(name);
            }
            catch (Exception)
            {
                Console.WriteLine($"Failed to load {name}");
            }
            return res;
        }
    }

It works when I use the plugin DLL in an accompanying console app that I made, but I still can't get it to load in MB.
MB is able to detect it, but when I click Enable, I get the unhelpful message:
'Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.'

Is it possible to include the retrieved info from LoaderExceptions  in this popup?

I'm of course able to load the plugin if I don't call any of the code requiring any dependencies, but that's basically all of my code (outside of MusicBeePlugin.Plugin setup)

EDIT:
I checked ErrorLog.dat, and only found this (it's in Danish but shouldn't be an issue)
Code
15-12-2023 15:33:20 - 10.0.22631.0 - 3.5.8698.34385D - System.Reflection.ReflectionTypeLoadException: En eller flere af de anmodede typer kan ikke indlæses. Hent egenskaben LoaderExceptions for at få flere oplysninger.
   ved System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   ved System.Reflection.RuntimeModule.GetTypes()
   ved System.Reflection.Assembly.GetTypes()
   ved #=zu4Zx8AwXW_Fbz0RgnA==..ctor(#=zOPAFmqxyWq4nEsXBtA== #=zogaPBWQ=)

EDIT2:
I think I get what's going on now.
MB seems to call
Code
System.Reflection.Assembly.GetTypes()
before the snippet above gets to run. I tested this in the console app by trying to call Assembly.GetTypes() before and after the snippet ran. Obviously, it worked only if the snippet ran first.
Next, I tried to look for ways to get it to execute before MB uses Assembly.GetTypes(). So I changed the snippet to the following, in an attempt to get the code to execute upon load:
Code
public sealed class LibraryEntryPoint
    {

        static string DLLDirectory = "";

        // This static constructor will be called when the DLL is loaded
        static LibraryEntryPoint()
        {
            Assembly thisAssem = typeof(LibraryEntryPoint).Assembly;
            // Setup DLL dependencies
            SetupDllDependencies(thisAssem.GetCustomAttribute<AssemblyTitleAttribute>().Title);
        }

        static public void SetupDllDependencies(string dependencyDirName)
        {
            DLLDirectory = Path.Combine(AppContext.BaseDirectory, dependencyDirName);

            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly;
            AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
        }

        static private Assembly ResolveAssembly(Object sender, ResolveEventArgs e)
        {
            string name = Path.Combine(DLLDirectory, $"{e.Name.Split(',')[0]}.dll");
            Assembly res = null;
            try
            {
                res = System.Reflection.Assembly.LoadFile(name);
            }
            catch (Exception)
            {
                Console.WriteLine($"Failed to load {name}");
            }
            return res;
        }
    }

It didn't work.
With no way to know how MB loads plugins, I think I might be on an impasse. There seems to be no way to be no way to ensure dependencies are loaded before MB uses Assembly.GetTypes(). And I guess I understand that you need to GetTypes() to check if the required types are there?

EDIT 3: It works
Disregard what I mentioned in the previous edit. I got it to work. The error I got was due to a wrong dll folder being set.
This is the correct code:
Code
public sealed class LibraryEntryPoint
    {

        static string DLLDirectory = "";

        // This static constructor will be called when the DLL is loaded
        static LibraryEntryPoint()
        {
            Assembly thisAssem = typeof(LibraryEntryPoint).Assembly;
            // Setup DLL dependencies
            string libFolder = Path.GetDirectoryName(thisAssem.Location);
            string libDepFolder = Path.Combine(libFolder, thisAssem.GetCustomAttribute<AssemblyTitleAttribute>().Title);
            SetupDllDependencies(libDepFolder);
        }

        static public void SetupDllDependencies(string dependencyDirPath)
        {
            DLLDirectory = dependencyDirPath;

            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly;
            AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
        }

        static private Assembly ResolveAssembly(Object sender, ResolveEventArgs e)
        {
            string name = Path.Combine(DLLDirectory, $"{e.Name.Split(',')[0]}.dll");
            Assembly res = null;
            try
            {
                res = System.Reflection.Assembly.LoadFile(name);
            }
            catch (Exception)
            {
                Console.WriteLine($"Failed to load {name}");
            }
            return res;
        }
    }

Also remember to add this class to the Plugin class so the code gets triggered:
Code
namespace MusicBeePlugin
{

    public partial class Plugin
    {
        // Required so entrypoint can be called
        static private LibraryEntryPoint entryPoint = new LibraryEntryPoint();
   
        //...
     }
}
Or you can just move everything in LibraryEntryPoint to Plugin.
Well, everything works, so my issue has been resolved!

7
Thanks a lot for the response!
I'm quite new to .NET and having to deal with DLLs,. My understanding tells me those DLLs my plugin depends on need to be in the same folder. I'll try to look up if splitting the DLLs like that is possible, if not then I guess that's too bad!
Again, thanks a lot for your reply!

8
So I'm making a plugin and after build I get my own DLL and then about 24 other DLLs my plugin depends on.
I tried creating a folder for the plugin the usual place MB looks for plugins, but nothing gets picked up? Even the .zip option gets me "Can't find any .dll's".

Polluting users plugin folders with 24 unrelated DLLs seems kinda excessive?

Pages: 1