OpenGL visual plugins for Bass.dll

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
Patrice Terrier
Posts: 66
Joined: Jan 06, 2006 8:27
Location: France
Contact:

OpenGL visual plugins for Bass.dll

Post by Patrice Terrier »

Image

The purpose of this application is to switch easily from one plugin to another to check the OpenGL FPO effects transposed to 64-bit.
Most of them inherit from the original 32-bit version written long ago in PowerBASIC for BassBox.

You can use drag & drop from the Explorer to play any audio file supported by Bass.dll.

To navigate from one plugin to another move the cursor to the left or right edge of the window, and click on the auto/hide arrow.

Here is the BBP API to use to communicate with the plugin DLL.
See in the WM_TIMER message the gl_DrawScene() code using BBP_RenderOpenGL to pass the wimdata pointer to the DLL.

Code: Select all

#pragma once
'typedef ULONGLONG QWORD;

#include once "GL/gl.bi"

Const BBP_RENDER       = 1       ' Render the scene.
Const BBP_CREATE       = 2       ' Retrieve Title, Name, Version, Render mode.
Const BBP_INIT         = 3       ' Init the OpenGL.
Const BBP_SIZE         = 4       ' The size of the control has changed.
Const BBP_KEYBOARD     = 5       ' All keyborad message.
Const BBP_MOUSE        = 6       ' All mouse messages.
Const BBP_DESTROY      = 7       ' Free Up resources.
Const BBP_NEW_SOUND    = 8       ' We are playing a new sound file.

Const BBP_GDIPLUS      = 0       ' GDImage GDIPLUS compatible mode.
Const BBP_OPENGL       = 1       ' OpenGL mode.
Const BBP_DIRECTX      = 2       ' DirectX mode (for future extension).

Const BBP_SUCCESS      = 0
Const BBP_ERROR        = -1

Type QWORD As ULongInt  ' Equivalent to ULONGLONG

Type BBPLUGIN
    msg         As ULong
    parent      As HWND
    dc          As HDC
    rc          As HGLRC

    lpeak       As UShort
    rpeak       As UShort

    title       As ZString * 32
    author      As ZString * 64

    version     As ULong
    renderto    As Long
    backargb    As Long

    fftdata     As Single Ptr
    fftsize     As UShort

    winmsg      As ULong

    wparam      As WPARAM
    lparam      As LPARAM

    wimdata     As Short Ptr

    medialength As QWord
    mediapos    As QWord

    reserved    As ZString * 56
End Type ' 256 bytes

Function BBP_ProcHandle(ByVal hProc As FARPROC, ByVal RW As Long) As FARPROC
    Static WasHproc As FARPROC
    If (RW) Then WasHproc = hProc
    Return WasHproc
End Function

Function BBP_Plugin(ByRef BBP As BBPLUGIN) As Long
    Dim nRet As Long = BBP_ERROR

    If IsWindow(gP.hGL) Then
        Dim glRC As HGLRC = Cast(HGLRC, ZI_GetProperty(gP.hGL, ZI_GLRC))
        If glRC <> 0 Then
            ' Retrieve stored procedure
            Dim hProc As Any Ptr = BBP_ProcHandle(0, 0)
            If hProc Then
                ' Define a delegate type for the plugin proc
                Dim pluginProc As Function(ByRef BBP As BBPLUGIN) As Long
                pluginProc = Cast(Function(ByRef BBP As BBPLUGIN) As Long, hProc)
                nRet = pluginProc(BBP)
            End If
        End If
    End If

    Return nRet
End Function

Function BBP_ActivePlugin(ByVal sPluginName As WString Ptr, ByVal RW As Long) As WString Ptr
    Static sWasPluginName As WString * MAX_PATH
    If (RW) Then wcscpy(@sWasPluginName, sPluginName)
    Return @sWasPluginName
End Function

