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.


Topics - Mayibongwe

Pages: 1 23 4
16
Plugins / AB Repeat Toggle (Hotkey)
« on: August 31, 2024, 09:51:19 PM »
Download it from the add-on link here

NB: I'm yet to address one aspect of the plugin that'll currently prevent you from setting up the AB Repeat for the last played song from the previous MB session.

I initially planned to add this function to the other hotkey plugin I shared a couple of weeks ago, but I've decided otherwise.
Splitting them up will help with discoverability and ensure users get to download only the features they desire.

The function was requested here and I've been enjoying it myself too:
It would be great if AB repeat functionality could be added to Musicbee.




The entire code for anyone interested in taking a peak.
Code
using System;
using System.IO;
using System.Timers;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MusicBeePlugin
{
    public partial class Plugin
    {
MusicBeeApiInterface mbApi;
System.Timers.Timer myTimer = new Timer();
ToolTip status = new ToolTip();

string dataFolder;
string logPath;

bool timer_Active = false;
bool pauseOn = false;

int mode = 0;
int start_time;
int end_time;
int streamHandle = -1;
double position;

        public PluginInfo Initialise(IntPtr apiInterfacePtr)
        {
            mbApi = new MusicBeeApiInterface();
            PluginInfo info = new PluginInfo();

            mbApi.Initialise(apiInterfacePtr);
            info.PluginInfoVersion = PluginInfoVersion;
            info.Name = "AB_Repeat Hotkey Toggle";
            info.Description = "Triggers a repeat state between two points in a song";
            info.Author = "Mayibongwe (2024)";
            info.TargetApplication = "";
            info.Type = PluginType.General;
            info.VersionMajor = 1;
            info.VersionMinor = 3;
            info.Revision = 0;
            info.MinInterfaceVersion = MinInterfaceVersion;
            info.MinApiRevision = MinApiRevision;
            info.ReceiveNotifications = ReceiveNotificationFlags.PlayerEvents | ReceiveNotificationFlags.TagEvents;
            info.ConfigurationPanelHeight = -1;

            dataFolder = Path.Combine(mbApi.Setting_GetPersistentStoragePath(), "mb_RepeatAB");
            if (Directory.Exists(dataFolder) == false) Directory.CreateDirectory(dataFolder);
            logPath = Path.Combine(dataFolder, "Activity.log");

            return info;
        }

public bool Configure(IntPtr panelHandle)
        {
            return false;
        }

public void SaveSettings(){}

public void Close(PluginCloseReason reason)
{
            myTimer.Dispose();
            status.Dispose();
}

public void Uninstall()
{
            if (Directory.Exists(dataFolder)) Directory.Delete(dataFolder, true);
}

public void writeToLog(string data)
{
            File.AppendAllText(logPath, data + Environment.NewLine);
}

public void ReceiveNotification(string sourceFileUrl, NotificationType type)
        {
switch(type)
{
case NotificationType.PluginStartup:
File.WriteAllText(logPath, "Plugin in effect" + Environment.NewLine);
mbApi.MB_AddMenuItem(null, "Player: Toggle AB Repeat", repeatHandler);
break;

case NotificationType.TrackChanged:
if(end_time != 0)
{
resetPoints();
writeToLog("Repeat off / New playing track");
}
break;

case NotificationType.PlayStateChanged:
if(end_time != 0)
{
PlayState status = mbApi.Player_GetPlayState();

if(timer_Active == true)
{
mode = 0;
if(status == PlayState.Paused)
{
pauseOn = true;
writeToLog("Playback paused");
}

if(status == PlayState.Stopped) writeToLog("Playback stopped");
}
else
{
if(status == PlayState.Playing && pauseOn == true)
{
mode = 2;
pauseOn = false;
myTimer.Enabled = true;
writeToLog("Playback resumed");
}
}
}
break;
}
        }

public void repeatHandler(object sender, EventArgs e)
{
if(streamHandle != -1 && mbApi.Player_GetPlayState() != PlayState.Stopped)
{
mode += 1;
switch(mode)
{
case 1:
start_time = mbApi.Player_GetPosition();
writeToLog("Start Time: " + start_time);
break;

case 2:
end_time = mbApi.Player_GetPosition();

if(end_time < start_time)
{
writeToLog("End Time Invalid: " + end_time);
resetPoints();
writeToLog("AB points captured discarded: Retry");
}
else
{
writeToLog("End Time: " + end_time);
repeatTrack();
showTooltip("on");
}
break;

case 3:
resetPoints();
writeToLog("Repeat turned off");
showTooltip("off");
break;
}
}
else
{
writeToLog("Cannot proceed without stream handle");
showTooltip("handle");
}
}

private void showTooltip(string enabled)
{
if(enabled == "on") enabled = "AB Repeat On";
else if (enabled == "off") enabled = "AB Repeat Off";
else enabled = "Missing Stream Handle";

status.Show(enabled, Application.OpenForms[0], Cursor.Position.X-42, Cursor.Position.Y-25, 1750);
}

private void resetPoints()
{
mode = 0;
start_time = 0;
end_time = 0;
}

private void repeatTrack()
{
switch(mbApi.Player_GetPlayState())
{
case PlayState.Playing:
mbApi.Player_SetPosition(start_time);

myTimer = new System.Timers.Timer();
myTimer.Interval = 1;
myTimer.Enabled = true;
myTimer.Elapsed += timer_Tick;
writeToLog("AB Repeat Commenced: While Playing");
break;

case PlayState.Paused:
pauseOn = true;
mbApi.Player_SetPosition(start_time);
BASS_ChannelPause(streamHandle);
writeToLog("AB Repeat Commenced: While Paused");
break;
}
}

private void timer_Tick(object sender, ElapsedEventArgs e)
{
if(mode == 2)
{
timer_Active = true;
position = toSeconds(BASS_ChannelGetPosition(streamHandle, 0));

if(position > end_time || position < start_time)
{
writeToLog("Loop ended: " + position);
mbApi.Player_SetPosition(start_time);
}
}
else
{
timer_Active = false;
writeToLog("Timing disabled");
myTimer.Enabled = false; // stop timing if repeat is disabled
}
}

private double toSeconds(long byteData)
{
double seconds = BASS_ChannelBytes2Seconds(streamHandle, byteData);
return seconds*1000;
}

public void InitialiseStream(int handle)
{
streamHandle = handle;
writeToLog("Stream Initialised: " + handle);
}

[System.Security.SuppressUnmanagedCodeSecurity()]
        [DllImport("bass.dll", CharSet = CharSet.Auto)]
public static extern long BASS_ChannelGetPosition(int handle, int mode);

[System.Security.SuppressUnmanagedCodeSecurity()]
        [DllImport("bass.dll", CharSet = CharSet.Auto)]
public static extern bool BASS_ChannelPause(int handle);

[System.Security.SuppressUnmanagedCodeSecurity()]
        [DllImport("bass.dll", CharSet = CharSet.Auto)]
public static extern double BASS_ChannelBytes2Seconds(int handle, long byteData);
    }
}

