Here is the control version of BassVis now with drag & drop play.
GdS
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
Comment