Sub MarqueeUpdate()
    Dim zDrive As WString * _MAX_DRIVE
    Dim zDir As WString * _MAX_DIR
    Dim zFname As WString * _MAX_FNAME
    Dim zExt As WString * _MAX_EXT
    wsplitpath(gB.audiofile, zDrive, zDir, zFname, zExt)
    ClearMemory(@gP.plugintitle, sizeof(gP.plugintitle))
    wcscpy(@gP.plugintitle, @gP.title)
    Add_Str(@gP.plugintitle, @gP.version)
    Add_Str(@gP.plugintitle, !" by ")
    Add_Str(@gP.plugintitle, @gP.author)
    Add_Str(@gP.plugintitle, !", playing """)
    Add_Str(@gP.plugintitle, @zFname)
    Add_Str(@gP.plugintitle, zExt)
    Add_Str(@gP.plugintitle, !"""")
    ZD_SetObjectText(ID_COPYRIGHT, gP.plugintitle)
End Sub

Sub BBP_Reset()
    Dim BBP As BBPLUGIN
    ClearMemory(@BBP, sizeof(BBP))

    BBP.msg = BBP_CREATE
    BBP_Plugin(BBP)

    ClearMemory(@gP.title, sizeof(gP.title))
    wcscpy(@gP.title, cswconv(BBP.title)) ' C string to WCHAR
    ClearMemory(@gP.author, sizeof(gP.author))
    wcscpy(@gP.author, cswconv(BBP.author)) ' C string to WCHAR

    Dim majorVersion As UByte = (BBP.version And &hFF)
    Dim minorVersion As UByte = ((BBP.version Shr 8) And &hFF)
    ClearMemory(@gP.version, sizeof(gP.version))
    gP.version = !" (" + Wstr(majorVersion) + !"." + Wstr(minorVersion) + !")"

    MarqueeUpdate()

    if (BBP.renderto = BBP_OPENGL) Then
        glDisable(GL_BLEND)
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_LIGHT0)
        glDisable(GL_LIGHT1)
        glDisable(GL_LIGHT2)
        glDisable(GL_LIGHT3)
        glDisable(GL_LIGHT4)
        glDisable(GL_LIGHT5)
        glDisable(GL_LIGHT6)
        glDisable(GL_LIGHT7)
        glDisable(GL_LIGHTING)
        glDisable(GL_COLOR_MATERIAL)
        glDisable(GL_ALPHA_TEST)
        glDisable(GL_NORMALIZE)
        glDisable(GL_LINE_SMOOTH)

        glDisable(GL_LINE_SMOOTH)

        glGetError()

    End If
End Sub

Sub BBP_Detached(ByVal hWnd As HWND, ByRef hLib As HMODULE)
    Dim BBP As BBPLUGIN
    if (hLib) Then
        BBP.msg = BBP_DESTROY
        BBP.parent = hWnd
        BBP_Plugin(BBP)

        ' Brute force to delete any existing texture
        Const Tmax As Long = 64
        Dim DT(0 To Tmax - 1) As GLuint
        For K As Long = 0 To Tmax - 1
            DT(K) = K
        Next
        glDeleteTextures(Tmax, @DT(0))

        BBP_ProcHandle(0, 1)
        FreeLibrary(hLib): hLib = 0
    End If
End Sub

Sub BBP_ResizeOpenGL()
    if (IsWindow(gP.hGL)) Then
        Dim BBP As BBPLUGIN
        ClearMemory(@BBP, sizeof(BBP))
        BBP.msg          = BBP_SIZE
        BBP.parent       = gP.hGL
        BBP_Plugin(BBP)
    End If
End Sub

' Load/unload plugin DLL to/from memory
Function BBP_LoadPlugin(ByVal hWnd As HWND, ByVal zPlugin As WString Ptr) As Long
    Dim nDone As Long = BBP_ERROR
    Dim nLen As Long = lstrlenW(zPlugin)
    if ((nLen) And (_wcsicmp(zPlugin, BBP_ActivePlugin(0,0)) <> 0)) Then
        if (FileExistW(*zPlugin)) Then
            if (gP.hLib) Then BBP_Detached(hWnd, gP.hLib)
            gP.hLib = LoadLibraryW(zPlugin)
            if (gP.hLib) Then
                Dim hProc As FARPROC = GetProcAddress(gP.hLib, "BBProc")

                If hProc <> 0 Then
                    BBP_ProcHandle(hProc, 1)
                    BBP_ActivePlugin(zPlugin, 1)
                    BBP_Reset()
                    nDone = BBP_SUCCESS
                End If
            End If
        End If
    ElseIf (nLen = 0) Then
        If (gP.hLib) Then BBP_Detached(hWnd, gP.hLib)
    End If
    Return nDone
End Function

Function BBP_AttachPlugin(ByVal zPlugin As WString Ptr) As Long
    gP.pluginloaded = 0

    If IsWindow(gP.hGL) Then
        If BBP_LoadPlugin(gP.hGL, zPlugin) = BBP_SUCCESS Then

            Dim BBP As BBPLUGIN
            ClearMemory(@BBP, SizeOf(BBP))

            BBP.msg      = BBP_INIT
            BBP.parent   = gP.hGL
            BBP.dc       = Cast(HDC, ZI_GetProperty(gP.hGL, ZI_GLDC))
            BBP.rc       = Cast(HGLRC, ZI_GetProperty(gP.hGL, ZI_GLRC))
            BBP.backargb = 0
            BBP_Plugin(BBP)

            BBP.msg = BBP_SIZE
            BBP_Plugin(BBP)

            wcscpy(@gP.bin.lastplugin, zPlugin)

            gP.pluginloaded = -1
        End If
    End If

    Return gP.pluginloaded
End Function

Sub BBP_RenderOpenGL(ByVal nLevel As DWORD, ByVal pInt As Short Ptr)
    Dim BBP As BBPLUGIN
    ClearMemory(@BBP, SizeOf(BBP))

    Dim glDC As HDC = Cast(HDC, ZI_GetProperty(gP.hGL, ZI_GLDC))
    Dim glRC As HGLRC = Cast(HGLRC, ZI_GetProperty(gP.hGL, ZI_GLRC))

    If glRC <> 0 Then
        BBP.msg         = BBP_RENDER
        BBP.parent      = gP.hGL
        BBP.dc          = glDC
        BBP.rc          = glRC
        BBP.lpeak       = SolvePeak(LOWORD(nLevel), 128)
        BBP.rpeak       = SolvePeak(HIWORD(nLevel), 128)
        BBP.backargb    = 0
        BBP.fftdata     = Cast(Any Ptr, BassChannelGetData())
        BBP.fftsize     = 256
        BBP.medialength = gB.medialength
        BBP.mediapos    = gB.mediapos
        BBP.wimdata     = pInt

        BBP_Plugin(BBP)

        ' Refresh display
        SwapBuffers(glDC)

        InvalidateRect(gP.hGL, NULL, 0)
        UpdateWindow(gP.hGL)
    End If

    ReleaseDC(gP.hGL, glDC)
End Sub

Sub BBP_NewSound()
    Dim BBP As BBPLUGIN
    ClearMemory(@BBP, SizeOf(BBP))
    BBP.msg = BBP_NEW_SOUND
    BBP_Plugin(BBP)
End Sub
The C/C++ visual plugins DLL are stored inside of the BBplugin folder, they are very small by modern bloated standard (from 11 to 32 Kb).

Link to download the project
UEZ
Posts: 1083
Joined: May 05, 2017 19:59
Location: Germany

Re: OpenGL visual plugins for Bass.dll

Post by UEZ »

Nice - thanks for sharing.

I need to learn the OpenGL stuff... :)
Patrice Terrier
Posts: 66
Joined: Jan 06, 2006 8:27
Location: France
Contact:

Re: OpenGL visual plugins for Bass.dll

Post by Patrice Terrier »

I need to learn the OpenGL stuff
Much to learn, and modern OpenGL is understanding only C to write GPU shader.

But the visual plugins can use any language as long as using OpenGL version 2+.
Post Reply