17
MusicBee API / Retrieving the StreamHandle of the Playing Track
« on: August 30, 2024, 11:06:39 PM »
In the future, I will convert this plugin to a generalized hotkey provider, as and when the requests come up.
Bookmarking this in case the wishlist request goes cold: AB Repeat
Tonight, I wanted to get something going for this request.
Along the way, I discovered that the playStateChanged notification seems not to be kicking in at all.

________

Unrelated to this bug report:
I actually can't think of how I'll get the tracks to repeat between two points using the current API.

So far, I'm able to capture both the user's start and end times.
Able to get it to commence the loop at A.
My challenge now comes in figuring out how to determine that the track has reached point B.
Calling Player_GetPosition() non-stop to figure out how much longer till B would be crazy.

At this moment, I can only see this working if MB was to receive a value from the plugin telling it to stop at such a position.
For example, PlayerSetEndPosition()

Edit: Subject line amended from the initial false bug report.

18
General Discussions / <Artist> and <Display Artist>
« on: July 07, 2024, 03:10:05 PM »
Bringing this here just so we don't pollute the tip and trick topic.

Is that a trick question, haha.
<artist> itself is <display artist> in all occurrences within MusicBee.
Nope, no trickery going on here ;-)

Display Artist begins its life as an internal virtual tag that will indeed show what's in Artist.
But after modifying tags (not artist related tags per-se) it will begin a second life as a physical tag.
I myself am using Picard to populate the Display Artist tag, and that will sometimes differ from Artist.


