MonkeyToys: VB.NET extension adding MCE remote support

Download and get help for different MediaMonkey Addons.

Moderators: Peke, Gurus

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

MonkeyToys: VB.NET extension adding MCE remote support

Post by stax76 » Sun Dec 24, 2006 4:32 pm

MediaMonkey is a extension written with VB.NET
  • Sets ratings using 0-9 key
  • Toggles Play/Pause using space key
  • Jumps 10 seconds using left/right key
  • Next/Previous track using Page Up/Down key
  • Adds Microsoft MCE remote control support
  • Quick Filter panel
  • Expands the library node at startup
  • Tag editor that can transform fields in smart ways
  • Trashlist to manage trash tracks
  • VB.NET source code
Being able to use keys like 0-9, space, left/right without the need to press a modifier key like Ctrl is possible because MonkeyToys is smart and checks if text is currently entered in which case the text can be entered without the key is triggering the associated action.

The trashlist can be used by selecting trash tracks and chose 'Add to trashlist' from the context menu. This means MonkeyToys remembers the track artist+title. Now you remove the trash from your computer and anytime later you can check if your library contains trash by going to the 'Files to edit/Trash' node.

The Quick Filter panel allows to quickly filter by rating, genre and apply an order. It don't only allow to choose a exact rating but also 'equal or higher' or 'equal or lower'.

The Tag Editor can for instance apply title case only to one field instead of all or it can apply tokens from the file name to fields.

Unfortunately everything is hardcoded as making options would require more work than I can spend on the project, I need to focus on my main projects StaxRip and StaxPlayer.

Requirements

Vista or higher, on XP .NET 2.0 has to be installed

License

GPL

Download

At my website
Last edited by stax76 on Thu Sep 03, 2009 6:05 pm, edited 19 times in total.

Steegy
Posts: 3452
Joined: Sat Nov 05, 2005 7:17 pm
Location: Belgium
Contact:

Post by Steegy » Sun Dec 24, 2006 7:22 pm

Hey Stax

This makes me wonder: you can get MediaMonkey's events using VB.Net2 and COM interface, passing SDB reference as parameter.
Does this work also without the COM interface (a standard/separate application that makes an SDB object (instead of getting the reference to it through the Init call))?

TIA
Steegy
Extensions: ExternalTools, ExtractFields, SongPreviewer, LinkedTracks, CleanImport, and some other scripts (Need Help with Addons > List of All Scripts).

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

Post by stax76 » Sun Dec 24, 2006 7:49 pm

Hi Steegy,
Does this work also without the COM interface (a standard/separate application that makes an SDB object (instead of getting the reference to it through the Init call))?
I think yes it works :), hope you don't mind that I'm using your StartupNode code.

Peke
Posts: 12679
Joined: Tue Jun 10, 2003 7:21 pm
Location: Serbia
Contact:

Post by Peke » Sun Dec 24, 2006 8:28 pm

@Stax
Very good workaround to WSH. MM calls your Interface when it is needed and your app do all things without MM.
Very Very interesting, I was thinking about this kind of approach but never had time to make example.

@Steegy
It should work.

!@#$%^& I hate when something like this fill my head with ideas and I do not have time to bring them to light :(
Best regards,
Pavle
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
How to add SCREENSHOTS to forum

Steegy
Posts: 3452
Joined: Sat Nov 05, 2005 7:17 pm
Location: Belgium
Contact:

Post by Steegy » Sun Dec 24, 2006 10:34 pm

"I think yes it works" & "It should work"
Can someone give an example in C#? This "events catching" has been discussed before (in the OnShutdown event thread), but I never saw a working solution.

Code: Select all

        public SDBApplication SDB;
        public void Init(SDBApplication mm)
        {
            SDB = mm;
            SDB.set_Objects(Assembly.GetExecutingAssembly().GetName().Name, this);
            SDB.OnPlay += new ISDBApplicationEvents_OnPlayEventHandler(SDB_OnPlay);
        }

        void SDB_OnPlay()
        {
            SDB.Player.Volume = 0.2;
        }
This doesn't work.
Everything works within the Init method. Once that's finished, there seems to be no way to get any program interaction (using events, timer, ...) but the application seems to be still active (still in SDB.Objects dictionary, and COM warning on MM Shutdown)
Extensions: ExternalTools, ExtractFields, SongPreviewer, LinkedTracks, CleanImport, and some other scripts (Need Help with Addons > List of All Scripts).

