Imports System.Runtime.InteropServices
Imports System.CodeDom
Public Class OutputPlugin
'function name = winampGetOutModule
'Main delegate. The declare above for GetProcAddress returns this type
Private Delegate Function ptrwinampGetOutModule() As OutModule
Private _OutModule As OutModule 'holds the plugin info
Sub New(ByVal FromFile As String)
MyBase.New()
_OutModule = DynamicBinding(Of OutModule).CallFunction(FromFile, "winampGetOutModule")
End Sub
#Region "Methods"
'these call the pointers to the various functions of the plugin.
'Note: this section is not yet complete
'Plugin loads settings, etc.
Public Sub Init()
_OutModule.Init()
End Sub
'Plugin saves settings, closes devices
Public Sub Quit()
_OutModule.Quit()
End Sub
'Show the about window
Public Sub About(ByVal Owner As Form)
_OutModule.About(Owner.Handle)
End Sub
'Show the config window
Public Sub Config(ByVal Owner As Form)
_OutModule.Config(Owner.Handle)
End Sub
#End Region
End Class
#Region "OutModule Structure"
'"Slightly" modified def of the structure. See OUT.H in the sdk for the original version
<StructLayout(LayoutKind.Sequential)> _
Public Structure OutModule
Public version As Integer '// module version (OUT_VER)
Public description As String '// description of module, with version string
Public id As Integer '// module id. each input module gets its own. non-nullsoft modules should
'// be >= 65536.
Public hMainWindow As Integer '// winamp's main window (filled in by winamp)
Public hDllInstance As Integer '// DLL instance handle (filled in by winamp)
Public Delegate Sub ptrConfig(ByVal hwndParent As Integer)
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Config As ptrConfig '(HWND hwndParent); '// configuration dialog
Public Delegate Sub ptrAbout(ByVal hwndParent As Integer)
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public About As ptrAbout '(HWND hwndParent); '// about dialog
Public Delegate Sub ptrInit()
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Init As ptrInit '(); '// called when loaded
Public Delegate Sub ptrQuit()
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Quit As ptrQuit '(); '// called when unloaded
Public Delegate Function ptrOpen(ByVal SampleRate As Integer, ByVal NumChannels As Integer, ByVal BitsPerSamp As Integer, ByVal BufferLenMS As Integer, ByVal PreBufferMS As Integer) As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Open As ptrOpen '(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
'// returns >=0 on success, <0 on failure
'// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
'// ... so don't expect the max latency returned to be what you asked for.
'// returns max latency in ms (0 for diskwriters, etc)
'// bufferlenms and prebufferms must be in ms. 0 to use defaults.
'// prebufferms must be <= bufferlenms
Public Delegate Sub ptrClose()
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Close As ptrClose '(); '// close the ol' output device.
Public Delegate Function ptrWrite(ByRef buf As Byte(), ByVal len As Integer) As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Write As ptrWrite '(char *buf, int len);
'// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
'// 1 returns not able to write (yet). Non-blocking, always.
Public Delegate Function ptrCanWrite() As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public CanWrite As ptrCanWrite '(); '// returns number of bytes possible to write at a given time.
'// Never will decrease unless you call Write (or Close, heh)
Public Delegate Function ptrIsPlaying() As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public IsPlaying As ptrIsPlaying '(); '// non0 if output is still going or if data in buffers waiting to be
'// written (i.e. closing while IsPlaying() returns 1 would truncate the song
Public Delegate Function ptrPause(ByVal Pause As Integer) As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Pause As ptrPause '(int pause); '// returns previous pause state
Public Delegate Sub ptrSetVolume(ByVal volume As Integer)
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public SetVolume As ptrSetVolume '(int volume); '// volume is 0-255
Public Delegate Sub ptrSetPan(ByVal pan As Integer)
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public SetPan As ptrSetPan '(int pan); '// pan is -128 to 128
Public Delegate Sub ptrFlush(ByVal t As Integer)
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public Flush As ptrFlush '(int t); '// flushes buffers and restarts output at time t (in ms)
'// (used for seeking)
Public Delegate Function ptrGetOutputTime() As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public GetOutputTime As ptrGetOutputTime '(); '// returns played time in MS
Public Delegate Function ptrGetWrittenTime() As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public GetWrittenTime As ptrGetWrittenTime '(); '// returns time written in MS (used for synching up vis stuff)
End Structure
#End Region
Friend Class DynamicBinding(Of ReturnStructure As Structure)
'replacements in template
Private Const DLLName As String = "DLLName"
Private Const [Structure] As String = "Integer"
Private Const FunctionName As String = "FunctionName"
'name of module
Private Const ClassName As String = "CallDll"
Public Shared Function CallFunction(ByVal DLL As String, ByVal Funct As String) As ReturnStructure
'Code is loaded from a resource. see Template.VB
Dim TemplateCode As String = My.Resources.Template
'Replace parts of the code with the constants above
TemplateCode = Replace(TemplateCode, DLLName, DLL)
TemplateCode = Replace(TemplateCode, FunctionName, Funct)
TemplateCode = Replace(TemplateCode, [Structure], GetType(ReturnStructure).FullName)
'Compile the code
Dim CompileUnit As New CodeSnippetCompileUnit(TemplateCode)
Dim TemplateCodeArray As String() = {TemplateCode}
Dim Params As New Compiler.CompilerParameters()
With Params
.GenerateExecutable = False
.GenerateInMemory = True
.IncludeDebugInformation = False
.ReferencedAssemblies.Add(Application.ExecutablePath)
End With
Dim CodeProvider As New Microsoft.VisualBasic.VBCodeProvider()
'this is the line that compiles it
Dim CompilerResaults As Compiler.CompilerResults = CodeProvider.CompileAssemblyFromSource(Params, TemplateCodeArray)
'if there are errors, let me see what they are
If CompilerResaults.Errors.Count > 0 Then
Dim ce As Object = CompilerResaults.Errors
Dim item As Object
For Each item In ce
'cheap and simple way of debugging compiler errors:
'hover the mouse over 'item' in the code window while stopped
'it will tell you what error occured.
Stop
Next
End If
'now it should be compiled, use relfection to call the code
Dim Assembly As System.Reflection.Assembly = CompilerResaults.CompiledAssembly
Dim [class] As System.Type = Assembly.GetType(ClassName)
Dim method As Reflection.MethodInfo = [class].GetMethod(Funct, Reflection.BindingFlags.Static Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.FlattenHierarchy)
[b]Return DirectCast(method.Invoke(Nothing, Nothing), ReturnStructure)[/b]
End Function
End Class