So when you open the Tag Editor, what value is in the artist field?

Sorry I'm not being lazy, i would test it myself, but i have no other means of populating display artist besides editing it in MusicBee.

19
Plugins / Miscellaneous Hotkeys
« on: June 11, 2024, 09:06:32 PM »
Download it from the add-on link here

Version 1.0
In the future, I will convert this plugin to a generalized hotkey provider, as and when the requests come up.
The crossfade hotkey was requested a while back - I found this link from a recent wishlist request from another separate topic which I haven't linked here.

Maybe I'm missing something, but I couldn't find the Toggle Crossfade hotkey in the list.




Version 1.1

I've looked and searched and can't find a way to access the "Mark as having no lyrics" option outside the Lyrics tab in the Tag Editor.




The entire code for anyone interested in taking a peak.
Code
using System;

namespace MusicBeePlugin
{
    public partial class Plugin
    {
        private MusicBeeApiInterface mbApi;
        private PluginInfo about = new PluginInfo();

        public PluginInfo Initialise(IntPtr apiInterfacePtr)
        {
            mbApi = new MusicBeeApiInterface();
            mbApi.Initialise(apiInterfacePtr);
            about.PluginInfoVersion = PluginInfoVersion;
            about.Name = "Miscellaneous Hotkeys";
            about.Description = "hotkey support for various actions";
            about.Author = "Mayibongwe";
            about.TargetApplication = "";
            about.Type = PluginType.General;
            about.VersionMajor = 1;
            about.VersionMinor = 1;
            about.Revision = 0;
            about.MinInterfaceVersion = MinInterfaceVersion;
            about.MinApiRevision = MinApiRevision;
            about.ReceiveNotifications = ReceiveNotificationFlags.StartupOnly;
            about.ConfigurationPanelHeight = -1;

            return about;
        }

        public void ReceiveNotification(string sourceFileUrl, NotificationType type)
        {
            if (type == NotificationType.PluginStartup)
            {
                mbApi.MB_AddMenuItem(null, "Miscellaneous: Toggle Crossfade On/Off", crossfadeHandler);
                mbApi.MB_AddMenuItem(null, "Miscellaneous: Mark As Having No Lyrics", lyricsHandler);
            }
        }

        public void lyricsHandler(object sender, EventArgs e)
        {
            string[] selection;
            mbApi.Library_QueryFilesEx("domain=SelectedFiles", out selection);

            for (int i=1; i<=selection.Length; i++)
            {
               string track = selection[i-1];
               mbApi.Library_SetFileTag(track, MetaDataType.HasLyrics, "MarkNoLyrics");
               mbApi.Library_CommitTagsToFile(track);
               mbApi.MB_SetBackgroundTaskMessage(i + "/" + selection.Length + " tracks marked as having no lyrics...");
            }

            mbApi.MB_RefreshPanels();
        }

        public void crossfadeHandler(object sender, EventArgs e)
        {
            bool isCrossfadeOn = mbApi.Player_GetCrossfade();
            switch (isCrossfadeOn)
            {
               case true:
               mbApi.Player_SetCrossfade(false);
               break;

               case false:
               mbApiInterface.Player_SetCrossfade(true);
               break;
            }
        }

        public bool Configure(IntPtr panelHandle)
        {
            return false;
        }
    }
}

20
Plugins / Volume Lock
« on: June 09, 2024, 02:14:45 AM »
Download it from the add-on link here

Any way/chance of locking the volume control?
Could it be done as a plugin?
Above is the link to the thread that made me give this a go just to see if it'd be possible.
Looks to be working just fine in my brief testing.


21
MusicBee API / Deriving The Skin Icons of a MusicBee Form
« on: June 06, 2024, 06:22:25 PM »
I'm in the process of creating a basic settings form that'll be accessible through the 'configure' button in the preferences.

If I wanted that form to mirror the current skin's border images and button icons (close, minimize, etc):
Would it technically be possible for me to backtrack to the Preferences parent form via the control that the configure function provides, in order to retrieve the icons myself?