Peke
Posts: 12679
Joined: Tue Jun 10, 2003 7:21 pm
Location: Serbia
Contact:

Post by Peke » Sun Dec 24, 2006 10:50 pm

Hmmm. That is good Q.
Will see how to Make things work. The COM warning serves to let you know that MM have app that connects to its COM which is correct in your case as you have not disconnected/free VAR SDB from MM.
I got that same problem few years ago in Delphi and SongMonitor. Events I'm not sure but I think that parse event to your app or read MM object with timer from your app and set MM to change it on desired event.

I'm gone to sleep, I'll see if I can look at this today.
Best regards,
Pavle
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
How to add SCREENSHOTS to forum

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

Post by stax76 » Mon Dec 25, 2006 12:17 am

@Steegy

Please post more code, maybe I can help you.

Steegy
Posts: 3452
Joined: Sat Nov 05, 2005 7:17 pm
Location: Belgium
Contact:

Post by Steegy » Mon Dec 25, 2006 7:26 pm

This is a full sample app (using the COM approach):

Code: Select all

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using SongsDB;

namespace MMComObject
{
    public class Program
    {
        public SDBApplication SDB;
        Timer tmr = new Timer();

        [STAThread]
        public static void Main()     // Run on program start
        {
            RegistrationServices reg = new RegistrationServices();
            reg.RegisterAssembly(Assembly.GetExecutingAssembly(), AssemblyRegistrationFlags.SetCodeBase);
        }


        public void Init(SDBApplication mm)     // Called by COM client
        {
            SDB = mm;
            SDB.set_Objects(Assembly.GetExecutingAssembly().GetName().Name, this);
            ((Program)SDB.get_Objects(Assembly.GetExecutingAssembly().GetName().Name)).SDB.Player.Play();     // WORKS, lets the MM player start playing

            SDB.OnPlay += new ISDBApplicationEvents_OnPlayEventHandler(SDB_OnPlay);

            tmr.Interval = 3000;
            tmr.Enabled = true;
            tmr.Tick += new EventHandler(tmr_Tick);
            tmr.Start();
        }

        void tmr_Tick(object sender, EventArgs e)     // Never executed
        {
            SDB.Player.Volume = 0.2;
            MessageBox.Show(SDB.Player.Volume.ToString());
            Application.Exit();
        }

        void SDB_OnPlay()     // Never executed
        {
            SDB.Player.Volume = 0.5;
        }
    }
}
Cheers
Steegy
Extensions: ExternalTools, ExtractFields, SongPreviewer, LinkedTracks, CleanImport, and some other scripts (Need Help with Addons > List of All Scripts).

Peke
Posts: 12679
Joined: Tue Jun 10, 2003 7:21 pm
Location: Serbia
Contact:

Post by Peke » Mon Dec 25, 2006 8:38 pm

In delphi all works like a charm Using WinAPI I have searched for references in C++ Builder and here it is
http://www.blong.com/Conferences/ICon99 ... n/3192.htm
Here is same thing In Delphi SDB is Variant Type or OLEVariant and from that I use only existing MM Scripting help. When Events are created you will need to parse Handle from Function/Procedure inside your own App so that MM Calls that App. Will need to test that but it should work or close enough.

Code: Select all

      If Findwindow('TFMainWindow','MediaMonkey') > 0 Then
        Begin
          SDB := CreateOleObject('SongsDB.SDBApplication');
        End
On Shutdown Event you will need to Clear/Free SDB Var if you wanna avoid COM Warning.

Unfortunately I do not know C that much (only basics that I need to know for using it with Delphi) and if this is not rubbish maybe is all that I can help.

NOTE: MM is Automation Server so why don't we access it that way? And except of some small syntax changes whole thing can be ported to VBS, Delphi, VB, .NET, ...
Best regards,
Pavle
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
How to add SCREENSHOTS to forum

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

Post by stax76 » Tue Dec 26, 2006 5:08 am

Your code should work, it does here:

script (put in ...\MediaMonkey\Scripts\Auto):

Code: Select all

Sub OnStartup
	Set o = CreateObject("WindowsApplication1.Program")
	o.Init(SDB)
End Sub
assembly of type winexe:

Code: Select all

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using SongsDB;

namespace WindowsApplication1
{
    [ComVisible(true)] // this overrides [assembly: ComVisible(false)] (is set by project options dialog) so registry don't get bloated with unneeded types
    public class Program
    {
        public SDBApplication SDB;
        Timer tmr = new Timer();

        [STAThread]
        public static void Main()
        {
            if (MessageBox.Show("Click yes to install, no to uninstall",
                Application.ProductName, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                RegistrationServices rs = new RegistrationServices();
                rs.RegisterAssembly(Assembly.GetExecutingAssembly(), AssemblyRegistrationFlags.SetCodeBase);
            }
            else
            {
                RegistrationServices rs = new RegistrationServices();
                rs.UnregisterAssembly(Assembly.GetExecutingAssembly());
            }
        }

        public void Init(SDBApplication mm)
        {
            SDB = mm;
            SDB.set_Objects(Assembly.GetExecutingAssembly().GetName().Name, this);
            ((Program)SDB.get_Objects(Assembly.GetExecutingAssembly().GetName().Name)).SDB.Player.Play(); // WORKS, lets the MM player start playing

            SDB.OnPlay += new ISDBApplicationEvents_OnPlayEventHandler(SDB_OnPlay);

            tmr.Interval = 3000;
            tmr.Enabled = true;
            tmr.Tick += new EventHandler(tmr_Tick);
            tmr.Start();
        }

        void tmr_Tick(object sender, EventArgs e) // executed!
        {
            tmr.Enabled = false;
            SDB.Player.Volume = 0.2;
            MessageBox.Show("timer");
        }

        void SDB_OnPlay() // executed!
        {
            SDB.Player.Volume = 0.5;
            MessageBox.Show("onplay");
        }
    }
}

Steegy
Posts: 3452
Joined: Sat Nov 05, 2005 7:17 pm
Location: Belgium
Contact:

Post by Steegy » Tue Dec 26, 2006 6:07 am

Hey Stax

The code works (as also mine does) when the COM object is created in an auto-script. It doesn't work if MediaMonkey is already running and you then launch the vbs script like this

Code: Select all

Dim SDB : Set SDB = CreateObject("SongsDB.SDBApplication")
Dim o : Set o = CreateObject("MMComObject.Program")
o.Init(SDB)
I've been testing the last situation, so it didn't work (but I still want it to work).
Probably this problem is the same problem as when an external EXE creates the MM automation object and then tries to attach event handlers (see code fragment below). Maybe MM has problems with attaching event handlers to external applications, if they're not loaded on startup and are no scripts?

Code: Select all

            SongsDB.SDBApplicationClass SDB = new SongsDB.SDBApplicationClass();
            SDB.ShutdownAfterDisconnect = false;

            SDB.OnPlay += new SongsDB.ISDBApplicationEvents_OnPlayEventHandler(SDB_OnPlay);
            SDB.OnShutdown += new SongsDB.ISDBApplicationEvents_OnShutdownEventHandler(SDB_OnShutdown);
Extensions: ExternalTools, ExtractFields, SongPreviewer, LinkedTracks, CleanImport, and some other scripts (Need Help with Addons > List of All Scripts).

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

Post by stax76 » Tue Dec 26, 2006 7:05 am

I think the scripts (WSH) exits, the WSH is hosting your .NET/COM object and since WSH is gone your .NET/COM object is gone too. Those are only guesses, you can play with tools like 'Process Explorer' to make things more transparent, you can also implement IDisposable to see if/when your object gets disposed.

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

Re: MonkeyToys

Post by stax76 » Sat Aug 02, 2008 4:54 pm

I've just uploaded a update, check the first post for changes.

GMGJ
Posts: 86
Joined: Mon Mar 12, 2007 3:17 pm
Contact:

Re: MonkeyToys

Post by GMGJ » Thu Oct 02, 2008 2:42 pm

FYI
I followed the link from http://www.planetdvb.net/utilities/monkeytoys to what was supposed to be the 3.5 version of Net, The link took me to the 3.0 version.
You need the 3.5 version

stax76
Posts: 176
Joined: Sun Mar 12, 2006 6:45 am

Re: MonkeyToys

Post by stax76 » Tue Oct 14, 2008 11:55 am

Thanks, I've fixed the link.

Post Reply