It is currently September 20th, 2020, 8:28 pm

WavLength Plugin

Share and get help with Plugins and Addons
User avatar
jsmorley
Developer
Posts: 21372
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

WavLength Plugin

Post by jsmorley »

In another thread a user had asked about how to have some action take place "during" the time a Play command is playing a .wav sound file. This really can't be done in native Rainmeter, as Rainmeter has no way to "know" when the Play command is done. It's more or less a "fire and forget" deal.

So here is a little plugin that can help with this.

WavLength Plugin

WavLength_1.0.rmskin

When given a path to a .wav sound file, the plugin will return the length of the sound, in Seconds or Milliseconds.

Just download this and run it to install the appropriate version of the plugin in Rainmeter and install and load the example skin. Included in the skin folders will be both the 32bit and 64bit versions of the plugin .dll so you can distribute it in your own .rmksin.

You can also just download the 32bit and 64bit plugin alone.
WavLength Plugin for Distribution.zip



Plugin Options


WavPath

The path and name of a .wav sound file.
Example: WavPath=C:\Sounds\MySound.wav

Unit

Unit of measure (Seconds or Milliseconds) to return the value in. The default is Seconds.
Example: Unit=Milliseconds



Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Variables]
FilePath=#@#Sounds\
FileName=Windows Intro.wav
Unit=Milliseconds

[MeasureWav]
Measure=Plugin
Plugin=WavLength
WavPath=#FilePath##FileName#
Unit=#Unit#
UpdateDivider=-1
OnUpdateAction=[!SetVariable Seconds "(Round([&MeasureWav]/1000))"]

[MeterWav]
Meter=String
MeasureName=MeasureWav
W=200
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
NumOfDecimals=0
DynamicVariables=1
Text=#FileName##CRLF##Seconds# seconds in length

[MeterPlay]
Meter=String
Y=50
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Play Me
LeftMouseUpAction=[Play "#FilePath##FileName#"][!HideMeter MeterPlay][!ShowMeter MeterPlaying][!UpdateMeter *][!Redraw][!Delay [&MeasureWav]][!HideMeter MeterPlaying][!ShowMeter MeterPlay][!UpdateMeter *][!Redraw]

[MeterPlaying]
Meter=String
X=153
Y=50
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Playing
Hidden=1
GIF.gif




If you are interested, the plugin .cs (C#) code looks like this:

Code: Select all

using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Rainmeter;

namespace PluginWavLength
{

    internal class Measure
    {
        [DllImport("winmm.dll")]
        public static extern uint mciSendString(
        string command,
        StringBuilder returnValue,
        int returnLength,
        IntPtr winHandle);

        public string fileName;
        public double wavLength;
        public string unit;

        private void GetSoundLength(string fileName)
        {
            StringBuilder lengthBuf = new StringBuilder(32);

            mciSendString(string.Format("open \"{0}\" type waveaudio alias wave", fileName), null, 0, IntPtr.Zero);
            mciSendString("status wave length", lengthBuf, lengthBuf.Capacity, IntPtr.Zero);
            mciSendString("close wave", null, 0, IntPtr.Zero);

            int length = 0;
            int.TryParse(lengthBuf.ToString(), out length);
            wavLength = length;

        }

        internal Measure()
        {
        }

        internal void Reload(Rainmeter.API rm, ref double maxValue)
        {
            fileName = rm.ReadString("WavPath", "");
            unit = rm.ReadString("Unit", "").ToLower();
        }

        internal double Update()
        {
            GetSoundLength(fileName);
            if (unit == "milliseconds")
            {
                return wavLength;
            }
            else
            {
                return wavLength / 1000;
            }                
        }

        //internal string GetString()
        //{
        //    return "";
        //}

        //internal void ExecuteBang(string args)
        //{
        //}
    }

    public static class Plugin
    {
        [DllExport]
        public unsafe static void Initialize(void** data, void* rm)
        {
            uint id = (uint)((void*)*data);
            Measures.Add(id, new Measure());
        }

        [DllExport]
        public unsafe static void Finalize(void* data)
        {
            uint id = (uint)data;
            Measures.Remove(id);
        }

        [DllExport]
        public unsafe static void Reload(void* data, void* rm, double* maxValue)
        {
            uint id = (uint)data;
            Measures[id].Reload(new Rainmeter.API((IntPtr)rm), ref *maxValue);
        }

        [DllExport]
        public unsafe static double Update(void* data)
        {
            uint id = (uint)data;
            return Measures[id].Update();
        }

        //[DllExport]
        //public unsafe static char* GetString(void* data)
        //{
        //    uint id = (uint)data;
        //    fixed (char* s = Measures[id].GetString()) return s;
        //}

        //[DllExport]
        //public unsafe static void ExecuteBang(void* data, char* args)
        //{
        //    uint id = (uint)data;
        //    Measures[id].ExecuteBang(new string(args));
        //}

        internal static Dictionary<uint, Measure> Measures = new Dictionary<uint, Measure>();
    }
}
You do not have the required permissions to view the files attached to this post.