I could give it a go ofc, but I figured asking here would save me some time in case the attributes of that parent form are internally protected anyway,
or if it's outright impossible to backtrack that far (I'm new to forms - so it'd take a bit of researching and experimenting).

If we indeed cannot get to those icons ourselves, how about introducing one of these alternatives:

1. New API calls to retrieve each of those icons.

2. Which I think is the best solution
Providing access to a standard MusicBee form which already follows the skin buttons and borders.

Edit: one like this (just without the contents of that inner rectangle).

22
Developers' Area / Add-on Icon [Bookmarked]
« on: May 04, 2024, 07:28:23 PM »
I think it would be an injustice not to have this icon on a skin or something.
Where'd you dig it up, Tony?



A Very Very Happy MusicBee user, i wish i found it a lifetime ago....  8)

23
Beyond MusicBee / Bit of a Funny Read To Make Up Your Friday
« on: March 08, 2024, 05:32:52 AM »
In the previous MusicBee version it worked perfectly. I wonder if I'm the only one with this problem.  :'(
you are the only person who has reported this so my guess is you have installed and are running the new musicbee version from a different location
I'm running MusicBee from Mozambique, is there something I can do to resolve this issue?
location on your computer ie. you have two installed instances of musicbee

24
General Discussions / Usage of Multivalue Tags | <Artist> <Composer>
« on: January 27, 2024, 12:39:28 PM »
Here's my argumentation for having a dedicated Album Artists tag:
https://getmusicbee.com/forum/index.php?topic=29851.msg166102#msg166102
While chewing on the concept of album artists, I got heavily distracted by your use of <artists: artist>.
I've created a new topic here instead of responding in either of those threads because I don't wanna pollute/derail what they were intended for.



Is the above screenshot from your linked thread currently how you have these artists tagged?
If I was replying to a new forum member, I would even be bold enough to say that they're using <artist> incorrectly,
but seeing as I am addressing somebody more knowledgeable and experienced than me, I'm thinking there's something I'm missing here.

Why has <artist> (a multivalue tag) been tagged with Aretha Franklin & George Michael?
Your very reason for creating the custom tag <artists [credited]> (splitting up the two artists above) is what <artist> itself is designed for.

There's also an artist tag for Patti LaBelle feat. Michael McDonald? I'm perplexed...

Wanna hear your feedback on this before going back to the composers thread.

25
General Discussions / 2023 - Compliments / Reviews / Observations
« on: December 15, 2023, 06:43:14 PM »
It's that time of the year people!🎉
https://getmusicbee.com/forum/index.php?topic=11596.0

Two weeks left before we say goodbye to 2023 and this is a massive thank you to Steven for the ongoing commitment that he's injected into this precious project throughout the years.
The turnaround times for a one-man show continue to amaze! How's that for service?💯

Although the forum does not appear to have been graced with a lot of new members this year, MusicBee continues to grow onward and upward💪
The optimist in me thinks that can only mean our moderators have been hard at work getting rid of fake accounts. Way to go guys - phred, zak, psychoadept!


26
General Discussions / Translated Error Logs
« on: November 03, 2023, 06:53:15 PM »
Saw an error report here that encouraged me to finally raise this question I've always had: https://getmusicbee.com/forum/index.php?topic=40177.msg217499#msg217499

More often than not, the only people who can dissect a MB error log are Steven and a handful of other seasoned (English speaking) users.
Which begs the question, is it really wise to translate the error log when other languages are selected in the MB preferences, since:

As far as I've noticed, the reporting user simply dumps the error log in that translated state and I would guess,
Steven and the other aforementioned forum members would then have to take the time to translate the log back into English? (or is this assumption incorrect?)

Just a thought...

27
TheaterMode / Theater Modes / What Are They? / How Do They Work?
« on: August 10, 2023, 11:04:01 PM »
The Theater Mode plugin - a gem designed and maintained by MusicBee's one and only developer, Steven.

This post is long overdue - been thinking about doing this for the past year or so.
I'd like to thank karbock, and hiccup I believe, for their recent write-ups in the Tips and Tricks board that have motivated me into finally getting this done.


So, Theater Modes (TM's)...what are they?

These are custom views or layouts that are meant to extend the visual aspect of the MusicBee listening experience.
Simply put, they allow users to redesign MusicBee's graphical user interface to their liking.
As I've said in the past, listening to soundtracks has never been this beautiful.


Embedded vs Full-screen

These are the types of TM's that we have and the main difference between them lies in the screen area that MusicBee allocates for each.


Embedded Theater Modes
  • MusicBee reserves only the main panel for use. i.e everywhere but the title & tabs bar and the player controls.
  • They are accessible from the Now Playing tab, Compact Player, as well as the Now Playing Bar which can be docked in either the Main or Bottom Panel.
  • They are located in .../MusicBee/Plugins/TheaterMode.Embedded



Full-screen Theater Modes
  • As the name suggests, they occupy every inch of the screen.
  • They can be activated by means of a hotkey or the drop-down menu in View > Theater Mode.
  • They are located in .../MusicBee/Plugins/TheaterMode.List



Normal Theater Modes
  • They are more or less the same as full-screens.
  • These are set to occupy all of MusicBee's main window with the exception of the Title Bar.



Built-In vs Custom

Every MusicBee install comes bundled with a couple of built-in and user-created TM's.


Built-In Theater Modes
  • These are hardcoded into MusicBee and cannot be edited by any means other than the options provided in the panel configuration settings.
  • At the time of writing, we only have three built-in TM's - Artist Picture, Album Color Mix, and Large Album.

Custom Theater Modes
  • These are user-created and will show up in the list of TM's once placed in the appropriate folders mentioned hereinabove.
  • The files need to be saved with an .xml extension in order to be recognized by MusicBee.
  • Most of your code will comprise of items called <elements> and <attributes>, which are basically series of keywords used to command MusicBee into taking various actions.
  • Attributes are used to define the structure of the elements.
  • There is a specific syntax that is required during the definition of these elements and attributes - refer to the posts below.

28
Plugins / Library Quiz
« on: November 05, 2022, 02:00:53 PM »
Download the plugin from the add-on link here.
NB: Only works with MusicBee 3.5.8338 and later versions.

I came across this thread some time ago and also thought this would be an interesting and fun thing to have in MusicBee.
Probably not exactly what is described there, but it's close.
All comments are welcome. Let the games begin!

Installation

- Download the mb_LibraryQuiz zip file.
- Then locate and select it from MusicBee > Edit > Preferences > Plugins > Add Plugin
- Lastly, dock the "Library Quiz" element to any panel of your choosing in View -> Arrange Panels...

How It Works

- The plugin will pick a random track from your library.
- Then you'll have to type in whatever values you think correspond with the track tags.
- Your answer will only be evaluated once the field is out of focus i.e when you move on to the next field or click anywhere outside the current field.
- After evaluation, the correct answer will get displayed on that specific field and the scores will get incremented accordingly (1 point for each correct answer).
- Clicking on the track's correct album cover will also earn you a point.
- The round artist picture does not do anything; it's only there to jog your memory.
- You are free to make an attempt on any or all of the 6 fields - you won't get penalized for leaving a field unanswered.
- Click on the track title when you're ready to move on to the next round.

Customization

- The colours used by the plugin are that of the current skin.
- If you're not entirely happy with some of them, you can override them from this folder ...MusicBee\AppData\mb_LibraryQuiz\Skins


29
MusicBee API / Enhancement To Existing Artwork API Calls
« on: October 27, 2022, 11:00:18 PM »
Currently, it appears that artwork retrieval functions return a null whenever there isn't any artwork linked to a track file.

Instead of returning nothing, would it be possible to return the "No Artwork" image that is provided by skins?
And in case of artist pictures, returning the "Unknown Artist" image instead?

30
MusicBee API / Set Panel Scrollable Area
« on: October 27, 2022, 10:43:38 PM »
I know it's in the name but can I get clarity on what SetPanelScrollableArea is supposed to do?
Like what should I expect MusicBee to do when I've defined the following?

Code
mbApi.MB_SetPanelScrollableArea(panel, new Size(100, 200), true);
I've been working on a quiz plugin for the past few weeks that's near-ready.
I just need to get some scrolling to take place in there if ever the panel size is too small.
Can I rely on that function to get me the scrollbar that's showing up in the 'Upcoming Tracks' panel below or do I just have to add my own scroll control.


Pages: 1 23 4