Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

BassVis Control 0.2 w/drag & drop

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • BassVis Control 0.2 w/drag & drop

    Here is the control version of BassVis now with drag & drop play.

    GdS

    Code:
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    '
    '                   BASSVISCTL.INC v0.2
    '
    ' Visualization control for BASS.DLL w/drag&drop
    '
    ' 10/2007 by Gus del Solar
    '
    ' You need bass23pb.inc by Steve Rossell from:
    ' http://www.powerbasic.com/support/pbforums/showthread.php?t=25060
    '
    ' and also BASS.DLL 2.3 by Ian Luck from: www.un4seen.com
    ' it is free for non commercial uses.
    '
    ' Based on: vb visualization examples from BASS.DLL docs
    '           and several snippets borrowed from this forum,
    '           my special acknowledges for its coders.
    ' This doesn't pretend to be ready for produccion...test it
    ' and enjoy, zero warranty. Comments are welcome.
    '
    ' USAGE EXAMPLE:
    '
    ' First call one time InitBassVisCtrl() to register the class, example:
    '
    '    SELECT CASE AS LONG CBMSG
    '           CASE %WM_INITDIALOG
    '                BASS_Init( -1, 44100, 0, CBHNDL, 0)  'Init BASS.DLL
    '                InitBassVisCtrl
    '
    ' Then create control/s:
    '
    ' %IDC_BASSVISCTL1 = 5005
    '
    ' CONTROL ADD "BASSVISCTL", CBHNDL, %IDC_BASSVISCTL1, "", 98, 104, 150, 90, _
    '              %WS_CHILD OR %WS_VISIBLE OR %SS_LEFT OR %SS_NOTIFY, %WS_EX_LEFT OR _
    '              %WS_EX_LTRREADING OR %WS_EX_ACCEPTFILES
    '
    ' Get the handle:
    ' CONTROL HANDLE CBHNDL, %IDC_BASSVISCTL1 TO g_bassvis1
    '
    ' Set a stream (previously got from BASS.DLL):
    '        bassvis_setstream g_bassvis1, hstream
    '
    ' Or drop an audio file and it will play.
    '
    ' Clicking the window changes display mode.
    '
    ' Sit and enjoy, that's all.
    '
    ' More options:
    '
    ' To manually set an osd text call this way:
    '        bassvis_setosdtext g_bassvis1, osdstring, x, y, duration'
    ' where x, y = text left/top coordinates, duration * 100 mseg
    '
    ' Enable and disable command bar buttons:
    '        bassvis_setstate g_bassvis1, states
    ' where states is a bitmask as follows:
    ' %BASSVIS_BTN_PREV   = 16
    ' %BASSVIS_BTN_PLAY   = 8
    ' %BASSVIS_BTN_PAUSE  = 4
    ' %BASSVIS_BTN_STOP   = 2
    ' %BASSVIS_BTN_NEXT   = 1
    '
    ' Receive messages from bassvis to control play/pause/etc:
    '
    ' CASE %WM_COMMAND
    '      SELECT CASE AS LONG CBCTL
    '             CASE %IDC_BASSVISCTL1
    '                  outtext "%IDC_BASSVISCTL"
    '                  SELECT CASE CBCTLMSG
    '                         CASE %WM_BASSVIS_PLAY
    '                              IF BASS_ChannelIsActive(gstream) = %BASS_ACTIVE_PAUSED THEN
    '                                 BASS_ChannelPlay(gstream, 0) 'resume
    '                              ELSE
    '                                 BASS_ChannelPlay(gstream, 1) 'play
    '                              END IF
    '                         CASE %WM_BASSVIS_PAUSE
    '                              '
    '                         CASE %WM_BASSVIS_STOP
    '                              '
    '                         CASE %WM_BASSVIS_PREV
    '                         CASE %WM_BASSVIS_NEXT
    '
    ' You can call this shortcuts subs or sendmessage...your decision.
    '
    ' More soon...enjoy, Gus
    '
    ''''''''''''''''''''''''''''''''''''''''
    
    #IF NOT %DEF(%BASS_H)
    
        #INCLUDE "bass23PB.inc"
    
    #ENDIF
    
    
    ''''''''''''''''''''''''''''''''''''''''
    ' modified structs and declares
    ''''''''''''''''''''''''''''''''''''''''
    
    TYPE mBITMAPINFO
            bmiHeader AS BITMAPINFOHEADER
            bmiColors(255) AS RGBQUAD
    END TYPE
    
    DECLARE FUNCTION mCreateDIBSection LIB "GDI32.DLL" ALIAS "CreateDIBSection" (BYVAL hdc AS DWORD, pbmi AS mBITMAPINFO, BYVAL dwUsage AS DWORD, BYVAL ppvBits AS DWORD, BYVAL hSection AS DWORD, BYVAL dwOffset AS DWORD) AS DWORD
    DECLARE SUB mFillMemory LIB "kernel32.dll" ALIAS "RtlFillMemory" (Destination AS ANY, BYVAL length AS LONG, BYVAL FILL AS BYTE)
    MACRO Pi = 3.141592653589793##
    
    ''''''''''''''''''''''''''''''''''''''''
    ' some utility routines
    ''''''''''''''''''''''''''''''''''''''''
    
    FUNCTION align32(toalign AS LONG) AS LONG
        FUNCTION = (toalign + 3) AND &hFFFFFFFC
    END FUNCTION
    
    FUNCTION EnumCharSet(elf AS ENUMLOGFONT, ntm AS NEWTEXTMETRIC, BYVAL FontType AS LONG, CharSet AS LONG) AS LONG
      ' Get type of character set - ansi, symbol.. a must for some fonts.
      CharSet = elf.elfLogFont.lfCharSet
    END FUNCTION
    
    FUNCTION MakeFontEx(BYVAL FontName AS STRING, BYVAL PointSize AS LONG, BYVAL fBold AS LONG, _
                        BYVAL fItalic AS LONG, BYVAL fUnderline AS LONG) AS DWORD
    '  Create a desirable font and return its handle. Original code by Dave Navarro
    '  NOTE: enhanced with proper enumeration of character set via EnumCharSet proc.
    '  modified by Borje Hagsten?
       LOCAL hDC AS DWORD, CharSet, CyPixels AS LONG
       hDC = GetDC(%HWND_DESKTOP)
       CyPixels = GetDeviceCaps(hDC, %LOGPIXELSY)
       EnumFontFamilies hDC, BYVAL STRPTR(FontName), CODEPTR(EnumCharSet), BYVAL VARPTR(CharSet)
       ReleaseDC %HWND_DESKTOP, hDC
       PointSize = 0 - (PointSize * CyPixels) \ 72
       FUNCTION = CreateFont(PointSize, 0, _  'height, width(default=0)
            0, 0, _                     'escapement(angle), orientation
            fBold, _                    'weight (%FW_DONTCARE = 0, %FW_NORMAL = 400, %FW_BOLD = 700)
            fItalic, _                  'Italic
            fUnderline, _               'Underline
            %FALSE, _                   'StrikeThru
            CharSet, %OUT_TT_PRECIS, _
            %CLIP_DEFAULT_PRECIS, %DEFAULT_QUALITY, _
            %FF_DONTCARE , BYCOPY FontName)
    END FUNCTION
    
    ''''''''''''
    'by Kev Peel
    FUNCTION GetDropFiles(BYVAL hDropParam AS DWORD) AS STRING
      LOCAL sDropFiles AS STRING, sText AS STRING, i AS LONG
      FOR i = 0 TO DragQueryFile(hDropParam, &HFFFFFFFF&, "", 0)-1
          sText = SPACE$(DragQueryFile(hDropParam, i, "", 0)+1)
          DragQueryFile hDropParam, i, BYVAL STRPTR(sText), LEN(sText)
          sText = LEFT$(sText, LEN(sText)-1)
          sDropFiles = sDropFiles + sText + "|"
      NEXT i
      DragFinish hDropParam
      FUNCTION = RTRIM$(sDropFiles, "|")
    END FUNCTION
    
    ''''''''''''''''''''''''''''''''''''''''
    ' constants intended to be public
    ''''''''''''''''''''''''''''''''''''''''
    
    %BASSVIS_SHOW_OSD   = 1                        'show options OSD
    %BASSVIS_SHOW_TIME  = 2                        'show options progress time
    %BASSVIS_SHOW_CMD   = 4                        'show options command bar
    %BASSVIS_SHOW_VOL   = 8                        'show options volume
    %BASSVIS_DROP_ENA   = 16                       'accept droped files
    
    %BASSVIS_BTN_PREV   = 16
    %BASSVIS_BTN_PLAY   = 8
    %BASSVIS_BTN_PAUSE  = 4
    %BASSVIS_BTN_STOP   = 2
    %BASSVIS_BTN_NEXT   = 1
    
    %WM_BASSVIS_FIRST     = %WM_USER + 505           '
    %WM_BASSVIS_SETTIC    = %WM_BASSVIS_FIRST +  6   'set refresh timer mseg (wparam), def. 100 mseg
    %WM_BASSVIS_SETMODE   = %WM_BASSVIS_FIRST +  8   'set visual mode (0 to 6 so far) (wparam)
    %WM_BASSVIS_SETSTR    = %WM_BASSVIS_FIRST + 39   'Attach a stream in wparam
    %WM_BASSVIS_GETOPT    = %WM_BASSVIS_FIRST + 40   'get show options
    %WM_BASSVIS_SETOPT    = %WM_BASSVIS_FIRST + 41   'set show options
    %WM_BASSVIS_GETPTR    = %WM_BASSVIS_FIRST + 42   'get struct ptr
    %WM_BASSVIS_SETOSDSTR = %WM_BASSVIS_FIRST + 43   'set osd string
    %WM_BASSVIS_SETOSDXYT = %WM_BASSVIS_FIRST + 44   'set osd corrdinates
    %WM_BASSVIS_BTNENABLE = %WM_BASSVIS_FIRST + 45   'buttons enables
    %WM_BASSVIS_GETSTR    = %WM_BASSVIS_FIRST + 46   'get current stream
    
    %WM_BASSVIS_PLAY      = %WM_BASSVIS_FIRST + 12   'sent by bassvis to parent to signal button press
    %WM_BASSVIS_STOP      = %WM_BASSVIS_FIRST + 14   ' "
    %WM_BASSVIS_PAUSE     = %WM_BASSVIS_FIRST + 16   ' "
    %WM_BASSVIS_NEXT      = %WM_BASSVIS_FIRST + 18   ' "
    %WM_BASSVIS_PREV      = %WM_BASSVIS_FIRST + 20   ' "
    %WM_BASSVIS_RPSO      = %WM_BASSVIS_FIRST + 22   ' " repeat song (not yet implemented)
    %WM_BASSVIS_RPLS      = %WM_BASSVIS_FIRST + 24   ' " repeat list (not yet implemented)
    %WM_BASSVIS_RPRN      = %WM_BASSVIS_FIRST + 26   ' " randomize songs (not yet implemented)
    %WM_BASSVIS_RDWN      = %WM_BASSVIS_FIRST + 28   ' " R btn down, wparam carry x, lparam y, to pop a menu?
    %WM_BASSVIS_LUP       = %WM_BASSVIS_FIRST + 30   ' " L btn down, wparam carry x, lparam y
    %WM_BASSVIS_RUP       = %WM_BASSVIS_FIRST + 32   ' " R btn up, wparam carry x, lparam y
    %WM_BASSVIS_LDWN      = %WM_BASSVIS_FIRST + 34   ' " L btn up, wparam carry x, lparam y
    
    ''''''''''''''''''''''''''''''''''''''''
    ' bassvis struct
    ''''''''''''''''''''''''''''''''''''''''
    
    TYPE bassvis_struct
         parent   AS LONG      'parent window
         id       AS LONG      'window id
         CtrlID   AS LONG      'ctl id
         str      AS HSTREAM   'stream attached if any
         x        AS LONG      'window x position
         y        AS LONG      'window y position
         w        AS LONG      'window wide
         h        AS LONG      'window height
         mseg     AS LONG      'refresh period in mseg
         mode     AS LONG      'vis mode, 0-8, -1 = alternate modes every 10 seg
         mhdc     AS DWORD     'memory dc
         mbmp     AS DWORD     'memory bitmap
         oldbmp   AS DWORD     'internal use don't touch
         hfnt1    AS DWORD     'osd message font
         hfnt2    AS DWORD     'command bar font
         oldfnt   AS DWORD     'internal use
         mpen     AS DWORD     'internal use
         oldpen   AS DWORD     'internal use
         mbrush   AS DWORD     'internal use
         oldbrush AS DWORD     'internal use
         mpal     AS DWORD     'internal use
         pkinc    AS DWORD     'internal use
         specpos  AS DWORD     'internal use
         peak(32) AS DWORD     'internal use
         showopt  AS DWORD     'internal flags
         repeat   AS DWORD     'repeat mode 0 list, 1 song, 2 randomize
         progpt   AS pointapi  'left/top point progress indicator
         cmdpt    AS pointapi  'left/top point command bar
         osdpt    AS pointapi  'left/top point osd
         hover    AS DWORD     'hover button flags
         btnclr   AS DWORD     'buttons color
         hoverclr AS DWORD     'buttons hover color
         disclr   AS DWORD     'buttons disabled color
         profclr  AS DWORD     'progress fore color
         probkclr AS DWORD     'progress back color, reserved byte = 1 means transparent
         bottomh  AS DWORD     'bottom margin to place command/progress bar
         osdstr   AS ASCIIZ * 128  'osd user defined string
         osdtime  AS DWORD     'osd duration (1 = 100 mseg)
         btnen    AS DWORD     'buttons enable, from left to right bit 4 = btn prev, 3 = play...bit 0 = btn next
         tittle   AS ASCIIZ * 30
         vol      AS LONG      'volume level
    END TYPE
    
    ''''''''''''''''''''''''''''''''''''''''
    ' constants and other things not intended to be public
    ''''''''''''''''''''''''''''''''''''''''
    
    %BASSVIS_MAIN_TIMER = 1007
    %BASSVIS_STOPPED    = 32
    
    TYPE VISID3TAG
         tag      AS STRING * 3
         tittle   AS STRING * 30
         artis    AS STRING * 30
         album    AS STRING * 30
         year     AS STRING * 4
         comment  AS STRING * 29
         genre    AS BYTE
    END TYPE
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Set osd message, this will reset any previous osd message
    ' x & y = location, mseg = duration * 100 mseg
    '
    SUB bassvis_setosdtext(hctl AS DWORD, BYVAL osd AS STRING, x AS LONG, y AS LONG, mseg AS LONG)
        LOCAL zstr AS ASCIIZ * 256
        zstr = osd
        sendmessage hctl, %WM_BASSVIS_SETOSDSTR, VARPTR(zstr), 0
        sendmessage hctl, %WM_BASSVIS_SETOSDXYT, MAK(DWORD, y, x), mseg
    END SUB
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Set current stream
    '
    SUB bassvis_setstream(hctl AS DWORD, BYVAL str AS LONG)
        sendmessage hctl, %WM_BASSVIS_SETSTR, str, 0
    END SUB
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Get current stream
    '
    FUNCTION bassvis_getstream(hctl AS DWORD) AS LONG
        FUNCTION = sendmessage (hctl, %WM_BASSVIS_GETSTR, 0, 0)
    END FUNCTION
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Set buttons enable/disable state
    '
    SUB bassvis_setstate(hctl AS DWORD, BYVAL states AS LONG)
        sendmessage hctl, %WM_BASSVIS_BTNENABLE, states, 0
    END SUB
    
    FUNCTION initbassvisctrl() AS LONG
          LOCAL wc AS WNDCLASSEX, OldClassName, NewClassName AS STRING
          LOCAL lpfnNewWndProc, cbWndExtra AS LONG
          cbWndExtra = 4
          lpfnNewWndProc = CODEPTR(bassviswinproc)
          OldClassName = "STATIC"
          NewClassName = "BASSVISCTL"
          wc.cbSize = SIZEOF(wc)
          IF GetClassInfoEx(BYVAL 0&, BYVAL STRPTR(OldClassName), wc) THEN
             CallWindowProc lpfnNewWndProc, 0, 0, wc.lpfnWndProc, wc.cbWndExtra
             wc.hInstance = GetModuleHandle(BYVAL 0&)
             wc.lpszClassName = STRPTR(NewClassName)
             wc.lpfnWndProc = lpfnNewWndProc
             wc.cbWndExtra = wc.cbWndExtra + cbWndExtra
             wc.hbrBackground     = GetStockObject(%null_BRUSH)
             FUNCTION = RegisterClassEx(wc)
          END IF
    END FUNCTION
    
    ''''''''''''''''''''''''''''''''''''''''''
    ' bassvis window proc
    ''''''''''''''''''''''''''''''''''''''''''
    FUNCTION bassviswinproc(BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
             LOCAL x1, y1, b0, sc, b1 AS LONG
             LOCAL bmwi2, bmhe2, idx, x, y AS LONG
             LOCAL hDc, maxptr, bands AS LONG
             LOCAL fft(), wave(), hfac, fftt, sum AS SINGLE
             LOCAL bmwi, bmhe, offptr AS LONG
             LOCAL rc AS rect, pt AS pointapi
             LOCAL ci AS BASS_CHANNELINFO
             LOCAL bst AS bassvis_struct PTR
             LOCAL leng, qprogress, dura, lens AS LONG
             LOCAL stmp1, stmp2 AS STRING
             LOCAL pbits AS BYTE PTR
             LOCAL hoverpen, btnpen, dispen, oldpen AS LONG
             LOCAL tag AS VISID3TAG PTR
             LOCAL sptr AS ASCIIZ PTR
             LOCAL scrclr AS LONG
    
             STATIC bh() AS mBITMAPINFO
             STATIC apbits () AS DWORD
             STATIC cost(), sint() AS SINGLE
             STATIC stars() AS LONG
             STATIC count AS LONG
    
             STATIC BaseWndProc    AS LONG
             STATIC OffsetWndExtra AS LONG
    
             IF (hWnd = 0) THEN BaseWndProc = wparam: OffsetWndExtra = lparam: EXIT FUNCTION
    
             IF (hWnd AND (wMsg <> %WM_CREATE)) THEN
                bst = GetWindowLong(hWnd, OffsetWndExtra)
                IF ISFALSE(bst) THEN FUNCTION = CallWindowProc(BaseWndProc, hWnd, wMsg, WPARAM, LPARAM): EXIT FUNCTION
             END IF
    
             REDIM fft(1024)
    
             SELECT CASE AS LONG wMsg
                    CASE %WM_CREATE
                         bst = HeapAlloc(GetProcessHeap, %HEAP_ZERO_MEMORY, SIZEOF(@bst))
                         IF bst THEN
                            SetWindowLong hwnd, OffsetWndExtra, bst
                         ELSE
                            FUNCTION = -1: EXIT FUNCTION
                         END IF
                         INCR count
                         getclientrect hwnd, rc
                         @bst.id = count
                         @bst.CtrlID = GetDlgCtrlID(hWnd)
                         @bst.x = rc.nleft
                         @bst.y = rc.ntop
                         @bst.w = align32(rc.nright - rc.nleft)
                         @bst.h = rc.nbottom - rc.ntop
                         @bst.mseg = 100
                         @bst.parent = GetWindowLong(hWnd, %GWL_HWNDPARENT)
                         @bst.mode   = 0
                         @bst.cmdpt.x = 5
                         @bst.cmdpt.y = @bst.h - 12
                         @bst.progpt.x = 72
                         @bst.progpt.y = @bst.h - 15
                         @bst.probkclr = &h00000001
                         @bst.profclr  = %RED
                         @bst.hoverclr = %YELLOW '
                         @bst.btnclr   = %RED    '
                         @bst.disclr   = %GRAY   '
                         @bst.bottomh  = 15
                         @bst.osdstr   = "BASSVIS 0.2 PB"
                         @bst.osdtime  = 50
                         @bst.osdpt.x = 10
                         @bst.osdpt.y = @bst.h \ 2
                         @bst.showopt = %BASSVIS_SHOW_TIME OR %BASSVIS_SHOW_CMD OR _
                                        %BASSVIS_SHOW_OSD OR %BASSVIS_SHOW_VOL OR _
                                        %BASSVIS_DROP_ENA
                         REDIM PRESERVE bh(@bst.id)
                         REDIM PRESERVE apbits(@bst.id)
                         hDc = getwindowdc (hwnd)
                         @bst.mpal = -1
                         @bst.mhdc = CreateCompatibleDC(hdc)
                         'replace this fonts if need
                         @bst.hFnt1 = MakeFontEx("Quartz", 18, %FW_BOLD, %true, %FALSE)
                         @bst.hFnt2 = MakeFontEx("Quartz", 12, %FW_BOLD, %true, %FALSE)
                         releasedc hwnd, hdc
                         'first win setup sin / cos tables and starsfield
                         IF @bst.id = 1 THEN
                            REDIM cost(360)
                            REDIM sint(360)
                            FOR sum = 1 TO 360
                                cost(sum) = COS(sum * PI / 180)
                                sint(sum) = SIN(sum * PI / 180)
                            NEXT
                            REDIM stars(200, 4)
                            FOR sum = 0 TO 199
                                stars(sum, 0) = RND(1, 360)                    'angle
                                stars(sum, 1) = 0 'RND(1, min&(bmwi2, bmhe))   'acc radius
                                stars(sum, 2) = RND(1, 5)                      'speed
                                stars(sum, 3) = RND(1, 3)                      'type
                            NEXT
                         END IF
                         @bst.mbrush = createsolidbrush(%BLACK)
                         idx = settimer(hwnd, %BASSVIS_MAIN_TIMER, @bst.mseg, BYVAL %null)
                    CASE %WM_NCDESTROY
                    'CASE %WM_DESTROY
                         killtimer hwnd, %BASSVIS_MAIN_TIMER
                         'clean all
                         deleteobject @bst.mbrush
                         deleteobject selectobject(@bst.mhdc, @bst.oldbmp)
                         deleteobject selectobject(@bst.mhdc, @bst.oldfnt)
                         deleteobject @bst.hfnt1
                         deleteobject @bst.hfnt2
                         deletedc @bst.mhdc
                         HeapFree GetProcessHeap, 0, bst
                    CASE %WM_DROPFILES
                         IF (@bst.showopt AND %BASSVIS_DROP_ENA) THEN
                            stmp1 = GetDropFiles(wparam)
                            IF LEN(stmp1) THEN
                               stmp2 = PARSE$(stmp1, "|", 1)
                               IF LEN(stmp2) THEN
                                  IF @bst.str THEN
                                     BASS_ChannelStop(@bst.str)
                                     BASS_StreamFree(@bst.str)
                                  END IF
                                  @bst.str = BASS_StreamCreateFile(0, stmp2 + $NUL, 0, 0, %BASS_STREAM_PRESCAN)
                                  bassvis_setstream hwnd, @bst.str
                                  BASS_ChannelPlay(@bst.str, 1)
                                  
                               END IF
                            END IF
                         END IF
                    CASE %WM_BASSVIS_SETSTR
                         'new stream setting msg
                         @bst.str = wparam
                         'try to get ID3 tag
                         tag = BASS_ChannelGetTags(wparam, %BASS_TAG_ID3)
                         'show tittle in osd
                         @bst.tittle = IIF$(tag, @tag.tittle, "")
                         IF tag THEN
                            @bst.osdstr = @tag.tittle
                            @bst.osdpt.x = 5
                            @bst.osdtime = 50
                            @bst.showopt = @bst.showopt OR %BASSVIS_SHOW_OSD
                         END IF
                    CASE %WM_BASSVIS_GETSTR
                         FUNCTION = @bst.str
                         EXIT FUNCTION
                    CASE %WM_BASSVIS_SETOPT
                         'show options setting msg
                         @bst.showopt = wparam
                    CASE %WM_BASSVIS_GETOPT
                         'show options asking msg
                         FUNCTION = @bst.showopt
                         EXIT FUNCTION
                    CASE %WM_BASSVIS_GETPTR
                         'struct ptr asking msg
                         FUNCTION = bst
                         EXIT FUNCTION
                    CASE %WM_BASSVIS_SETOSDSTR
                         'osd string setting msg
                         IF wparam THEN
                            sptr = wparam
                            @bst.osdstr = @sptr
                         ELSE
                            @bst.osdstr = ""
                         END IF
                    CASE %WM_BASSVIS_SETOSDXYT
                         'osd x-y setting msg
                         x = HI(WORD, wparam)
                         y = LO(WORD, wparam)
                         @bst.osdpt.x = IIF&(x, x, @bst.x \ 2) 'if 0 center it
                         @bst.osdpt.y = IIF&(y, y, @bst.y \ 2) 'if 0 center it
                         @bst.osdtime = lparam
                         @bst.showopt = @bst.showopt OR %BASSVIS_SHOW_OSD
                    CASE %WM_BASSVIS_BTNENABLE
                         'button enables setting msg
                         @bst.btnen = wparam
                    CASE %WM_BASSVIS_SETOPT
                         IF ((@bst.showopt AND %BASSVIS_STOPPED) AND ISFALSE(@bst.showopt AND %BASSVIS_STOPPED)) THEN
                            idx = settimer(hwnd, %BASSVIS_MAIN_TIMER, @bst.mseg, BYVAL %null)
                         ELSEIF (ISFALSE(@bst.showopt AND %BASSVIS_STOPPED) AND (@bst.showopt AND %BASSVIS_STOPPED)) THEN
                            killtimer hwnd, %BASSVIS_MAIN_TIMER
                         END IF
                         @bst.showopt = wparam
                    CASE %WM_BASSVIS_SETTIC
                         killtimer hwnd, %BASSVIS_MAIN_TIMER
                         @bst.mseg = wparam
                         idx = settimer(hwnd, %BASSVIS_MAIN_TIMER, @bst.mseg, BYVAL %null)
                    CASE %WM_BASSVIS_SETMODE
                         @bst.mode = wparam
                    CASE %WM_ENABLE
                         InvalidateRect hWnd, BYVAL %NULL, 0 : UpdateWindow hWnd
                         FUNCTION = 0: EXIT FUNCTION
                    CASE %WM_GETDLGCODE
                         FUNCTION = %DLGC_STATIC
                         EXIT FUNCTION
                    CASE %WM_ERASEBKGND
                         'hdc = wparam
                         'getclientrect hwnd, rc
                         'fillrect hdc, rc, @bst.mbrush
                         FUNCTION = 1: EXIT FUNCTION
                    CASE %WM_RBUTTONUP
                         'forward to parent, maybe useful to popup a menu
                         SendMessage @bst.parent, %WM_COMMAND, MAKDWD(@bst.CtrlID, %WM_BASSVIS_RUP), lparam
                    CASE %WM_RBUTTONDOWN
                    CASE %WM_LBUTTONUP
                         'check enables and send msg to parent if clicked
                         IF @bst.hover THEN
                            IF (@bst.hover AND %BASSVIS_BTN_PREV AND NOT(@bst.btnen)) THEN SendMessage @bst.parent, %WM_COMMAND, MAKDWD(@bst.CtrlID, %WM_BASSVIS_PREV), hWnd
                            IF (@bst.hover AND %BASSVIS_BTN_PLAY AND NOT(@bst.btnen)) THEN SendMessage @bst.parent, %WM_COMMAND, MAKDWD(@bst.CtrlID, %WM_BASSVIS_PLAY), hWnd
                            IF (@bst.hover AND %BASSVIS_BTN_PAUSE AND NOT(@bst.btnen)) THEN SendMessage @bst.parent, %WM_COMMAND, MAKDWD(@bst.CtrlID, %WM_BASSVIS_PAUSE), hWnd
                            IF (@bst.hover AND %BASSVIS_BTN_STOP AND NOT(@bst.btnen)) THEN SendMessage @bst.parent, %WM_COMMAND, MAKDWD(@bst.CtrlID, %WM_BASSVIS_STOP), hWnd
                            IF (@bst.hover AND %BASSVIS_BTN_NEXT AND NOT(@bst.btnen)) THEN SendMessage @bst.parent, %WM_COMMAND, MAKDWD(@bst.CtrlID, %WM_BASSVIS_NEXT), hWnd
                         ELSE
                            'no button clicked so lets change mode and show some text
                            @bst.mode = IIF&((@bst.hover = 0), (@bst.mode + 1) MOD 7, @bst.mode)
                            @bst.osdstr = CHOOSE$(@bst.mode + 1, "FFT", "BARS", "SPECTRUM", "WAVE", "PEAKS", "WEIRD THING", "STARFIELD")
                            @bst.osdpt.x = 30
                            @bst.osdtime = 30
                            @bst.showopt = @bst.showopt OR %BASSVIS_SHOW_OSD
                         END IF
                         FUNCTION = 1: EXIT FUNCTION
                    CASE %WM_LBUTTONDOWN
                         FUNCTION = 1: EXIT FUNCTION
                    CASE %WM_MOUSEMOVE
                         GetCursorPos pt
                         ScreenToClient hWnd, pt
                         '0-10, 11-22, 23-29, 30-42, 43-56
                         '<< button hittest
                         setrect rc, @bst.cmdpt.x, @bst.cmdpt.y, @bst.cmdpt.x + 10, @bst.cmdpt.y + 10
                         @bst.hover = IIF&(ptinrect(rc, pt.x, pt.y), %BASSVIS_BTN_PREV, 0)
                         setrect rc, @bst.cmdpt.x + 11, @bst.cmdpt.y, @bst.cmdpt.x + 22, @bst.cmdpt.y + 10
                         @bst.hover = IIF&(ptinrect(rc, pt.x, pt.y), @bst.hover OR %BASSVIS_BTN_PLAY, @bst.hover)
                         '|| button hittest
                         setrect rc, @bst.cmdpt.x + 23, @bst.cmdpt.y, @bst.cmdpt.x + 29, @bst.cmdpt.y + 10
                         @bst.hover = IIF&(ptinrect(rc, pt.x, pt.y), @bst.hover OR %BASSVIS_BTN_PAUSE, @bst.hover)
                         '# button hittest
                         setrect rc, @bst.cmdpt.x + 30, @bst.cmdpt.y, @bst.cmdpt.x + 42, @bst.cmdpt.y + 10
                         @bst.hover = IIF&(ptinrect(rc, pt.x, pt.y), @bst.hover OR %BASSVIS_BTN_STOP, @bst.hover)
                         '>> button hittest
                         setrect rc, @bst.cmdpt.x + 43, @bst.cmdpt.y, @bst.cmdpt.x + 56, @bst.cmdpt.y + 10
                         @bst.hover = IIF&(ptinrect(rc, pt.x, pt.y), @bst.hover OR %BASSVIS_BTN_NEXT, @bst.hover)
                         'outtext frs(pt.x) + frs(pt.y) + frs(@bst.hover)
                    CASE %WM_TIMER
                         bmwi = @bst.w
                         bmhe = @bst.h
                         bmwi2 = bmwi \ 2
                         bmhe2 = (bmhe - @bst.bottomh) \ 2
                         hfac = IIF((bmhe - @bst.bottomh), 256 / (bmhe - @bst.bottomh), 0)
                         offptr = @bst.bottomh * bmwi
                         maxptr = bmwi * bmhe
    
                         hDc = getwindowdc (hwnd)
    
                         IF (@bst.mpal <> @bst.mode) THEN
                            ' setup bitmap
                            IF @bst.oldbmp THEN selectobject(@bst.mhdc, @bst.oldbmp)
                            IF @bst.mbmp THEN deleteobject @bst.mbmp
                            bh(@bst.id).bmiHeader.biBitCount = 8
                            bh(@bst.id).bmiHeader.biPlanes = 1
                            bh(@bst.id).bmiHeader.biSize = SIZEOF(bh(0).bmiHeader)
                            bh(@bst.id).bmiHeader.biWidth = bmwi
                            bh(@bst.id).bmiHeader.biHeight = bmhe
                            bh(@bst.id).bmiHeader.biClrUsed = 256
                            bh(@bst.id).bmiHeader.biClrImportant = 256
                            ' setup palette
                            ZeroMemory(VARPTR(bh(@bst.id).bmiColors(0)), 256 * 3)
                            'how each mode can set it's own palette example ...
                            SELECT CASE @bst.mode
                                   CASE 0, 2, 3
                                        FOR x = 1 TO 255
                                            bh(@bst.id).bmiColors(x).rgbGreen = 256 - x
                                            bh(@bst.id).bmiColors(x).rgbRed   = x
                                            bh(@bst.id).bmiColors(x).rgbBlue  = x * SQR(1/x)
                                        NEXT
                                   CASE 1
                                        FOR x = 1 TO 255 STEP 10
                                            FOR y = x TO x + 5
                                                bh(@bst.id).bmiColors(y).rgbGreen = 256 - x
                                                bh(@bst.id).bmiColors(y).rgbRed   = x
                                                bh(@bst.id).bmiColors(y).rgbBlue  = x * SQR(1/x)
                                            NEXT
                                        NEXT
                                   CASE 4, 5, 6, 7, 8, 9, 10
                                        FOR x = 1 TO 255 STEP 8
                                            FOR y = x TO x + 5
                                                bh(@bst.id).bmiColors(y).rgbGreen = 256 - x
                                                bh(@bst.id).bmiColors(y).rgbRed   = x
                                                bh(@bst.id).bmiColors(y).rgbBlue  = x * SQR(1/x)
                                            NEXT
                                        NEXT
                            END SELECT
                            bh(@bst.id).bmiColors(255).rgbGreen = 255
                            bh(@bst.id).bmiColors(255).rgbRed   = 255
                            bh(@bst.id).bmiColors(255).rgbBlue  = 0
                            ' and it's own special variables
                            SELECT CASE @bst.mode
                                   CASE 0, 2, 3
                                   CASE 1
                                   CASE 4
                                   CASE 5, 6
                            END SELECT
                            @bst.mbmp = mCreateDIBSection(@bst.mhdc, bh(@bst.id), %DIB_RGB_COLORS, BYVAL VARPTR(pbits), 0, 0)
                            @bst.oldbmp = selectobject(@bst.mhdc, @bst.mbmp)
                            @bst.mpal = @bst.mode
                            apbits(@bst.id) = pbits
                         END IF
                         pbits = apbits(@bst.id)
                         '"effects" from 0 to 6, add new ones if desired
                         SELECT CASE @bst.mode
                                CASE 0   ' "normal" FFT
                                     BASS_ChannelGetData(@bst.str, VARPTR(fft(0)), %BASS_DATA_FFT2048)
                                     ZeroMemory(pbits, maxptr): scrclr = 1
                                     fftt = FIX((1024 \ (bmwi \ 2)) * 10) \ 10
                                     FOR X = 0 TO (bmwi / 2) - 1
                                         ' scale it (sqr to make low values more visible)
                                         Y = SQR(fft(X + 1 * fftt)) * 3 * (bmhe - @bst.bottomh) - 4
                                         ' scale it (linearly)
                                         'Y = fft(X + 1) * 10 * bmhe
                                         ' cap it
                                         y = IIF&(y > ((bmhe - @bst.bottomh) - 1), (bmhe - @bst.bottomh) - 1, y)
                                         ' interpolate from previous to make the display smoother
                                         IF (X) THEN
                                             y1 = (Y + y1) / 2
                                             DECR y1
                                             WHILE (y1 >= 0)
                                                 idx = MIN&((Y1 * bmwi) + ((X * 2) - 1) + offptr, maxptr)
                                                 @pbits[idx] = MIN&((y1 + 1) * hfac, 255)
                                                 DECR y1
                                             WEND
                                         END IF
                                         y1 = Y
                                         DECR y
                                         WHILE (Y >= 0)
                                             ' draw level
                                             idx = MIN&((Y * bmwi) + (X * 2) + offptr, maxptr)
                                             @pbits[idx] = MIN&((y + 1) * hfac, 255)
                                             DECR y
                                         WEND
                                     NEXT X
                                CASE 1   'logarithmic, acumulate & average bins
                                     bands = MIN&(bmwi \ 10, 32)
                                     BASS_ChannelGetData(@bst.str, VARPTR(fft(0)), %BASS_DATA_FFT2048)
                                     ' clear display
                                     ZeroMemory(pbits, maxptr): scrclr = 1
                                     FOR X = 0 TO BANDS - 1
                                         sum = 0
                                         b1 = 2 ^ (X * 10# / (BANDS - 1))
                                         b1 = IIF&(b1 > 1023, 1023, b1)
                                         ' make sure it uses at least 1 FFT bin
                                         b1 = IIF&(b1 <= b0, b0 + 1, b1)
                                         sc = 10 + b1 - b0
                                         DO
                                             sum = sum + fft(1 + b0)
                                             b0 = b0 + 1
                                         LOOP WHILE b0 < b1
                                         ' scale it
                                         Y = (SQR(sum / LOG10(sc)) * 1.7 * (bmhe - @bst.bottomh)) - 4
                                         ' cap it
                                         y = IIF&(Y > (bmhe - @bst.bottomh), (bmhe - @bst.bottomh), y)
                                         DECR y
                                         WHILE (Y >= 0)
                                             idx = MIN&(Y * bmwi + X * INT(bmwi / BANDS) + offptr, maxptr)
                                             mFillMemory(@pbits[idx], (bmwi / BANDS) - 2, MIN&(y * hfac, 255))
                                             DECR Y
                                         WEND
                                     NEXT X
                                CASE 2   '3D
                                     BASS_ChannelGetData(@bst.str, VARPTR(fft(0)), %BASS_DATA_FFT2048)
                                     FOR X = 0 TO (bmhe - @bst.bottomh) - 1
                                         ' scale it (sqr to make low values more visible)
                                         Y = SQR(fft(X + 1)) * 3 * (bmhe - @bst.bottomh) - 1    '127
                                         y = IIF(Y > ((bmhe - @bst.bottomh) - 1), (bmhe - @bst.bottomh) - 1, y)
                                         ' plot it
                                         idx = MIN&(X * bmwi + @bst.specpos + offptr, maxptr)
                                         @pbits[idx] = ((bmhe + Y) * hfac)
                                     NEXT X
                                     ' move marker onto next position
                                     @bst.specpos = (@bst.specpos + 1) MOD bmwi
                                     FOR X = 0 TO (bmhe - @bst.bottomh) - 1
                                         idx = MIN&(X * bmwi + @bst.specpos + offptr, maxptr)
                                         @pbits[idx] = 255
                                     NEXT X
                                CASE 3   'waveform
                                     ' clear display
                                     ZeroMemory(pbits, maxptr): scrclr = 1
                                     ' get number of channels
                                     BASS_ChannelGetInfo(@bst.str, ci)
                                     ' allocate buffer for data
                                     REDIM wave(ci.chans * bmwi * SIZEOF(wave(0)))
                                     ' get the sample data (floating-point to avoid 8 & 16 bit processing)
                                     BASS_ChannelGetData(@bst.str, VARPTR(wave(0)), (ci.chans * bmwi * SIZEOF(wave(0))) OR %BASS_DATA_FLOAT)
                                     FOR b0 = 0 TO ci.chans - 1
                                         FOR X = 0 TO bmwi - 1
                                             ' invert and scale to fit display
                                             b1 = (1 - wave(X * ci.chans + b0)) * bmhe2
                                             b1 = IIF&(b1 < 0, 0, b1)
                                             b1 = IIF&(b1 > (bmhe - @bst.bottomh), (bmhe - @bst.bottomh) -1, b1)
                                             y = IIF&(x = 0, b1, y)
                                             DO
                                                 ' draw line from previous sample...
                                                 y = IIF&(y < b1, y + 1, y)
                                                 y = IIF&(y > b1, y - 1, y)
                                                 ' left=green, right=red (could add more colours to palette for more chans)
                                                 idx = MIN&((Y * bmwi + X) + offptr, maxptr)
                                                 @pbits[idx] = IIF&(b0 AND 1, 252, 1)
                                             LOOP WHILE (Y <> b1)
                                         NEXT
                                     NEXT
                                CASE 4   'bars and peaks
                                     BASS_ChannelGetData(@bst.str, VARPTR(fft(0)), %BASS_DATA_FFT2048)
                                     bands = MIN&(bmwi \ 10, 32)
                                     @bst.pkinc = IIF&(@bst.pkinc + 1 = 3, 0, @bst.pkinc + 1)
                                     ' clear display
                                     ZeroMemory(pbits, maxptr): scrclr = 1
                                     FOR X = 0 TO BANDS - 1
                                         sum = 0
                                         b1 = 2 ^ (X * 10# / (BANDS - 1))
                                         b1 = MIN&(b1, 1023) 'IIF&(b1 > 1023, 1023, b1)
                                         ' make sure it uses at least 1 FFT bin
                                         b1 = IIF&(b1 <= b0, b0 + 1, b1)
                                         sc = 10 + b1 - b0
                                         DO
                                             sum = sum + fft(1 + b0)
                                             b0 = b0 + 1
                                         LOOP WHILE b0 < b1
                                         ' scale it
                                         Y = (SQR(sum / LOG10(sc)) * 1.7 * (bmhe - @bst.bottomh)) - 4
                                         ' cap it
                                         y = IIF&(Y > (bmhe - @bst.bottomh), (bmhe - @bst.bottomh), y)
                                         DECR y
                                         @bst.peak(x) = MAX&(@bst.peak(x), y, 5)
                                         WHILE (Y >= 0)
                                             idx = MIN&(Y * bmwi + X * INT(bmwi / BANDS) + offptr, maxptr)
                                             mFillMemory(@pbits[idx], (bmwi / BANDS) - 2, MIN&(y * hfac, 255))
                                             DECR Y
                                         WEND
                                         FOR y = @bst.peak(x) - 5 TO @bst.peak(x)
                                             idx = MIN&(Y  * bmwi + X * INT(bmwi / BANDS) + offptr, maxptr)
                                             mFillMemory(@pbits[idx], (bmwi / BANDS) - 2, 255)
                                             @bst.peak(x) = IIF&(@bst.pkinc = 0, MAX&(@bst.peak(x) - 5, 5), @bst.peak(x))
                                         NEXT
                                     NEXT X
                                CASE 5  'weird thing
                                     BASS_ChannelGetData(@bst.str, VARPTR(fft(0)), %BASS_DATA_FFT2048)
                                     ZeroMemory(pbits, maxptr): scrclr = 1
                                     fftt = (FIX((1024 \ 360) * 10) \ 10)
                                     FOR b1 = 1 TO 360
                                         X = bmwi2 + (bmwi * SQR(fft(b1 * fftt)) * cost(b1)) * 3
                                         Y = bmhe2 + ((bmhe - @bst.bottomh) * SQR(fft(b1 * fftt)) * sint(b1)) * 3
                                         IF b1 = 1 THEN
                                            movetoex @bst.mhdc, x, y, pt
                                         ELSE
                                            lineto @bst.mhdc, x, y
                                         END IF
                                         idx = MAX&(0, MIN&((y * bmwi) + x  + offptr, maxptr))
                                         @pbits[idx] = RND(1, 255) '255 - (255 * SQR(fft(b1 * fftt)))
                                     NEXT
                                CASE 6  'crude star field
                                     'BASS_ChannelGetData(@bst.str, VARPTR(fft(0)), %BASS_DATA_FFT2048)
                                     ZeroMemory(pbits, maxptr): scrclr = 1
                                     fftt = (FIX((1024 \ 360) * 10) \ 10)
                                     FOR b1 = 0 TO 199
                                         IF @bst.id = 1 THEN
                                            IF stars(b1, 0) = 0 THEN
                                               stars(b1, 0) = RND(1, 360) * CINT(RND)
                                               stars(b1, 1) = 1 'RND(1, 3)
                                               stars(b1, 2) = RND(1, 5)
                                            END IF
                                         END IF
                                         X = bmwi2 + (stars(b1, 1) * cost(stars(b1, 0)))
                                         Y = bmhe2 + (stars(b1, 1) * sint(stars(b1, 0)))
                                         IF @bst.id = 1 THEN
                                            stars(b1, 0) = IIF&(x < 0, 0, stars(b1, 0))
                                            stars(b1, 0) = IIF&(x > bmwi, 0, stars(b1, 0))
                                            stars(b1, 0) = IIF&(y < 0, 0, stars(b1, 0))
                                            stars(b1, 0) = IIF&(y > (bmhe - @bst.bottomh), 0, stars(b1, 0))
                                            stars(b1, 1) = stars(b1, 1) + stars(b1, 2)
                                         END IF
                                         idx = MAX&(0, MIN&((Y * bmwi) + x + offptr, maxptr))
                                         @pbits[idx] = RND(1, 255)
                                     NEXT
                                CASE 7
                                CASE 8
                                     'Add your effects here...
                         END SELECT
                         'check volume level
                         x = BASS_GetVolume
                         IF ((x <> @bst.vol) AND (@bst.showopt AND %BASSVIS_SHOW_VOL))THEN
                            @bst.osdstr = "VOLUME " + FORMAT$(x)
                            @bst.osdpt.x = 50
                            @bst.osdpt.y = 50
                            @bst.osdtime = 30
                            @bst.showopt = @bst.showopt OR %BASSVIS_SHOW_OSD
                            @bst.vol = x
                         END IF
                         'check flags and show progress
                         IF (@bst.showopt AND %BASSVIS_SHOW_TIME) THEN
                            leng      = BASS_ChannelGetLength(@bst.str)
                            qprogress = BASS_ChannelGetPosition(@bst.str)
                            dura = BASS_ChannelBytes2Seconds(@bst.str, qprogress)
                            lens = BASS_ChannelBytes2Seconds(@bst.str, leng)
                            dura = IIF&(dura > -1, dura, 0)
                            lens = IIF&(lens > -1, lens, 0)
                            stmp1 = FORMAT$(INT(dura \ 60), "00") + ":" + FORMAT$(INT(dura MOD 60), "00")
                            stmp2 = FORMAT$(INT(lens \ 60), "00") + ":" + FORMAT$(INT(lens MOD 60), "00")
                            stmp1 = stmp1 + "/" + stmp2 + " " + CHR$(65 + @bst.mode)
                            settextcolor @bst.mhdc, @bst.profclr 'rgb(&hff, &ha5, 0)
                            selectobject @bst.mhdc, @bst.hfnt2
                            IF @bst.probkclr AND &h01 THEN
                               setbkmode @bst.mhdc, %TRANSPARENT
                            ELSE
                               setbkmode @bst.mhdc, %OPAQUE
                               setbkcolor @bst.mhdc, (@bst.probkclr AND &hfffffffe)
                            END IF
                            setrect rc, @bst.progpt.x, @bst.progpt.y, @bst.progpt.x + 30, @bst.progpt.y
                            drawtext @bst.mhdc, BYVAL STRPTR(stmp1), LEN(stmp1), rc, %DT_CALCRECT OR %DT_LEFT OR %DT_VCENTER
                            IF ISFALSE(scrclr) THEN fillrect @bst.mhdc, rc, @bst.mbrush
                            drawtext @bst.mhdc, BYVAL STRPTR(stmp1), LEN(stmp1), rc, %DT_LEFT OR %DT_VCENTER OR %DT_NOCLIP OR %DT_NOPREFIX
                         END IF
                         'let check flags and show osd if need
                         IF (@bst.showopt AND %BASSVIS_SHOW_OSD) THEN
                             settextcolor @bst.mhdc, %RED
                             selectobject @bst.mhdc, @bst.hfnt1
                             setbkmode @bst.mhdc, %TRANSPARENT
                             setrect rc, @bst.osdpt.x, @bst.osdpt.y, @bst.osdpt.x + 30, @bst.osdpt.y
                             drawtext @bst.mhdc, BYVAL VARPTR(@bst.osdstr), LEN(@bst.osdstr), rc, %DT_CALCRECT OR %DT_LEFT OR %DT_VCENTER
                             IF ISFALSE(scrclr) THEN fillrect @bst.mhdc, rc, @bst.mbrush
                             drawtext @bst.mhdc, BYVAL VARPTR(@bst.osdstr), LEN(@bst.osdstr), rc, %DT_LEFT OR %DT_VCENTER OR %DT_NOCLIP OR %DT_NOPREFIX
                             DECR @bst.osdtime
                             @bst.showopt = IIF&(@bst.osdtime < 1, @bst.showopt AND NOT(%BASSVIS_SHOW_OSD), @bst.showopt)
                         END IF
                         'check flags and command bar
                         IF (@bst.showopt AND %BASSVIS_SHOW_CMD) THEN
                             hoverpen = createpen(%ps_solid, 2, @bst.hoverclr)
                             btnpen = createpen(%ps_solid, 2, @bst.btnclr)
                             dispen = createpen(%ps_solid, 2, @bst.disclr)
                             oldpen = selectobject(@bst.mhdc, btnpen)
                             'buttons are ~ 10x 10y
                             'check and draw << button
                             selectobject(@bst.mhdc, IIF&((@bst.btnen AND %BASSVIS_BTN_PREV), dispen, IIF&((@bst.hover AND %BASSVIS_BTN_PREV), hoverpen, btnpen)))
                             movetoex @bst.mhdc, @bst.cmdpt.x + 5, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x, @bst.cmdpt.y + 5
                             lineto @bst.mhdc, @bst.cmdpt.x + 5, @bst.cmdpt.y + 10
                             movetoex @bst.mhdc, @bst.cmdpt.x + 10, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 5, @bst.cmdpt.y + 5
                             lineto @bst.mhdc, @bst.cmdpt.x + 10, @bst.cmdpt.y + 10
                             'check and draw > button
                             selectobject(@bst.mhdc, IIF&((@bst.btnen AND %BASSVIS_BTN_PLAY), dispen, IIF&((@bst.hover AND %BASSVIS_BTN_PLAY), hoverpen, btnpen)))
                             movetoex @bst.mhdc, @bst.cmdpt.x + 15, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 20, @bst.cmdpt.y + 5
                             lineto @bst.mhdc, @bst.cmdpt.x + 15, @bst.cmdpt.y + 10
                             lineto @bst.mhdc, @bst.cmdpt.x + 15, @bst.cmdpt.y
                             'check and draw || button
                             selectobject(@bst.mhdc, IIF&((@bst.btnen AND %BASSVIS_BTN_PAUSE), dispen, IIF&((@bst.hover AND %BASSVIS_BTN_PAUSE), hoverpen, btnpen)))
                             movetoex @bst.mhdc, @bst.cmdpt.x + 25, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 25, @bst.cmdpt.y + 10
                             movetoex @bst.mhdc, @bst.cmdpt.x + 28, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 28, @bst.cmdpt.y + 10
                             'check and draw # button
                             selectobject(@bst.mhdc, IIF&((@bst.btnen AND %BASSVIS_BTN_STOP), dispen, IIF&((@bst.hover AND %BASSVIS_BTN_STOP), hoverpen, btnpen)))
                             movetoex @bst.mhdc, @bst.cmdpt.x + 35, @bst.cmdpt.y + 1, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 42, @bst.cmdpt.y + 1
                             lineto @bst.mhdc, @bst.cmdpt.x + 42, @bst.cmdpt.y + 9
                             lineto @bst.mhdc, @bst.cmdpt.x + 35, @bst.cmdpt.y + 9
                             lineto @bst.mhdc, @bst.cmdpt.x + 35, @bst.cmdpt.y + 1
                             'check and draw >> button
                             selectobject(@bst.mhdc, IIF&((@bst.btnen AND %BASSVIS_BTN_NEXT), dispen, IIF&((@bst.hover AND %BASSVIS_BTN_NEXT), hoverpen, btnpen)))
                             movetoex @bst.mhdc, @bst.cmdpt.x + 48, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 53, @bst.cmdpt.y + 5
                             lineto @bst.mhdc, @bst.cmdpt.x + 48, @bst.cmdpt.y + 10
                             movetoex @bst.mhdc, @bst.cmdpt.x + 53, @bst.cmdpt.y, pt
                             lineto @bst.mhdc, @bst.cmdpt.x + 58, @bst.cmdpt.y + 5
                             lineto @bst.mhdc, @bst.cmdpt.x + 53, @bst.cmdpt.y + 10
                             selectobject(@bst.mhdc, oldpen)
                             deleteobject hoverpen
                             deleteobject btnpen
                             deleteobject dispen
                         END IF
                         'all done, bitblt it
                         bitblt hdc, 0, 0, bmwi, bmhe, @bst.mhdc, 0, 0, %SRCCOPY
                         'give it back to windows
                         releasedc hwnd, hDc
             END SELECT
             'function = defwindowproc(hwnd, wmsg, wparam, lparam)
             FUNCTION = CallWindowProc(BaseWndProc, hWnd, wMsg, WPARAM, LPARAM)
    END FUNCTION

  • #2
    BassVis demo code

    .
    BASS DEMO by James Klutho modified to show BassVisCtl.

    Drop a supported audio file.

    GdS

    Code:
    '
    '
    'BASS DEMO by James Klutho modified to show BassVisCtl
    '
    '
    #PBFORMS CREATED V1.51
    '------------------------------------------------------------------------------
    ' The first line in this file is a PB/Forms metastatement.
    ' It should ALWAYS be the first line of the file. Other
    ' PB/Forms metastatements are placed at the beginning and
    ' end of "Named Blocks" of code that should be edited
    ' with PBForms only. Do not manually edit or delete these
    ' metastatements or PB/Forms will not be able to reread
    ' the file correctly.  See the PB/Forms documentation for
    ' more information.
    ' Named blocks begin like this:    #PBFORMS BEGIN ...
    ' Named blocks end like this:      #PBFORMS END ...
    ' Other PB/Forms metastatements such as:
    '     #PBFORMS DECLARATIONS
    ' are used by PB/Forms to insert additional code.
    ' Feel free to make changes anywhere else in the file.
    '------------------------------------------------------------------------------
    
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    #INCLUDE "bass23PB.inc"
    #INCLUDE "bassvisctl.inc"   'the above INC file
    #INCLUDE "COMDLG32.INC"
    
    GLOBAL g_stream AS HSTREAM
    GLOBAL g_hWndMain AS LONG
    GLOBAL g_bassvis AS LONG
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDC_GETFILE  = 1004
    %IDC_PAUSE    = 1002
    %IDC_PLAY     = 1001
    %IDC_STOP     = 1003
    %IDD_BASSDEMO =  101
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    %IDC_BASSVISCTL1 = 5005
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowBASSDEMOProc()
    DECLARE FUNCTION ShowBASSDEMO(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    SUB Play(Filename AS STRING)
        LOCAL fn AS ASCIIZ * 255
        fn=Filename
        g_stream = BASS_StreamCreateFile(0,fn, 0, 0, %BASS_STREAM_PRESCAN)
        IF g_stream <> 0 THEN
          BASS_ChannelPlay(g_stream,1)
        END IF
    END SUB
    
    SUB OpenAudioFile()
        LOCAL  Filename AS STRING
        LOCAL f AS STRING
        LOCAL Path AS STRING
        LOCAL myStyle AS LONG
        LOCAL FileSpec AS STRING
        Path  = CURDIR$
        f = ""
        MySTYLE = %OFN_FILEMUSTEXIST OR %OFN_HIDEREADONLY OR %OFN_LONGNAMES
        IF OpenFileDialog(g_hWndMain, "Choose an Audio File", f, Path, "Audio Formats: (mp1,mp2,mp3,ogg,wave,aif)|*.mp1;*.mp2;*.mp3;*.ogg;*.wav;*.aif| |", "wav", MySTYLE) THEN
            filename=f
            IF filename <> "" THEN
              'if g_stream not stopped
              IF BASS_ChannelIsActive(g_stream) <> %BASS_ACTIVE_STOPPED THEN
                BASS_ChannelStop(g_stream)
                BASS_StreamFree(g_stream)
              END IF
              FileSpec = PARSE$(FileName,"\",-1)
              DIALOG SET TEXT g_hWndMain, FileSpec
              Play(filename)
            END IF
        END IF
    END SUB
    
    FUNCTION PBMAIN()
        ShowBASSDEMO %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowBASSDEMOProc()
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ' Initialization handler
                  BASS_Init( -1, 44100, 0, 0, 0)
                  initbassvisctrl
                  CONTROL ADD "BASSVISCTL", CBHNDL, %IDC_BASSVISCTL1, "", 10, 10, 150, 90, _
                        %WS_CHILD OR %WS_VISIBLE OR %SS_LEFT OR %SS_NOTIFY, %WS_EX_LEFT OR _
                        %WS_EX_LTRREADING OR %WS_EX_ACCEPTFILES
                  CONTROL HANDLE CBHNDL, %IDC_BASSVISCTL1 TO g_bassvis
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE %WM_COMMAND
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
                     CASE %IDC_BASSVISCTL1
                          SELECT CASE CBCTLMSG
                                 CASE %WM_BASSVIS_PLAY
                                      IF BASS_ChannelIsActive(bassvis_getstream(g_bassvis)) = %BASS_ACTIVE_PAUSED THEN
                                         BASS_ChannelPlay(bassvis_getstream(g_bassvis), 0)  'pick up where paused
                                      ELSE
                                         BASS_ChannelPlay(bassvis_getstream(g_bassvis) ,1)  'restart at beginning
                                      END IF
                                 CASE %WM_BASSVIS_PAUSE
                                      IF BASS_ChannelIsActive(bassvis_getstream(g_bassvis)) = %BASS_ACTIVE_PAUSED THEN
                                         BASS_ChannelPlay(bassvis_getstream(g_bassvis), 0)  'pick up where paused
                                      ELSE
                                         BASS_ChannelPause(bassvis_getstream(g_bassvis))
                                      END IF
                                 CASE %WM_BASSVIS_STOP
                                      BASS_ChannelStop(bassvis_getstream(g_bassvis))
                                 CASE %WM_BASSVIS_PREV
                                 CASE %WM_BASSVIS_NEXT
                          END SELECT
                    CASE %IDC_PLAY
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            IF g_stream <> 0 THEN
                               IF BASS_ChannelIsActive(g_stream) = %BASS_ACTIVE_PAUSED THEN
                                    BASS_ChannelPlay(g_stream,0)  'pick up where paused
                               ELSE
                                    BASS_ChannelPlay(g_stream,1)  'restart at beginning
                               END IF
                              ELSE
                                OpenAudioFile
                            END IF
                            CONTROL DISABLE CBHNDL, %IDC_PLAY
                            CONTROL ENABLE CBHNDL, %IDC_PAUSE
                            CONTROL ENABLE CBHNDL, %IDC_STOP
                        END IF
    
                    CASE %IDC_PAUSE
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            IF g_stream <> 0 THEN
                                BASS_ChannelPause(g_stream)
                                CONTROL ENABLE CBHNDL, %IDC_PLAY
                                CONTROL DISABLE CBHNDL, %IDC_PAUSE
                                CONTROL ENABLE CBHNDL, %IDC_STOP
                            END IF
                        END IF
    
                    CASE %IDC_STOP
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            IF g_stream <> 0 THEN
                                BASS_ChannelStop(g_stream)
                                CONTROL ENABLE CBHNDL, %IDC_PLAY
                                CONTROL DISABLE CBHNDL, %IDC_PAUSE
                                CONTROL DISABLE CBHNDL, %IDC_STOP
                            END IF
                        END IF
    
                    CASE %IDC_GETFILE
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                           OpenAudioFile
                           IF BASS_ChannelIsActive(g_stream) = %BASS_ACTIVE_PLAYING THEN
                               bassvis_setstream g_bassvis, g_stream
                               CONTROL DISABLE CBHNDL, %IDC_PLAY
                               CONTROL ENABLE CBHNDL, %IDC_PAUSE
                               CONTROL ENABLE CBHNDL, %IDC_STOP
                           END IF
                        END IF
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowBASSDEMO(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
        LOCAL Count AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_BASSDEMO->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "BassVisCtl DLL Demo", 233, 47, 176, 120, %WS_POPUP OR _
            %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
            %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
            %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD BUTTON, hDlg, %IDC_PLAY, "Play", 6, 172, 50, 15
        CONTROL ADD BUTTON, hDlg, %IDC_PAUSE, "Pause", 60, 172, 50, 15
        CONTROL ADD BUTTON, hDlg, %IDC_STOP, "Stop", 114, 172, 50, 15
        CONTROL ADD BUTTON, hDlg, %IDC_GETFILE, "...", 166, 172, 20, 15
    #PBFORMS END DIALOG
        CONTROL DISABLE hDlg, %IDC_PAUSE
        CONTROL DISABLE hDlg, %IDC_STOP
        DIALOG SHOW MODAL hDlg, CALL ShowBASSDEMOProc TO lRslt
    
        BASS_Free()
    #PBFORMS BEGIN CLEANUP %IDD_BASSDEMO
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    Last edited by Guest; 11 Oct 2007, 06:59 AM.

    Comment


    • #3
      Visual plugins

      Gus,

      Have you seen this:
      ZAP Visual plugins

      Also if you want to contribute to my open source BassBox project (on Jose Roca's forum), then you are welcomed.

      ...
      Last edited by Patrice Terrier; 11 Oct 2007, 01:02 AM.
      Patrice Terrier
      www.zapsolution.com
      www.objreader.com
      Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

      Comment


      • #4
        Hi Patrice,

        Wow, congrats. That looks really nice.
        That is not clear to me, is the player also free?
        I'll subscribe there, since we are in source code forum.

        Thanks.

        Comment


        • #5
          Gus,

          ZAP Media Lite is freeware.

          And the version with CD-burner and audio file conversion ZAP Media Tools is shareware, however very cheap, only $19 (it has also a movie player and much more) however there is compatibilty problems with VISTA, because they have changed so many things, especialy in the low level audio mixer API.

          And on jose Roca's forum I have started an open source project named BassBox that is specificaly designed to work with VISTA, but it should also work fine with XP.

          ...
          Patrice Terrier
          www.zapsolution.com
          www.objreader.com
          Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

          Comment

          Working...
          X