diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d7f9baf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,26 @@ +project(visualization.milkdrop) + +cmake_minimum_required(VERSION 2.6) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) + +find_package(kodi REQUIRED) +find_package(DirectX REQUIRED) + +include_directories(${PROJECT_SOURCE_DIR}/lib + ${DIRECTX_INCLUDE_DIR} + ${KODI_INCLUDE_DIR}) + +set(MILKDROP_SOURCES src/MilkdropXBMC.cpp + src/XmlDocument.cpp) + +add_definitions(-DHAS_DX -D_CRT_SECURE_NO_WARNINGS) + +add_subdirectory(lib/vis_milkdrop) + +set(DEPLIBS evallib vis_milkdrop + ${DIRECTX_D3DX9_LIBRARY}) + +build_addon(visualization.milkdrop MILKDROP DEPLIBS) + +include(CPack) diff --git a/FindDirectX.cmake b/FindDirectX.cmake new file mode 100644 index 0000000..342e5f7 --- /dev/null +++ b/FindDirectX.cmake @@ -0,0 +1,39 @@ +# - Try to find DirectX SDK +# Once done this will define +# +# DIRECTX_FOUND - system has DirectX SDK +# DIRECTX_INCLUDE_DIR - the DirectX include directories +# DIRECTX_LIBRARIES - Link these to use DirectX SDK +# DIRECTX_D3D9_LIBRARY - Link this to use D3D9 +# DIRECTX_D3DX9_LIBRARY - Link this to use D3DX9 + +FIND_PATH(DIRECTX_INCLUDE_DIR d3d9.h PATHS + "$ENV{DXSDK_DIR}Include" + "$ENV{PROGRAMFILES}/Microsoft DirectX SDK*/Include" + "C:/apps_x86/Microsoft DirectX SDK*/Include" + "C:/apps/Microsoft DirectX SDK*/Include" + "C:/Program Files (x86)/Microsoft DirectX SDK*/Include" + "C:/Program Files/Microsoft DirectX SDK*/Include" + NO_DEFAULT_PATH +) +FIND_PATH(DIRECTX_INCLUDE_DIR d3d9.h) +GET_FILENAME_COMPONENT(DIRECTX_ROOT_DIR "${DIRECTX_INCLUDE_DIR}/.." ABSOLUTE) + +IF(CMAKE_CL_64) + SET(DIRECTX_LIBRARY_PATHS "${DIRECTX_ROOT_DIR}/Lib/x64") +ELSE() + SET(DIRECTX_LIBRARY_PATHS "${DIRECTX_ROOT_DIR}/Lib/x86" "${DIRECTX_ROOT_DIR}/Lib") +ENDIF() + +FIND_LIBRARY(DIRECTX_D3D9_LIBRARY d3d9 ${DIRECTX_LIBRARY_PATHS} NO_DEFAULT_PATH) +FIND_LIBRARY(DIRECTX_D3DX9_LIBRARY d3dx9 ${DIRECTX_LIBRARY_PATHS} NO_DEFAULT_PATH) +SET(DIRECTX_LIBRARIES ${DIRECTX_D3D9_LIBRARY} ${DIRECTX_D3DX9_LIBRARY}) + +# handle the QUIETLY and REQUIRED arguments and set DIRECTX_FOUND to TRUE if all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(DIRECTX DEFAULT_MSG DIRECTX_ROOT_DIR DIRECTX_LIBRARIES DIRECTX_INCLUDE_DIR) +MARK_AS_ADVANCED( + DIRECTX_INCLUDE_DIR + DIRECTX_D3D9_LIBRARY + DIRECTX_D3DX9_LIBRARY +) \ No newline at end of file diff --git a/lib/vis_milkdrop/CMakeLists.txt b/lib/vis_milkdrop/CMakeLists.txt new file mode 100644 index 0000000..c28d9f2 --- /dev/null +++ b/lib/vis_milkdrop/CMakeLists.txt @@ -0,0 +1,22 @@ +project(vis_milkdrop) + +enable_language(CXX) + +cmake_minimum_required(VERSION 2.6) + +include_directories(${PROJECT_SOURCE_DIR}) + +set(SOURCES dxcontext.cpp + fft.cpp + pluginshell.cpp + utility.cpp + milkdropfs.cpp + plugin.cpp + state.cpp + support.cpp) + +add_subdirectory(evallib) + +add_library(vis_milkdrop STATIC ${SOURCES}) + +target_link_libraries(vis_milkdrop evallib) diff --git a/lib/vis_milkdrop/LICENSE.TXT b/lib/vis_milkdrop/LICENSE.TXT new file mode 100644 index 0000000..ad0bbb0 --- /dev/null +++ b/lib/vis_milkdrop/LICENSE.TXT @@ -0,0 +1,24 @@ +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/vis_milkdrop/defines.h b/lib/vis_milkdrop/defines.h new file mode 100644 index 0000000..a1361e1 --- /dev/null +++ b/lib/vis_milkdrop/defines.h @@ -0,0 +1,207 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#ifndef __NULLSOFT_DX8_PLUGIN_SHELL_DEFINES_H__ +#define __NULLSOFT_DX8_PLUGIN_SHELL_DEFINES_H__ 1 + +// APPNAME should be something like "MyPlugin 1.0". +// This is the name that will appear in Winamp's list of installed plugins. +// Try to include the version number with the name. +// Note: to change the name of the *file* (DLL) that the plugin is +// compiled to, go to Project Settings -> Link tab -> and change the +// 'output file name'. Don't forget to do it for both Debug AND +// Release builds! +#define SHORTNAME "MilkDrop" // used as window caption. avoid numbers or punctuation; when 'integrate with winamp' option is enabled, these characters don't always work with all skins. +#define LONGNAME "MilkDrop 1.04b" // appears at bottom of config panel + +// INT_VERSION is the major version #, multipled by 100 (ie. version 1.02 +// would be 102). If the app goes to read in the INI file and sees that +// the INI file is from an older version of your plugin, it will ignore +// their old settings and reset them to the defaults for the new version; +// but that only works if you keep this value up-to-date. ***To disable this +// behavior, just always leave this at 100. *** +#define INT_VERSION 104 +// INT_SUBVERSION is the minor version #, counting up from 0 as you do +// mini-releases. If the plugin goes to read the old INI file and sees that +// the major version # is the same but the minor version # is not, it will, +// again, ignore their old settings and reset them to the defaults for the +// new version. ***To disable this behavior, just always leave this at 0. *** +#define INT_SUBVERSION 1 + +// INIFILE is the name of the .INI file that will save the user's +// config panel settings. Do not include a path; just give the filename. +// The actual file will be stored in the WINAMP\PLUGINS directory. +#define INIFILE "milkdrop_config.ini" + +// DOCFILE is the name of the documentation file that you'll write +// for your users. Do not include a path; just give the filename. +// When a user clicks the 'View Docs' button on the config panel, +// the plugin will try to display this file, located in the +// WINAMP\PLUGINS directory. +// +// ***Note that the button will be invisible (on the config panel) +// at runtime if this string is empty.*** +#define DOCFILE "milkdrop.html" // set this to something like "myplugin.html" + +// PLUGIN_WEB_URL is the web address of the homepage for your plugin. +// It should be a well-formed URL (http://...). When a user clicks +// the 'View Webpage' button on the config panel, the plugin will +// launch their default browser to display this page. +// +// ***Note that the button will be invisible (on the config panel) +// at runtime if this string is empty.*** +#define PLUGIN_WEB_URL "http://www.nullsoft.com/free/milkdrop/" // set this to something like "http://www.myplugin.com/" + +// The following two strings - AUTHOR_NAME and COPYRIGHT - will be used +// in a little box in the config panel, to identify the author & copyright +// holder of the plugin. Keep them short so they fit in the box. +#define AUTHOR_NAME "Ryan Geiss" +#define COPYRIGHT "(c) 2001-2003 Nullsoft, Inc." + +// CLASSNAME is the name of the window class that the plugin will +// use. You don't want this to overlap with any other plugins +// or applications that are running, so change this to something +// that will probably be unique. For example, if your plugin was +// called Libido, then "LibidoClass" would probably be a safe bet. +#define CLASSNAME "MilkDrop" + +// Here you can give names to the buttons (~tabs) along the top +// of the config panel. Each button, when clicked, will bring +// up the corresponding 'property page' (embedded dialog), +// IDD_PROPPAGE_1 through IDD_PROPPAGE_8. If you want less than +// 8 buttons to show up, just leave their names as blank. For +// full instructions on how to add a new tab/page, see +// DOCUMENTATION.TXT. +#define CONFIG_PANEL_BUTTON_1 "common settings" // nPage==1 +#define CONFIG_PANEL_BUTTON_2 "customizations" // nPage==2 +#define CONFIG_PANEL_BUTTON_3 "more options" // nPage==3 +#define CONFIG_PANEL_BUTTON_4 "transitions" // nPage==4 +#define CONFIG_PANEL_BUTTON_5 "" // nPage==5 +#define CONFIG_PANEL_BUTTON_6 "" // nPage==6 +#define CONFIG_PANEL_BUTTON_7 "" // nPage==7 +#define CONFIG_PANEL_BUTTON_8 "" // nPage==8 + +// adjust the defaults for the 4 built-in fonts here. +// (note: if you want the font to be available on 98 + ME + 2k + XP, use one of the following...) +// arial +// courier 10-12-15 +// courier new +// comic san[s] ms +// lucida console +// ms sans serif +// ms serif +// small fonts +// symbol 8-10-12-14-18-24 +// tahoma +// times new roman +// verdana +// webdings +#define SIMPLE_FONT_DEFAULT_FACE "Courier" //"MS Sans Serif" - changed to Courier because menus + code FAR more legible! +#define SIMPLE_FONT_DEFAULT_SIZE 12 //16 +#define SIMPLE_FONT_DEFAULT_BOLD 0 +#define SIMPLE_FONT_DEFAULT_ITAL 0 +#define SIMPLE_FONT_DEFAULT_AA 0 +#define DECORATIVE_FONT_DEFAULT_FACE "Times New Roman" +#define DECORATIVE_FONT_DEFAULT_SIZE 24 +#define DECORATIVE_FONT_DEFAULT_BOLD 0 +#define DECORATIVE_FONT_DEFAULT_ITAL 1 +#define DECORATIVE_FONT_DEFAULT_AA 1 +#define HELPSCREEN_FONT_DEFAULT_FACE "MS Sans Serif" +#define HELPSCREEN_FONT_DEFAULT_SIZE 14 // NOTE: should fit on 640x480 screen! +#define HELPSCREEN_FONT_DEFAULT_BOLD 1 +#define HELPSCREEN_FONT_DEFAULT_ITAL 0 +#define HELPSCREEN_FONT_DEFAULT_AA 0 +#define PLAYLIST_FONT_DEFAULT_FACE "Arial" +#define PLAYLIST_FONT_DEFAULT_SIZE 16 +#define PLAYLIST_FONT_DEFAULT_BOLD 0 +#define PLAYLIST_FONT_DEFAULT_ITAL 0 +#define PLAYLIST_FONT_DEFAULT_AA 0 + +// automatically add extra fonts to the config panel +// by simply #defining them here, UP TO A MAX OF 5 EXTRA FONTS. +// access the font by calling GetFont(EXTRA_1) for extra font #1, +// GetExtraFont(EXTRA_2) for extra font #2, and so on. +#define NUM_EXTRA_FONTS 2 // <- don't exceed 5 here! +#define TOOLTIP_FONT EXTRA_1 +#define EXTRA_FONT_1_NAME "Tooltips" +#define EXTRA_FONT_1_DEFAULT_FACE "Arial" +#define EXTRA_FONT_1_DEFAULT_SIZE 14 +#define EXTRA_FONT_1_DEFAULT_BOLD 0 +#define EXTRA_FONT_1_DEFAULT_ITAL 0 +#define EXTRA_FONT_1_DEFAULT_AA 0 +#define SONGTITLE_FONT EXTRA_2 +#define EXTRA_FONT_2_NAME "Animated Songtitles" +#define EXTRA_FONT_2_DEFAULT_FACE "Times New Roman" +#define EXTRA_FONT_2_DEFAULT_SIZE 22 +#define EXTRA_FONT_2_DEFAULT_BOLD 0 +#define EXTRA_FONT_2_DEFAULT_ITAL 1 +#define EXTRA_FONT_2_DEFAULT_AA 1 + +#define WINDOWCAPTION SHORTNAME // the caption that will appear on the plugin window +#define DLLDESC LONGNAME // the desc. of this DLL, as it appears in Winamp's list of viz plugins +#define MODULEDESC LONGNAME // the desc. of this viz module within the DLL (..this framework is set up for just 1 module per DLL) + +// Finally, a few parameters that will control how things are done +// inside the plugin shell: +#define NUM_WAVEFORM_SAMPLES 480 // RANGE: 32-576. This is the # of samples of waveform data that you want. + // Note that if it is less than 576, then VMS will do its best + // to line up the waveforms from frame to frame for you, using + // the extra samples as 'squish' space. + // Note: the more 'slush' samples you leave, the better the alignment + // will be. 512 samples gives you decent alignment; 400 samples + // leaves room for fantastic alignment. + // Observe that if you specify a value here (say 400) and then only + // render a sub-portion of that in some cases (say, 200 samples), + // make sure you render the *middle* 200 samples (#100-300), because + // the alignment happens *mostly at the center*. +#define NUM_FREQUENCIES 512 // # of freq. samples you want *out* of the FFT, for 0-11kHz range. + // ** this must be a power of 2! + // ** the actual FFT will use twice this many frequencies ** + +#define TEXT_MARGIN 10 // the # of pixels of margin to leave between text and the edge of the screen +#define PLAYLIST_INNER_MARGIN 4 // the extra margin between the playlist box and the text inside + +#define PLAYLIST_COLOR_PLAYING_TRACK 0xFFCCFF00 // alpha|red|green|blue +#define PLAYLIST_COLOR_HILITE_TRACK 0xFFFF5050 +#define PLAYLIST_COLOR_BOTH 0xFFFFCC22 +#define PLAYLIST_COLOR_NORMAL 0xFFCCCCCC + +#define MENU_COLOR 0xFFCCCCCC +#define MENU_HILITE_COLOR 0xFFFF4400 +#define DIR_COLOR 0xFF88CCFF +#define TOOLTIP_COLOR 0xFFBBBBCC + +#define MAX_PRESETS_PER_PAGE 32 + +#define PRESS_F1_MSG "Press F1 for Help " // leave extra space @ end, so italicized fonts don't get clipped +#define PRESS_F1_DUR 3.0f // in seconds +#define PRESS_F1_EXP 10.0f // exponent for how quickly it accelerates to leave the screen. 1 = linear; >1 = stays & then dashes off @ end + + +#endif \ No newline at end of file diff --git a/lib/vis_milkdrop/dxcontext.cpp b/lib/vis_milkdrop/dxcontext.cpp new file mode 100644 index 0000000..1cbe604 --- /dev/null +++ b/lib/vis_milkdrop/dxcontext.cpp @@ -0,0 +1,1451 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "DXContext.h" +#include "utility.h" +#include "shell_defines.h" +//#include "resource.h" +#include + +#define COMPILE_MULTIMON_STUBS 1 +//#include + +#define MY_EXT_WINDOW_STYLE (m_current_mode.m_skin ? 0 : ((m_current_mode.screenmode==DESKTOP) ? WS_EX_APPWINDOW : 0)) // note: changed from TOOLWINDOW to APPWINDOW b/c we wanted the plugin to appear in the taskbar. +#define MY_WINDOW_STYLE (m_current_mode.m_skin ? (WS_VISIBLE|WS_CHILDWINDOW|WS_OVERLAPPED|WS_CLIPCHILDREN|WS_CLIPSIBLINGS) : ((m_current_mode.screenmode==FAKE_FULLSCREEN || m_current_mode.screenmode==DESKTOP) ? WS_POPUP : WS_OVERLAPPEDWINDOW)) // note: WS_POPUP (by itself) removes all borders, captions, etc. + + + +//#include "vis.h" +//extern winampVisModule mod1; + +// note: the use of delayimp.lib, and the '/delayload' options below, +// will all ensure that the plugin DLL can still be loaded, even if +// DX8 is not installed. Without this delayed loading of the DX8 +// DLL's, **the plugin would not show up in the plug-ins list** on +// machines that do not have DX8 installed. Using delayed loading, +// we can at least let them try to configure or run the plugin, and +// then tell them that DX8 is missing. +//#pragma comment(lib,"delayimp.lib") +//#pragma comment(lib,"d3d8.lib") +//#pragma comment(linker,"/delayload:d3d8.dll") +//#ifdef _DEBUG +// #pragma comment(lib, "d3dx8d.lib") + //#pragma comment(linker,"/delayload:d3dx8d.dll") +//#else +// #pragma comment(lib, "d3dx8.lib") + //#pragma comment(linker,"/delayload:d3dx8.dll") +//#endif + +//DXContext::DXContext(HWND hWndWinamp,HINSTANCE hInstance,LPCSTR szClassName,LPCSTR szWindowCaption,WNDPROC pProc,LONG uWindowLong, int minimize_winamp, char* szIniFile) +DXContext::DXContext(LPDIRECT3DDEVICE9 device, char* szIniFile) +{ + m_szClassName[0] = 0; + m_szWindowCaption[0] = 0; + m_hwnd = NULL; + //m_lpD3D = NULL; + //HRESULT state = device->GetDirect3D(&m_lpD3D); + m_lpDevice = device; + m_hmod_d3d8 = NULL; + m_zFormat = D3DFMT_UNKNOWN; + for (int i=0; iCheckDeviceType(ordinal_adapter,D3DDEVTYPE_HAL,fmt,fmt,FALSE)) + return TRUE; + return FALSE; +#endif + return true; +} + +BOOL DXContext::TestDepth(int ordinal_adapter, D3DFORMAT fmt) +{ +#if 0 + if (D3D_OK!=m_lpD3D->CheckDeviceFormat(ordinal_adapter,D3DDEVTYPE_HAL,m_current_mode.display_mode.Format, + D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,fmt)) + return FALSE; + if (D3D_OK!=m_lpD3D->CheckDepthStencilMatch(ordinal_adapter,D3DDEVTYPE_HAL, + m_current_mode.display_mode.Format,m_current_mode.display_mode.Format,fmt)) + return FALSE; + return TRUE; +#endif + return true; +} + +int DXContext::CheckAndCorrectFullscreenDispMode(int ordinal_adapter, D3DDISPLAYMODE *pdm) +{ +#if 0 + // given the user's choice of fullscreen display mode, + // go through all the display modes available to the currently-selected adapter + // and find the best match. + + // returns 1 if it altered pdm to the best match, + // or 0 if it was able to find a perfect match. + + // if it returns 1, you might want to notify the user. + + + #define MAX_DISPLAY_MODES 4096 + D3DDISPLAYMODE list[MAX_DISPLAY_MODES]; + int nCount = min(m_lpD3D->GetAdapterModeCount(ordinal_adapter), MAX_DISPLAY_MODES); + int nValid = 0; + for (int i=0; iEnumAdapterModes(ordinal_adapter, i, &list[nValid]) == D3D_OK) + nValid++; + + // do many passes through the set until we find a match, + // each time relaxing more constraints. + // outline of the passes: + + int bpp_desired = 0; + switch(pdm->Format) + { +// case D3DFMT_R8G8B8 : bpp_desired = 32; break; + case D3DFMT_A8R8G8B8: bpp_desired = 32; break; + case D3DFMT_X8R8G8B8: bpp_desired = 32; break; + case D3DFMT_R5G6B5 : bpp_desired = 16; break; + case D3DFMT_X1R5G5B5: bpp_desired = 16; break; + case D3DFMT_A1R5G5B5: bpp_desired = 16; break; + case D3DFMT_A4R4G4B4: bpp_desired = 16; break; +// case D3DFMT_R3G3B2 : bpp_desired = 8; break; +// case D3DFMT_A8R3G3B2: bpp_desired = 16; break; +// case D3DFMT_X4R4G4B4: bpp_desired = 16; break; + } + + // rep MATCH: + // 0. w,h,r,f + // 1. w,h,-,f + // 2. w,h,r,- pass: + // 3. w,h,-,- -on pass 0, for 'f', match exact format + // 4. 8,6,r,f -on pass 1, for 'f', just match # of bits per pixel + // 5. 8,6,-,f (more relaxed match) + // 6. 8,6,r,- + // 7. 8,6,-,- + // 8. -,-,r,f + // 9. -,-,-,f + // 10. -,-,r,- + // 11. -,-,-,- + int found = 0; + for (int rep=0; rep<12 && !found; rep++) + { + for (int pass=0; pass<2 && !found; pass++) + { + for (i=0; iWidth != list[i].Width) + bMatch = false; + if (pdm->Height != list[i].Height) + bMatch = false; + } + else if (rep < 8) + { + if (DEFAULT_FULLSCREEN_WIDTH != list[i].Width) + bMatch = false; + if (DEFAULT_FULLSCREEN_HEIGHT != list[i].Height) + bMatch = false; + } + + if (((rep/2)%2)==0) + { + if (pass==0 && pdm->Format != list[i].Format) + bMatch = false; + else if (pass==1 && bpp_desired != bpp_this_mode) + bMatch = false; + } + + if (((rep%2)==0) && pdm->RefreshRate != list[i].RefreshRate) + { + bMatch = false; + } + + if (bMatch) + { + memcpy(pdm, &list[i], sizeof(D3DDISPLAYMODE)); + found = 1; + if (rep != 0 || pass != 0) + { + return 1; + /* + MessageBox(m_hwnd, + "The fullscreen display mode selected from the config panel\r" + "was invalid, for some reason. For now, the closest match\r" + "(to the old selection) will be used.\r" + "\r" + "To fix this, please return to the config panel and select a new\r" + "fullscreen display mode.\r" + "\r" + "The plugin will now run using the best match...\r" + ,"WARNING", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + */ + } + } + } + } + } +#endif + return 0; +} + +BOOL CALLBACK MyMonitorEnumProc( + HMONITOR hMonitor, // handle to display monitor + HDC hdcMonitor, // handle to monitor DC + LPRECT lprcMonitor, // monitor intersection rectangle + LPARAM dwData // data +) +{ +#if 0 + RECT* p = (RECT*)dwData; + if (hMonitor) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMonitor, &mi)) + { + p->top = min(p->top , mi.rcMonitor.top ); + p->left = min(p->left , mi.rcMonitor.left ); + p->right = max(p->right , mi.rcMonitor.right ); + p->bottom = max(p->bottom, mi.rcMonitor.bottom); + } + } +#endif + return TRUE; +} + + +int DXContext::GetWindowedModeAutoSize(int iteration) +{ +#if 0 + // note: requires 'm_monitor_rect' has been set! + + // generically determine size of window, for windowed mode: + int x = m_monitor_rect.right-m_monitor_rect.left; + int y = m_monitor_rect.bottom-m_monitor_rect.top; + + // if running in horz/vert-span multi-display mode, base the window size on + // an actual display size, not the giant double-sized monitor. Also, position + // the window on the same monitor that Winamp is on. + if (x >= y*2) + { + x /= 2; + + // move window to same display that Winamp is on: + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + if (GetWindowPlacement(m_hwnd_winamp, &wp)) + { + int winamp_center_x = (wp.rcNormalPosition.right + wp.rcNormalPosition.left)/2; + if (winamp_center_x > x) + { + m_monitor_rect.left += x; + m_monitor_rect.right += x; + } + } + } + else if (y > x*4/3) + { + y /= 2; + + // move window to same display that Winamp is on: + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + if (GetWindowPlacement(m_hwnd_winamp, &wp)) + { + int winamp_center_y = (wp.rcNormalPosition.top + wp.rcNormalPosition.bottom)/2; + if (winamp_center_y > y) + { + m_monitor_rect.top += y; + m_monitor_rect.bottom += y; + } + } + } + + int size = min(x, y); + size = (int)(size*DEFAULT_WINDOW_SIZE); + size = (size/64 - iteration)*64; + if (size < 64) + size = 64; + + return size; +#endif + return 0; +} + +void DXContext::WriteSafeWindowPos() +{ +#if 0 + if (m_current_mode.screenmode == WINDOWED) + { + WritePrivateProfileInt(64, "nMainWndTop", m_szIniFile, "settings"); + WritePrivateProfileInt(64, "nMainWndLeft", m_szIniFile, "settings"); + WritePrivateProfileInt(64+256, "nMainWndRight", m_szIniFile, "settings"); + WritePrivateProfileInt(64+256, "nMainWndBottom", m_szIniFile, "settings"); + WritePrivateProfileInt(64, "avs_wx",m_szIniFile,"settings"); + WritePrivateProfileInt(64, "avs_wy",m_szIniFile,"settings"); + WritePrivateProfileInt( 256, "avs_ww",m_szIniFile,"settings"); + WritePrivateProfileInt( 256, "avs_wh",m_szIniFile,"settings"); + } +#endif +} + +BOOL DXContext::Internal_Init(DXCONTEXT_PARAMS *pParams, BOOL bFirstInit) +{ + memcpy(&m_current_mode, pParams, sizeof(DXCONTEXT_PARAMS)); + memset(&myWindowState,0,sizeof(myWindowState)); + + // various checks + if (m_current_mode.screenmode != WINDOWED) + m_current_mode.m_skin = 0; + + // 1. destroy old window + if (m_hwnd) + { + m_ignore_wm_destroy = 1; +// DestroyWindow(m_hwnd); + m_ignore_wm_destroy = 0; + m_hwnd = NULL; + } + + // 2. CHECK TO MAKE SURE DIRECTX/DDRAW IS INSTALLED +/* + if (bFirstInit) + { + // Test for DirectX 8 + start it + // note: if you don't call LoadLibrary here, and you're on a system + // where DX8 is missing, Direct3DCreate8() might crash; so call it. + int d3d8_already_loaded = (GetModuleHandle("d3d8.dll") != NULL) ? 1 : 0; + if (!d3d8_already_loaded) + m_hmod_d3d8 = LoadLibrary("d3d8.dll"); + + if ( (!d3d8_already_loaded && !m_hmod_d3d8) || + !(m_lpD3D = Direct3DCreate8(D3D_SDK_VERSION)) + ) + { + MissingDirectX(NULL); + m_lastErr = DXC_ERR_CREATE3D; + return FALSE; + } + }*/ + + + // 3. get the smallest single rectangle that encloses ALL the monitors on the desktop: + // SetRect(&m_all_monitors_rect, 0, 0, 0, 0); + // EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (LPARAM)&m_all_monitors_rect); + + // 4. some DirectX- / DDraw-specific stuff. Also determine hPluginMonitor. + + m_lpDevice->GetDeviceCaps(&m_caps); + +#if 0 + HMONITOR hPluginMonitor = NULL; + { + D3DADAPTER_IDENTIFIER8 temp; + + // find the ordinal # of the adapter whose GUID matches what the user picked from the config panel. + // if no match found, use D3DADAPTER_DEFAULT. + m_ordinal_adapter = D3DADAPTER_DEFAULT; + int nAdapters = m_lpD3D->GetAdapterCount(); + { + for (int i=0; iGetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &temp) == D3D_OK) && + (memcmp(&temp.DeviceIdentifier, &m_current_mode.adapter_guid, sizeof(GUID))==0)) + { + m_ordinal_adapter = i; + break; + } + } + } + + if (m_lpD3D->GetAdapterIdentifier(m_ordinal_adapter, D3DENUM_NO_WHQL_LEVEL, &temp) == D3D_OK) + { + strcpy(m_szDriver, temp.Driver); + strcpy(m_szDesc, temp.Description); + } + + int caps_ok = 0; + int caps_tries = 0; + int changed_fs_disp_mode; + + // try to get the device caps for the adapter selected from the config panel. + // if GetDeviceCaps() fails, it's probably because the adapter has been + // removed from the system (or disabled), so we try again with other adapter(s). + do + { + changed_fs_disp_mode = 0; + + SetRect(&m_monitor_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + + // get bounding rect of the monitor attached to the adapter (to assist w/window positioning) + // note: in vert/horz span setups (psuedo-multimon), + // this will be 2048x768 or 1024x1536 or something like that. + hPluginMonitor = m_lpD3D->GetAdapterMonitor(m_ordinal_adapter); + /*if (hPluginMonitor) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hPluginMonitor, &mi)) + { + memcpy(&m_monitor_rect, &mi.rcMonitor, sizeof(RECT)); + memcpy(&m_monitor_work_rect, &mi.rcWork, sizeof(RECT)); + } + }*/ + + if (bFirstInit) + { + for (int i=0; iGetAdapterDisplayMode( i, &d3ddm ) ) ) + { + d3ddm.Format = D3DFMT_UNKNOWN; + //m_lastErr = DXC_ERR_GETFORMAT; + //MessageBox(m_hwnd, "DirectX initialization failed (GetAdapterDisplayMode)", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + //return FALSE; + } + m_orig_windowed_mode_format[i] = d3ddm.Format; + } + } + + // figure out pixel (color) format for back buffer: (m_current_mode.display_mode.Format) + if (m_current_mode.screenmode!=FULLSCREEN && m_ordinal_adapter < MAX_DXC_ADAPTERS) + m_current_mode.display_mode.Format = m_orig_windowed_mode_format[m_ordinal_adapter]; + // else + // for fullscreen, use what they gave us + + if (m_current_mode.display_mode.Format == D3DFMT_UNKNOWN || + !TestFormat(m_ordinal_adapter, m_current_mode.display_mode.Format)) + { + // if they try to run the plugin without ever running the config panel + // first (& pressing OK), then the fullscreen pixelformat hasn't been + // chosen... so we try all the possilibities until one works: + if (TestFormat(m_ordinal_adapter,D3DFMT_A8R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_A8R8G8B8; + else if (TestFormat(m_ordinal_adapter,D3DFMT_X8R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_X8R8G8B8; + else if (TestFormat(m_ordinal_adapter,D3DFMT_R8G8B8 )) m_current_mode.display_mode.Format = D3DFMT_R8G8B8 ; + else if (TestFormat(m_ordinal_adapter,D3DFMT_R5G6B5 )) m_current_mode.display_mode.Format = D3DFMT_R5G6B5 ; + else if (TestFormat(m_ordinal_adapter,D3DFMT_X1R5G5B5)) m_current_mode.display_mode.Format = D3DFMT_X1R5G5B5; + else if (TestFormat(m_ordinal_adapter,D3DFMT_A1R5G5B5)) m_current_mode.display_mode.Format = D3DFMT_A1R5G5B5; + else if (TestFormat(m_ordinal_adapter,D3DFMT_A4R4G4B4)) m_current_mode.display_mode.Format = D3DFMT_A4R4G4B4; + else if (TestFormat(m_ordinal_adapter,D3DFMT_X4R4G4B4)) m_current_mode.display_mode.Format = D3DFMT_X4R4G4B4; + } + + if (m_current_mode.display_mode.Format==D3DFMT_UNKNOWN) + { + m_lastErr = DXC_ERR_FORMAT; + MessageBox(m_hwnd, "DirectX initialization failed; unknown color format", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return FALSE; + } + + if (m_current_mode.screenmode == FULLSCREEN) + changed_fs_disp_mode = CheckAndCorrectFullscreenDispMode(m_ordinal_adapter, &m_current_mode.display_mode); + + // figure out pixel format of the z-buffer: (m_zFormat) + m_zFormat = D3DFMT_UNKNOWN; + if (TestDepth(m_ordinal_adapter,D3DFMT_D32 )) m_zFormat=D3DFMT_D32; + else if (TestDepth(m_ordinal_adapter,D3DFMT_D24S8 )) m_zFormat=D3DFMT_D24S8; + else if (TestDepth(m_ordinal_adapter,D3DFMT_D24X4S4 )) m_zFormat=D3DFMT_D24X4S4; + else if (TestDepth(m_ordinal_adapter,D3DFMT_D24X8 )) m_zFormat=D3DFMT_D24X8; + else if (TestDepth(m_ordinal_adapter,D3DFMT_D16 )) m_zFormat=D3DFMT_D16; + else if (TestDepth(m_ordinal_adapter,D3DFMT_D15S1 )) m_zFormat=D3DFMT_D15S1; + else if (TestDepth(m_ordinal_adapter,D3DFMT_D16_LOCKABLE)) m_zFormat=D3DFMT_D16_LOCKABLE; + + // get device caps: + memset(&m_caps, 0, sizeof(m_caps)); + if (FAILED(m_lpD3D->GetDeviceCaps(m_ordinal_adapter, D3DDEVTYPE_HAL, &m_caps))) + { + // that adapter was found in the system, but it might be disabled + // (i.e. 'extend my Windows desktop onto this monitor') is unchecked) + // so, try other adapters (try all sequentially). + + if (caps_tries < nAdapters) + { + // try again, this time using the default adapter: + m_ordinal_adapter = caps_tries; + caps_tries++; + } + else + { + m_lastErr = DXC_ERR_CAPSFAIL; + MessageBox(m_hwnd, + "DirectX initialization failed (GetDeviceCaps).\r" + "\r" + "This means that no valid 3D-accelerated display adapter could be found\r" + "on your computer." + "\r" + "If you know this is not the case, it is possible that your graphics\r" + "subsystem is temporarily unstable; please try rebooting your computer,\r" + "and then try to run the plugin again. Otherwise, please install a\r" + "3D-accelerated display adapter." + ,"ERROR",MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return FALSE; + } + } + else + { + caps_ok = 1; + } + } + while (!caps_ok); + + if (changed_fs_disp_mode) + { + MessageBox(m_hwnd, + "The fullscreen display mode selected from the config panel\r" + "was invalid, for some reason. For now, the closest match\r" + "(to the old selection) will be used.\r" + "\r" + "To fix this, please return to the config panel and select a new\r" + "fullscreen display mode.\r" + "\r" + "The plugin will now run using the best match...\r" + ,"WARNING", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + } + + switch(m_current_mode.display_mode.Format) + { + case D3DFMT_R8G8B8 : m_bpp = 32; break; + case D3DFMT_A8R8G8B8: m_bpp = 32; break; + case D3DFMT_X8R8G8B8: m_bpp = 32; break; + case D3DFMT_R5G6B5 : m_bpp = 16; break; + case D3DFMT_X1R5G5B5: m_bpp = 16; break; + case D3DFMT_A1R5G5B5: m_bpp = 16; break; + case D3DFMT_A8R3G3B2: m_bpp = 16; break; + case D3DFMT_A4R4G4B4: m_bpp = 16; break; + case D3DFMT_X4R4G4B4: m_bpp = 16; break; + case D3DFMT_R3G3B2 : m_bpp = 8; break; // misleading? implies a palette... + } + } +#endif + m_bpp = 32; + + // 5. set m_monitor_rect and m_monitor_work_rect. +/* if (hPluginMonitor) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hPluginMonitor, &mi)) + { + m_monitor_rect = mi.rcMonitor; + m_monitor_rect_orig = mi.rcMonitor; + m_monitor_work_rect = mi.rcWork; + m_monitor_work_rect_orig = mi.rcWork; + } + } +*/ + + // 6. embedded window stuff [where the plugin window is integrated w/winamp] +#if 0 + if (m_current_mode.m_skin) + { + // set up the window's position on screen + // note that we'd prefer to set the CLIENT size we want, but we can't, so we'll just do + // this here, and later, adjust the client rect size to what's left... + int size = GetWindowedModeAutoSize(0); // note: requires 'm_monitor_rect' has been set! + myWindowState.r.left = InternalGetPrivateProfileInt("settings","avs_wx",64,m_szIniFile); + myWindowState.r.top = InternalGetPrivateProfileInt("settings","avs_wy",64,m_szIniFile); + myWindowState.r.right = myWindowState.r.left + InternalGetPrivateProfileInt("settings","avs_ww",size+24,m_szIniFile); + myWindowState.r.bottom = myWindowState.r.top + InternalGetPrivateProfileInt("settings","avs_wh",size+40,m_szIniFile); + + // only works on winamp 2.90+! + int success = 0; + if (SendMessage(mod1.hwndParent,WM_WA_IPC,0,0) >= 0x2900) + { + myWindowState.flags |= EMBED_FLAGS_NOTRANSPARENCY; + HWND (*e)(embedWindowState *v); + *(void**)&e = (void *)SendMessage(mod1.hwndParent,WM_WA_IPC,(LPARAM)0,IPC_GET_EMBEDIF); + if (e) + { + m_current_mode.parent_window = e(&myWindowState); + if (m_current_mode.parent_window) + { + SetWindowText(m_current_mode.parent_window,m_szWindowCaption); + success = 1; + } + } + } + + if (!success) + m_current_mode.m_skin = 0; + } +#endif + // remember the client rect that was originally desired... +// RECT windowed_mode_desired_client_rect; +// windowed_mode_desired_client_rect.top = InternalGetPrivateProfileInt("settings","nMainWndTop",-1,m_szIniFile); +// windowed_mode_desired_client_rect.left = InternalGetPrivateProfileInt("settings","nMainWndLeft",-1,m_szIniFile); +// windowed_mode_desired_client_rect.right = InternalGetPrivateProfileInt("settings","nMainWndRight",-1,m_szIniFile); +// windowed_mode_desired_client_rect.bottom = InternalGetPrivateProfileInt("settings","nMainWndBottom",-1,m_szIniFile); + + // ...and in case windowed mode init fails severely, + // set it up to try next time for a simple 256x256 window. + // WriteSafeWindowPos(); + + // 7. create the window, if not already created +#if 0 + if (!m_hwnd) + { + m_hwnd = CreateWindowEx( + MY_EXT_WINDOW_STYLE, // extended style + m_szClassName, // class + m_szWindowCaption, // caption + MY_WINDOW_STYLE, // style + 0, // left + 0, // top + 256, // temporary width + 256, // temporary height + m_current_mode.parent_window, // parent window + NULL, // menu + m_hInstance, // instance + NULL + ); // parms + + if (!m_hwnd) + { + m_lastErr = DXC_ERR_CREATEWIN; + MessageBox(m_hwnd, "CreateWindow failed", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return FALSE; + } + + SetWindowLong(m_hwnd, GWL_USERDATA, m_uWindowLong); + + SendMessage(m_hwnd_winamp, WM_WA_IPC, (int)m_hwnd, IPC_SETVISWND); + + if (m_current_mode.m_skin) + ShowWindow(m_current_mode.parent_window,SW_SHOWNA); // showing the parent wnd will make it size the child, too + } +#endif + // 8. minimize winamp before creating devices & such, so there aren't + // any confusing window-focus issues +// MinimizeWinamp(hPluginMonitor); + + // 9. loop to try and create the window. + // if in windowed mode and not enough vidmem, it will try again w/smaller window + // (repeatedly, until window client size would be < 64) +#if 0 + int iteration = 0; + int device_ok = 0; + do + { + // set the window position + if (m_current_mode.screenmode==DESKTOP || + m_current_mode.screenmode==FAKE_FULLSCREEN) + { + int x = m_monitor_rect.right - m_monitor_rect.left; + int y = m_monitor_rect.bottom - m_monitor_rect.top; + + if (x >= y*2) + { + // (pseudo-multimon modes like 2048x768) + int mid = (m_monitor_rect.left + m_monitor_rect.right)/2; + if (m_current_mode.m_dualhead_horz==1) // show on left side + m_monitor_rect.right = mid; + else if (m_current_mode.m_dualhead_horz==2) // show on right side + m_monitor_rect.left = mid; + } + else if (y > x*4/3) + { + // (pseudo-multimon modes like 1024x1536) + int mid = (m_monitor_rect.top + m_monitor_rect.bottom)/2; + if (m_current_mode.m_dualhead_vert==1) // show on top half + m_monitor_rect.bottom = mid; + else if (m_current_mode.m_dualhead_vert==2) // show on bottom half + m_monitor_rect.top = mid; + } + + // recompute width & height (into x,y): + x = m_monitor_rect.right - m_monitor_rect.left; + y = m_monitor_rect.bottom - m_monitor_rect.top; + + m_client_width = x; + m_client_height = y; + m_window_width = x; + m_window_height = y; + + if (m_current_mode.screenmode == DESKTOP) + { + // note: we initially hide the window, and then + // only display it once the desktop is all nice & ready. + // see CPluginShell::DrawAndDisplay(). + SetWindowPos(m_hwnd,HWND_BOTTOM,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_HIDEWINDOW); + } + else // FAKE_FULLSCREEN + { + if (memcmp(&m_all_monitors_rect, &m_monitor_rect, sizeof(RECT))==0) + { + // there's only one display, and it's entirely covered + // by the plugin -> PUT THE PLUGIN ABOVE THE TASKBAR + // -> normally, if the user clicked another window, + // it would pop the taskbar to the top; but we don't + // have to worry about that here, since we're taking + // up the whole screen. + // -> don't worry about making the text, etc. avoid + // the taskbar in this case (see DrawAndDisplay()) + // -> DO worry about hiding the mouse cursor in this case + // (see WM_SETCURSOR handler) + + m_fake_fs_covers_all = 1; + //SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW); + } + else + { + // there is space to work outside of the plugin window. + // -> here we pretty much have to let the taskbar stay on + // top, because it really likes to be there; i.e., + // if you click any other window, it automatically + // pops up again. + // -> therefore, TRY TO KEEP THE WINDOW ON BOTTOM + // (below the taskbar). (see PushWindowToBack) + // -> don't worry about hiding the mouse cursor in this case + // (see WM_SETCURSOR handler) + // -> DO worry about making the text, etc. avoid + // the taskbar in this case (see DrawAndDisplay()) + + // (note that if taskbar is in the way, they can move it, + // since there are other monitors available) + + m_fake_fs_covers_all = 0; + //SetWindowPos(m_hwnd,HWND_TOP,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW); + } + + SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW); + } + } + else if (m_current_mode.screenmode == FULLSCREEN) + { + int x = m_current_mode.display_mode.Width ; + int y = m_current_mode.display_mode.Height; + int cx = m_monitor_rect.right - m_monitor_rect.left; + int cy = m_monitor_rect.bottom - m_monitor_rect.top; + + // test #1 + if (x >= y*2 || y > x*4/3) // tackle problem of vert/horz spans + { + int ret = MessageBox(m_hwnd, + "You are trying to enter fullscreen mode while running\r" + "multiple displays in a vertical or horizontal span,\r" + "without using 'Fake Fullscreen Mode'. As a result,\r" + "--the image will be stretched over both displays.--\r" + "\r" + "If you would prefer the plugin to appear on only one display\r" + "(and still be free to operate on the other display),\r" + "please return to the config panel, enable 'Fake Fullscreen\r" + "Mode', click the 'DualHead' button to configure your DualHead\r" + "setup, and then try again.\r" + "\r" + "Hit OK to proceed, or Cancel to exit now." + ,"Tip", MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST); + if (ret==IDCANCEL) + { + m_lastErr = DXC_ERR_USER_CANCELED; + return FALSE; + } + } + + // test #2 + if ((cx >= cy*2 && x < y*2) || (cy > cx*4/3 && y <= x*4/3)) + { + int ret = MessageBox(m_hwnd, + "You are trying to enter fullscreen mode while running\r" + "multiple displays in a vertical or horizontal span,\r" + "but the display mode you are entering does not stretch\r" + "over both displays. As a result, --the image will only\r" + "appear on one display, and the other display will be disabled.--\r" + "\r" + "There are two alternatives:\r" + "\r" + "1. To make the fullscreen image appear on only ONE display\r" + "AND still be free to operate on the other display,\r" + "please return to the config panel and enable 'Fake Fullscreen Mode',\r" + "then click 'DualHead' to select which screen you'd like the\r" + "plugin to occupy. (--RECOMMENDED--)\r" + "\r" + "2. To make the fullscreen image stretch across BOTH displays,\r" + "return to the config panel and select a display mode that\r" + "spans both displays (such as 2048 x 768, or 1024 x 1536).\r" + "\r" + "Hit OK to continue, or Cancel to exit now." + + ,"Tip", MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST); + if (ret==IDCANCEL) + { + m_lastErr = DXC_ERR_USER_CANCELED; + return FALSE; + } + } + + m_client_width = x; + m_client_height = y; + m_window_width = x; + m_window_height = y; + SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW); + } + else // WINDOWED + { + RECT margin; + if (m_current_mode.m_skin) + { + RECT r1, r2; + GetWindowRect(GetParent(m_hwnd), &r1); + GetWindowRect( m_hwnd , &r2); + margin.left = r2.left - r1.left; + margin.right = r1.right - r2.right; + margin.top = r2.top - r1.top; + margin.bottom= r1.bottom - r2.bottom; + } + else + { + RECT r1; + SetRect(&r1, 0, 0, 256, 256); + AdjustWindowRect(&r1, MY_WINDOW_STYLE, 0); + margin.left = 0 - r1.left; + margin.right = r1.right - 256; + margin.top = 0 - r1.top; + margin.bottom= r1.bottom - 256; + } + + int autosize = 1; + + RECT r = windowed_mode_desired_client_rect; + if (iteration==0 && r.top != -1 && r.left != -1 && r.bottom != -1 && r.right != -1) + { + // use prev. window coordinates: + m_client_width = r.right - r.left; + m_client_height = r.bottom - r.top; + if (m_current_mode.m_skin) // check this here in case they got a non-aligned size by resizing when "integrated with winamp" was unchecked, then checked it & ran the plugin... + { + // STRANGE ALIGNMENTS FOR THE WINDOW FRAME: (required by winamp 2): + // the window frame's width must be divisible by 25, and height by 29. + if (SendMessage(mod1.hwndParent,WM_WA_IPC,0,0) < 0x4000) // ... winamp 5 doesn't have this prob. (test vs. 0x4000 because winamp5 betas have version tags like 0x4987) + { + m_client_width = ((m_client_width + margin.left + margin.right)/25)*25 - margin.left - margin.right; + m_client_height = ((m_client_height + margin.top + margin.bottom)/29)*29 - margin.top - margin.bottom; + } + } + + // transform screen-space CLIENT rect into screen-space WINDOW rect + r.top = windowed_mode_desired_client_rect.top - margin.top; + r.left = windowed_mode_desired_client_rect.left - margin.left; + r.right = r.left + margin.left + m_client_width + margin.right; + r.bottom = r.top + margin.top + m_client_height + margin.bottom; + + // make sure the window is entirely visible on the selected monitor; + // otherwise, autosize/place it. + // (note that this test is only appled 1) at startup, and 2) after a resize/max/restore. + // this test is not applied when merely moving the window.) + if (r.top >= m_monitor_work_rect.top && + r.left >= m_monitor_work_rect.left && + r.right <= m_monitor_work_rect.right && + r.bottom <= m_monitor_work_rect.bottom) + { + if (m_current_mode.m_skin) + { + m_window_width = m_client_width ; // m_window_width/height are for OUR borderless window, not the embedwnd parent frame. + m_window_height = m_client_height; + SetWindowPos(GetParent(m_hwnd),HWND_NOTOPMOST, r.left, r.top, r.right-r.left, r.bottom-r.top, SWP_SHOWWINDOW); + SetWindowPos( m_hwnd ,HWND_NOTOPMOST, windowed_mode_desired_client_rect.left, windowed_mode_desired_client_rect.top, m_client_width, m_client_height, SWP_SHOWWINDOW); + } + else + { + m_window_width = r.right - r.left; + m_window_height = r.bottom - r.top; + SetWindowPos(m_hwnd,HWND_NOTOPMOST,r.left,r.top,m_window_width,m_window_height,SWP_SHOWWINDOW); + } + + autosize = 0; + } + } + + if (autosize) + { + int size = GetWindowedModeAutoSize(iteration); // note: requires 'm_monitor_rect' has been set! + + m_client_width = size; + m_client_height = size; + + if (m_current_mode.m_skin) + { + // STRANGE ALIGNMENTS FOR THE WINDOW FRAME: (required by winamp 2): + // the window frame's width must be divisible by 25, and height by 29. + if (SendMessage(mod1.hwndParent,WM_WA_IPC,0,0) < 0x4000) // ... winamp 5 doesn't have this prob. (test vs. 0x4000 because winamp5 betas have version tags like 0x4987) + { + m_client_width = ((m_client_width + margin.left + margin.right)/25)*25 - margin.left - margin.right; + m_client_height = ((m_client_height + margin.top + margin.bottom)/29)*29 - margin.top - margin.bottom; + } + + m_window_width = m_client_width ; // m_window_width/height are for OUR [borderless] window, not the parent window (which is the embedwnd frame). + m_window_height = m_client_height; + SetWindowPos(GetParent(m_hwnd),HWND_NOTOPMOST, m_monitor_work_rect.left+32, m_monitor_work_rect.top+32, m_client_width + margin.left + margin.right, m_client_height + margin.top + margin.bottom, SWP_SHOWWINDOW); + SetWindowPos( m_hwnd ,HWND_NOTOPMOST, m_monitor_work_rect.left+32 + margin.left, m_monitor_work_rect.top+32 + margin.top, m_client_width, m_client_height, SWP_SHOWWINDOW); + } + else + { + SetRect(&r, 0, 0, size, size); + AdjustWindowRect(&r, MY_WINDOW_STYLE, 0); + + m_window_width = r.right - r.left; + m_window_height = r.bottom - r.top; + + SetWindowPos(m_hwnd,HWND_NOTOPMOST, m_monitor_work_rect.left+32, m_monitor_work_rect.top+32, m_window_width, m_window_height, SWP_SHOWWINDOW); + } + } + } + m_frame_delay = 1; // set this to 2 if you use triple buffering! + + { + m_current_mode.display_mode.Width = m_client_width; + m_current_mode.display_mode.Height = m_client_height; + + // set up m_d3dpp (presentation parameters): + ZeroMemory(&m_d3dpp,sizeof(m_d3dpp)); + m_d3dpp.Windowed = (m_current_mode.screenmode==FULLSCREEN) ? 0 : 1; + m_d3dpp.BackBufferFormat = m_current_mode.display_mode.Format; + m_d3dpp.BackBufferWidth = m_client_width; + m_d3dpp.BackBufferHeight = m_client_height; + m_d3dpp.BackBufferCount = m_current_mode.nbackbuf; + if (m_current_mode.screenmode==FULLSCREEN) + m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//D3DSWAPEFFECT_FLIP; + else // windowed or fake FS + m_d3dpp.SwapEffect = (m_current_mode.allow_page_tearing) ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_COPY_VSYNC;//D3DSWAPEFFECT_DISCARD;//D3DSWAPEFFECT_FLIP; + // note: multisampling is only allowed if swapeffect is DISCARD! + m_d3dpp.MultiSampleType = (m_d3dpp.SwapEffect==D3DSWAPEFFECT_DISCARD) ? m_current_mode.multisamp : D3DMULTISAMPLE_NONE; + //m_d3dpp.hDeviceWindow = m_hwnd; + if (m_current_mode.screenmode==FULLSCREEN) + { + m_d3dpp.FullScreen_RefreshRateInHz = m_current_mode.display_mode.RefreshRate;//D3DPRESENT_RATE_DEFAULT; + m_d3dpp.FullScreen_PresentationInterval = m_current_mode.allow_page_tearing ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;//D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE; + } + if (m_zFormat != D3DFMT_UNKNOWN) + { + m_d3dpp.EnableAutoDepthStencil=TRUE; + m_d3dpp.AutoDepthStencilFormat=m_zFormat; + } + + // finally, create the device: + HRESULT hRes; + if(FAILED(hRes = m_lpD3D->CreateDevice( + m_ordinal_adapter, + D3DDEVTYPE_HAL, + m_hwnd, + (m_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, + &m_d3dpp, + &m_lpDevice ) ) ) + { + int code = LOWORD(hRes); + + char str[1024]; + if (code==2156) //D3DERR_NOTAVAILABLE + { + m_lastErr = DXC_ERR_CREATEDEV_NOT_AVAIL; + + char str[2048]; + sprintf(str, + "Unable to create a DirectX device. (D3DERR_NOTAVAILABLE)\r" + "\r" + "This could mean that you've chosen a combination of settings that is\r" + "not available on your video card. Try resetting the plugin to its\r" + "default settings (via the config panel's 'Default' button), and then\r" + "try running the plugin again.\r" + "\r" + "You might also want to close all other applications, to make sure they're\r" + "not interfering.\r" + "\r" + "If you have made any changes to your graphics subsystem since your\r" + "last reboot (such as updating video drivers, installing new software,\r" + "etc.), or have witnessed any strange behaviors, TRY REBOOTING first.\r" + "\r" + ); + if (m_current_mode.screenmode == FULLSCREEN) + strcat(str, + "NOTE: If you are trying to run the plugin on an older display adapter\r" + "(such as a Voodoo3 card), try going to the config panel (ALT+K)\r" + "and selecting a fullscreen display mode of a different color depth;\r" + "some of these older cards can only do 3D in particular color depths\r" + "(such as 16-bit color, for the Voodoo 3).\r" + ); + else + strcat(str, + "NOTE: If you are trying to run the plugin on an older display adapter\r" + "(such as a Voodoo3 card), try changing the color depth that Windows\r" + "is running in; some of these cards can only do 3D in particular color depths\r" + "(such as 16-bit color, for the Voodoo3).\r" + ); + + MessageBox(m_hwnd,str,"ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return FALSE; + } + else if (m_current_mode.screenmode==WINDOWED && m_client_width>64) + { + // DO NOTHING; try again w/smaller window + + } + else if (m_current_mode.screenmode != WINDOWED || m_client_width <= 64) + { + // usually, code==2154 here, which is D3DERR_OUTOFVIDEOMEMORY + m_lastErr = DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY; + sprintf(str, + "DirectX initialization failed (CreateDevice; code %d)\r" + "\r" + "Often this means you don't have enough free video memory.\r" + ,LOWORD(hRes)); + + // NOTE: *A 'SUGGESTION' SCREEN SHOULD APPEAR NEXT, PROVIDED BY THE CALLER* + + MessageBox(m_hwnd, str, "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return FALSE; + } + } + else + { + device_ok = 1; + } + } + + iteration++; + } + while (!device_ok); +#endif +m_bpp = 32; +m_client_width = 640; +m_client_height = 480; +m_window_width = 640; +m_window_height = 480; + // set initial viewport +// SetViewport(); + + // for desktop mode, push window to back again: +// if (m_current_mode.screenmode==DESKTOP) +// SetWindowPos(m_hwnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); +// +// if (m_current_mode.m_skin) +// { +// SetFocus(m_current_mode.parent_window); +// //SetActiveWindow(m_current_mode.parent_window); +// //SetForegroundWindow(m_current_mode.parent_window); +// } + +// if (m_current_mode.screenmode == WINDOWED) +// SaveWindow(); + + // return success + m_ready = TRUE; + return TRUE; +} + +BOOL DXContext::StartOrRestartDevice(DXCONTEXT_PARAMS *pParams) +{ +#if 0 + // call this to [re]initialize the DirectX environment with new parameters. + // examples: startup; toggle windowed/fullscreen mode; change fullscreen resolution; + // and so on. + // be sure to clean up all your DirectX stuff first (textures, vertex buffers, + // D3DX allocations, etc.) and reallocate it afterwards! + + // note: for windowed mode, 'pParams->disp_mode' (w/h/r/f) is ignored. + + // destroy old window + if (m_hwnd) + { + SendMessage(m_hwnd_winamp, WM_WA_IPC, NULL, IPC_SETVISWND); + m_ignore_wm_destroy = 1; + DestroyWindow(m_hwnd); + m_ignore_wm_destroy = 0; + m_hwnd = NULL; + } + + if (myWindowState.me) + { + SetForegroundWindow(mod1.hwndParent); + DestroyWindow(myWindowState.me); + myWindowState.me = NULL; + } +#endif + if (!m_ready) + { + // first-time init: create a fresh new device + return Internal_Init(pParams, TRUE); + } + else + { + // re-init: preserve the DX8 object (m_lpD3D), + // but destroy and re-create the DX8 device (m_lpDevice). + m_ready = FALSE; + +// SafeRelease(m_lpDevice); + // but leave the D3D object! + + // RestoreWinamp(); + return Internal_Init(pParams, FALSE); + } +} + +BOOL DXContext::OnUserResizeWindow(RECT *new_window_rect, RECT *new_client_rect) +{ +#if 0 + // call this function on WM_EXITSIZEMOVE when running windowed. + // don't bother calling this when fullscreen. + // be sure to clean up all your DirectX stuff first (textures, vertex buffers, + // D3DX allocations, etc.) and reallocate it afterwards! + + if (!m_ready || (m_current_mode.screenmode != WINDOWED)) + return FALSE; + + if ((m_client_width == new_client_rect->right - new_client_rect->left) && + (m_client_height == new_client_rect->bottom - new_client_rect->top) && + (m_window_width == new_window_rect->right - new_window_rect->left) && + (m_window_height == new_window_rect->bottom - new_window_rect->top)) + { + return TRUE; + } + + m_ready = FALSE; + + m_window_width = new_window_rect->right - new_window_rect->left; + m_window_height = new_window_rect->bottom - new_window_rect->top; + m_client_width = new_client_rect->right - new_client_rect->left; + m_client_height = new_client_rect->bottom - new_client_rect->top; + + m_d3dpp.BackBufferWidth = m_client_width; + m_d3dpp.BackBufferHeight = m_client_height; + if (m_lpDevice->Reset( &m_d3dpp ) != D3D_OK) + { + WriteSafeWindowPos(); + + char str[1024]; + sprintf(str, + "Window resize failed.\r" + "\r" + "Often this means the application ran out of video memory;\r" + " perhaps you tried to make the window too large.\r" + ); + MessageBox(m_hwnd, str, "OUT OF VIDEO MEMORY", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + + m_lastErr = DXC_ERR_RESIZEFAILED; + return FALSE; + } + + SetViewport(); + m_ready = TRUE; +#endif + return TRUE; +} + +void DXContext::SetViewport() +{ + D3DVIEWPORT9 v; + v.X = 0; + v.Y = 0; + v.Width = m_client_width; + v.Height = m_client_height; + v.MinZ = 0.0f; + v.MaxZ = 1.0f; +// m_lpDevice->SetViewport(&v); +} + +void DXContext::MinimizeWinamp(HMONITOR hPluginMonitor) +{ +#if 0 + // minimize Winamp window + + HMONITOR hWinampMon = MonitorFromWindow(m_hwnd_winamp, MONITOR_DEFAULTTONEAREST); + HMONITOR hPluginMon = hPluginMonitor;//MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);//m_lpD3D->GetAdapterMonitor(ordinal_adapter); + + if ((m_current_mode.screenmode == FULLSCREEN || m_current_mode.screenmode == FAKE_FULLSCREEN) && + (m_minimize_winamp) && + (hWinampMon && hPluginMon && hPluginMon==hWinampMon) && + (!m_winamp_minimized) + ) + { + // nitpicky check: if we're in fake fullscreen mode + // and are only going to display on half the screen, + // don't minimize Winamp. + if (m_current_mode.screenmode == FAKE_FULLSCREEN) + { + int x = m_monitor_rect.right - m_monitor_rect.left; + int y = m_monitor_rect.bottom - m_monitor_rect.top; + if ((x >= y*2 && m_current_mode.m_dualhead_horz != 0) || + (y > x*4/3 && m_current_mode.m_dualhead_vert != 0)) + { + return; + } + } + + ShowWindow(m_hwnd_winamp, SW_MINIMIZE); + // also restore the focus to the plugin window, since this will steal it: + SetFocus(m_hwnd); + SetActiveWindow(m_hwnd); + SetForegroundWindow(m_hwnd); + m_winamp_minimized = 1; + } +#endif +} + +void DXContext::RestoreWinamp() +{ +#if 0 + if (m_winamp_minimized) + { + ShowWindow(m_hwnd_winamp, SW_RESTORE); + m_winamp_minimized = 0; + } +#endif +} + +void DXContext::UpdateMonitorWorkRect() +{ +#if 0 + // get active monitor's bounding rectangle (to assist w/window positioning) + // note: in vert/horz span setups (psuedo-multimon), + // this will be 2048x768 or 1024x1536 or something like that. + + // calling this each frame allows you to detect when the taskbar + // moves around on the screen (from edge to edge), and rearrange + // the visual elements accordingly, so nothing is obscured. + + HMONITOR hMon = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);//m_lpD3D->GetAdapterMonitor(m_ordinal_adapter); + if (hMon) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMon, &mi)) + { + m_monitor_work_rect = mi.rcWork; + m_monitor_work_rect_orig = mi.rcWork; + + // if the monitor rect we're using is the same as the + // whole area of the monitor, there's no need to update it... + //if (memcmp(&mi.rcMonitor, &m_monitor_rect, sizeof(RECT))==0) + // return; + + // otherwise, we're doing a half-screen special case + // and are running in some pseudo-multimon res like + // 2048x768 or 1024x1536, but only using half of it + // (i.e. fake fullscreen or desktop mode) + + // therefore... we need to update the work-area rectangle + // to reflect which half of the screen it's on. + + if (m_monitor_rect.left == mi.rcMonitor.left) + m_monitor_work_rect.left = mi.rcWork.left; + else + m_monitor_work_rect.left = m_monitor_rect.left + (mi.rcWork.left - mi.rcMonitor.left); + + if (m_monitor_rect.top == mi.rcMonitor.top) + m_monitor_work_rect.top = mi.rcWork.top; + else + m_monitor_work_rect.top = m_monitor_rect.top + (mi.rcWork.top - mi.rcMonitor.top); + + if (m_monitor_rect.right == mi.rcMonitor.right) + m_monitor_work_rect.right = mi.rcWork.right; + else + m_monitor_work_rect.right = m_monitor_rect.right; + + if (m_monitor_rect.bottom == mi.rcMonitor.bottom) + m_monitor_work_rect.bottom = mi.rcWork.bottom; + else + m_monitor_work_rect.bottom = m_monitor_rect.bottom; + } + } +#endif +} + +void DXContext::SaveWindow() +{ +#if 0 + if (m_current_mode.screenmode == WINDOWED) + { + RECT c; + GetClientRect( m_hwnd, &c ); + + // convert client rect from client coords to screen coords: + // (window rect is already in screen coords...) + POINT p; + p.x = c.left; + p.y = c.top; + if (ClientToScreen(m_hwnd, &p)) + { + c.left += p.x; + c.right += p.x; + c.top += p.y; + c.bottom += p.y; + } + + // save bounds for window CLIENT area, but in screen coords + WritePrivateProfileInt(c.top, "nMainWndTop", m_szIniFile, "settings"); + WritePrivateProfileInt(c.left, "nMainWndLeft", m_szIniFile, "settings"); + WritePrivateProfileInt(c.right, "nMainWndRight", m_szIniFile, "settings"); + WritePrivateProfileInt(c.bottom,"nMainWndBottom", m_szIniFile, "settings"); + + // also save bounds for embedwnd + if (m_current_mode.m_skin && myWindowState.me) + { + WritePrivateProfileInt(myWindowState.r.left,"avs_wx",m_szIniFile,"settings"); + WritePrivateProfileInt(myWindowState.r.top ,"avs_wy",m_szIniFile,"settings"); + WritePrivateProfileInt(myWindowState.r.right-myWindowState.r.left,"avs_ww",m_szIniFile,"settings"); + WritePrivateProfileInt(myWindowState.r.bottom-myWindowState.r.top,"avs_wh",m_szIniFile,"settings"); + } + else if (!m_current_mode.m_skin && m_hwnd) + { + RECT r; + GetWindowRect(m_hwnd, &r); + WritePrivateProfileInt(r.left,"avs_wx",m_szIniFile,"settings"); + WritePrivateProfileInt(r.top ,"avs_wy",m_szIniFile,"settings"); + WritePrivateProfileInt(r.right-r.left,"avs_ww",m_szIniFile,"settings"); + WritePrivateProfileInt(r.bottom-r.top,"avs_wh",m_szIniFile,"settings"); + } + } +#endif +} \ No newline at end of file diff --git a/lib/vis_milkdrop/dxcontext.h b/lib/vis_milkdrop/dxcontext.h new file mode 100644 index 0000000..130d7a9 --- /dev/null +++ b/lib/vis_milkdrop/dxcontext.h @@ -0,0 +1,151 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __NULLSOFT_DX8_PLUGIN_SHELL_DXCONTEXT_H__ +#define __NULLSOFT_DX8_PLUGIN_SHELL_DXCONTEXT_H__ 1 + +#include +//#include +#include "shell_defines.h" +//#include "defines.h" +#include +#include + +typedef struct +{ + eScrMode screenmode; // WINDOWED, FULLSCREEN, or FAKE FULLSCREEN + int nbackbuf; + int allow_page_tearing; + GUID adapter_guid; + D3DDISPLAYMODE display_mode; // ONLY VALID FOR FULLSCREEN MODE. + D3DMULTISAMPLE_TYPE multisamp; + HWND parent_window; + int m_dualhead_horz; // 0 = span both, 1 = left only, 2 = right only + int m_dualhead_vert; // 0 = span both, 1 = top only, 2 = bottom only + int m_skin; +} +DXCONTEXT_PARAMS; + +#define MAX_DXC_ADAPTERS 32 + +class DXContext +{ + public: + // PUBLIC FUNCTIONS + DXContext(LPDIRECT3DDEVICE9 device, char* szIniFile); +// DXContext(int hWndWinamp,HINSTANCE hInstance,LPCSTR szClassName,LPCSTR szWindowCaption,WNDPROC pProc,LONG uWindowLong, int minimize_winamp, char* szIniFile); + ~DXContext(); + BOOL StartOrRestartDevice(DXCONTEXT_PARAMS *pParams); // also serves as Init() function + BOOL OnUserResizeWindow(RECT *new_window_rect, RECT *new_client_rect); + inline HWND GetHwnd() { return m_hwnd; }; + inline int TempIgnoreDestroyMessages() { return m_ignore_wm_destroy; }; + void OnTrulyExiting() { m_truly_exiting = 1; } + void UpdateMonitorWorkRect(); + int GetBitDepth() { return m_bpp; }; + inline D3DFORMAT GetZFormat() { return m_zFormat; }; + char* GetDriver() { return m_szDriver; }; + char* GetDesc() { return m_szDesc; }; + void SaveWindow(); + + // PUBLIC DATA - DO NOT WRITE TO THESE FROM OUTSIDE THE CLASS + int m_ready; + HRESULT m_lastErr; + int m_window_width; + int m_window_height; + int m_client_width; + int m_client_height; + int m_fake_fs_covers_all; + int m_frame_delay; + RECT m_all_monitors_rect; // rect that encompasses all monitors that make up the desktop. The primary monitor's upper-left corner is (0,0). + RECT m_monitor_rect; // rect for monitor the plugin is running on; for pseudo-multimon modes like 2048x768, if user decides to only run on half the monitor, this rect reflects that as well. + RECT m_monitor_rect_orig; // same, but it's the original rect; does not account for pseudo-multimon modes like 2048x768 + RECT m_monitor_work_rect; // same, but excludes the taskbar area. + RECT m_monitor_work_rect_orig; // original work rect; does not account for pseudo-multimon modes like 2048x768 + DXCONTEXT_PARAMS m_current_mode; + LPDIRECT3DDEVICE9 m_lpDevice; + D3DPRESENT_PARAMETERS m_d3dpp; + //LPDIRECT3D9 m_lpD3D; + D3DCAPS9 m_caps; + + protected: + D3DMULTISAMPLE_TYPE m_multisamp; + D3DFORMAT m_zFormat; + D3DFORMAT m_orig_windowed_mode_format[MAX_DXC_ADAPTERS]; + HMODULE m_hmod_d3d8; + int m_ordinal_adapter; + HWND m_hwnd; + HWND m_hwnd_winamp; + LONG m_uWindowLong; + char m_szClassName[256]; + char m_szWindowCaption[512]; + char m_szIniFile[MAX_PATH]; + char m_szDriver[512]; + char m_szDesc[512]; + HINSTANCE m_hInstance; + int m_ignore_wm_destroy; + int m_minimize_winamp; + int m_winamp_minimized; + int m_truly_exiting; + int m_bpp; + + embedWindowState myWindowState; + + void WriteSafeWindowPos(); + int GetWindowedModeAutoSize(int iteration); + BOOL TestDepth(int ordinal_adapter, D3DFORMAT fmt); + BOOL TestFormat(int ordinal_adapter, D3DFORMAT fmt); + int CheckAndCorrectFullscreenDispMode(int ordinal_adapter, D3DDISPLAYMODE *pdm); + void SetViewport(); + void MinimizeWinamp(HMONITOR hPluginMonitor); + BOOL Internal_Init(DXCONTEXT_PARAMS *pParams, BOOL bFirstInit); + void Internal_CleanUp(); + void RestoreWinamp(); +}; + +#define DXC_ERR_REGWIN -2 +#define DXC_ERR_CREATEWIN -3 +#define DXC_ERR_CREATE3D -4 +#define DXC_ERR_GETFORMAT -5 +#define DXC_ERR_FORMAT -6 +#define DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY -7 +#define DXC_ERR_RESIZEFAILED -8 +#define DXC_ERR_CAPSFAIL -9 +#define DXC_ERR_BAD_FS_DISPLAYMODE -10 +#define DXC_ERR_USER_CANCELED -11 +#define DXC_ERR_CREATEDEV_NOT_AVAIL -12 +#define DXC_ERR_CREATEDDRAW -13 + + + + + + + +#endif \ No newline at end of file diff --git a/lib/vis_milkdrop/evallib/CAL_TAB.C b/lib/vis_milkdrop/evallib/CAL_TAB.C new file mode 100644 index 0000000..2b904a0 --- /dev/null +++ b/lib/vis_milkdrop/evallib/CAL_TAB.C @@ -0,0 +1,601 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +//#include +#include +#include "Compiler.h" +#include "eval.h" + +#define VALUE 258 +#define IDENTIFIER 259 +#define FUNCTION1 260 +#define FUNCTION2 261 +#define FUNCTION3 262 +#define UMINUS 263 +#define UPLUS 264 +#define YYSTYPE int + +int yyerror(char *); +int yylex(char **exp); + +extern int result; + +typedef struct +{ + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; +} yyltype; + +#define YYLTYPE yyltype + +#define YYFINAL 51 +#define YYFLAG -32768 +#define YYNTBASE 21 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 264 ? yytranslate[x] : 26) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 14, 9, 2, 18, + 19, 12, 10, 20, 11, 2, 13, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 17, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 15, 16 +}; + + +static const short yyr1[] = { 0, + 21, 21, 22, 23, 23, 23, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 25, 25, 25 +}; + +static const short yyr2[] = { 0, + 1, 3, 1, 1, 1, 3, 1, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 1, 4, 6, 8 +}; + +static const short yydefact[] = { 0, + 3, 4, 0, 0, 0, 0, 0, 0, 5, 7, + 1, 17, 0, 0, 0, 0, 4, 16, 15, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 0, 6, 14, 13, 11, 12, 8, 9, 10, 18, + 0, 0, 0, 0, 19, 0, 0, 20, 0, 0, + 0 +}; + +static const short yydefgoto[] = { 49, + 9, 10, 11, 12 +}; + +static const short yypact[] = { 19, +-32768, -11, -7, -5, -4, 38, 38, 38,-32768,-32768, + 136,-32768, 38, 38, 38, 38,-32768,-32768,-32768, 88, + 38, 38, 38, 38, 38, 38, 38, 136, 100, 49, + 62,-32768, 41, 54, -9, -9,-32768,-32768,-32768,-32768, + 38, 38, 112, 75,-32768, 38, 124,-32768, 12, 27, +-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768, -6,-32768 +}; + + +#define YYLAST 150 + + +static const short yytable[] = { 18, + 19, 20, 25, 26, 27, 13, 28, 29, 30, 31, + 14, 50, 15, 16, 33, 34, 35, 36, 37, 38, + 39, 1, 2, 3, 4, 5, 51, 0, 6, 7, + 0, 0, 0, 0, 43, 44, 8, 0, 0, 47, + 1, 17, 3, 4, 5, 0, 0, 6, 7, 22, + 23, 24, 25, 26, 27, 8, 21, 22, 23, 24, + 25, 26, 27, 23, 24, 25, 26, 27, 41, 21, + 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, + 0, 42, 21, 22, 23, 24, 25, 26, 27, 0, + 0, 0, 0, 0, 46, 21, 22, 23, 24, 25, + 26, 27, 0, 0, 0, 0, 32, 21, 22, 23, + 24, 25, 26, 27, 0, 0, 0, 0, 40, 21, + 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, + 45, 21, 22, 23, 24, 25, 26, 27, 0, 0, + 0, 0, 48, 21, 22, 23, 24, 25, 26, 27 +}; + +static const short yycheck[] = { 6, + 7, 8, 12, 13, 14, 17, 13, 14, 15, 16, + 18, 0, 18, 18, 21, 22, 23, 24, 25, 26, + 27, 3, 4, 5, 6, 7, 0, -1, 10, 11, + -1, -1, -1, -1, 41, 42, 18, -1, -1, 46, + 3, 4, 5, 6, 7, -1, -1, 10, 11, 9, + 10, 11, 12, 13, 14, 18, 8, 9, 10, 11, + 12, 13, 14, 10, 11, 12, 13, 14, 20, 8, + 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, + -1, 20, 8, 9, 10, 11, 12, 13, 14, -1, + -1, -1, -1, -1, 20, 8, 9, 10, 11, 12, + 13, 14, -1, -1, -1, -1, 19, 8, 9, 10, + 11, 12, 13, 14, -1, -1, -1, -1, 19, 8, + 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, + 19, 8, 9, 10, 11, 12, 13, 14, -1, -1, + -1, -1, 19, 8, 9, 10, 11, 12, 13, 14 +}; +#define YYPURE 1 + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYIMPURE +#define YYLEX yylex(&exp) +#endif + +#ifndef YYPURE +#define YYLEX yylex(&yylval)//, &yylloc) MY MODIF! +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYIMPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + + +int yynerrs; /* number of parse errors so far */ +#endif /* YYIMPURE */ + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#define YYINITDEPTH 5000 +#define YYMAXDEPTH 5000 + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +#define __yy_bcopy(from,to,count) memcpy(to,from,(count)>0?(count):0) + +//#ln 131 "bison.simple" +int yyparse(char *exp) +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + + int yystacksize = YYINITDEPTH; + +#ifndef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + + yylval = 0; + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. */ + + yyssp = yyss - 1; + yyvsp = yyvs; + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + + if (yystacksize >= YYMAXDEPTH) + { + yyerror("internal error: parser stack overflow"); + return 2; + } + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; + + + if (yyssp >= yyss + yystacksize - 1) YYABORT; + } + + +// yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +// yyStackSize = yyssp - (yyss - 1); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + + } + else + { + yychar1 = YYTRANSLATE(yychar); + + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + + + switch (yyn) { + +case 1: +//#ln 32 "cal.y" +{ yyval = yyvsp[0]; result = yyvsp[0]; ; + break;} +case 2: +//#ln 34 "cal.y" +{ { + int i = (int)setVar((int)yyvsp[-2], 0); + int v = createCompiledValue(0, &(varTable[i].value)); + yyval = createCompiledFunction2(MATH_SIMPLE, FN_ASSIGN, v, (int)yyvsp[0]); + result = yyval; + } + ; + break;} +case 3: +//#ln 50 "cal.y" +{ yyval = yyvsp[0] ; + break;} +case 4: +//#ln 55 "cal.y" +{ yyval = getVar((int)yyvsp[0]);; + break;} +case 5: +//#ln 57 "cal.y" +{ yyval = yyvsp[0];; + break;} +case 6: +//#ln 59 "cal.y" +{ yyval = yyvsp[-1];; + break;} +case 7: +//#ln 64 "cal.y" +{ yyval = yyvsp[0]; ; + break;} +case 8: +//#ln 66 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_MULTIPLY, yyvsp[-2], yyvsp[0]); + break;} +case 9: +//#ln 72 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_DIVIDE, yyvsp[-2], yyvsp[0]); + break;} +case 10: +//#ln 78 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_MODULO, yyvsp[-2], yyvsp[0]); + break;} +case 11: +//#ln 84 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_ADD, yyvsp[-2], yyvsp[0]); + break;} +case 12: +//#ln 90 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_SUB, yyvsp[-2], yyvsp[0]); + break;} +case 13: +//#ln 96 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_AND, yyvsp[-2], yyvsp[0]); + break;} +case 14: +//#ln 102 "cal.y" +{ yyval = createCompiledFunction2(MATH_SIMPLE, FN_OR, yyvsp[-2], yyvsp[0]); + break;} +case 15: +//#ln 108 "cal.y" +{ yyval = createCompiledFunction1(MATH_SIMPLE, FN_UMINUS, yyvsp[0]); + break;} +case 16: +//#ln 114 "cal.y" +{ yyval = createCompiledFunction1(MATH_SIMPLE, FN_UPLUS, yyvsp[0]); + break;} +case 17: +//#ln 120 "cal.y" +{ yyval = yyvsp[0]; + break;} +case 18: +//#ln 125 "cal.y" +{ yyval = createCompiledFunction1(MATH_FN, (int)yyvsp[-3], yyvsp[-1]); + break;} +case 19: +//#ln 131 "cal.y" +{ yyval = createCompiledFunction2(MATH_FN, (int)yyvsp[-5], yyvsp[-3], yyvsp[-1]); + break;} +case 20: +//#ln 137 "cal.y" +{ yyval = createCompiledFunction3(MATH_FN, (int)yyvsp[-7], yyvsp[-5], yyvsp[-3], yyvsp[-1]); + break;} +} + /* the action file gets copied in in place of this dollarsign */ +//#ln 362 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; + + *++yyvsp = yyval; + + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; +#error this should not compile + msg = (char *) xmalloc(size + 15); + strcpy(msg, "syntax error"); + + if (count < 5) + { + count = 0; + for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("syntax error"); + } + +//yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) YYABORT; + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; + + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + yystate = yyn; + goto yynewstate; +} diff --git a/lib/vis_milkdrop/evallib/CMakeLists.txt b/lib/vis_milkdrop/evallib/CMakeLists.txt new file mode 100644 index 0000000..69c4252 --- /dev/null +++ b/lib/vis_milkdrop/evallib/CMakeLists.txt @@ -0,0 +1,21 @@ +project(evallib) + +enable_language(C) + +cmake_minimum_required(VERSION 2.6) + +set(SOURCES CAL_TAB.C + cfunc.c + Compiler.c + eval.c + Gettok.c + Lextab.c + LLSAVE.C + Yylex.c) + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # disable optimization for cfunc.c and Compiler.c + set_source_files_properties(cfunc.c Compiler.c COMPILE_FLAGS -Od) +endif() + +add_library(evallib STATIC ${SOURCES}) diff --git a/lib/vis_milkdrop/evallib/Compiler.c b/lib/vis_milkdrop/evallib/Compiler.c new file mode 100644 index 0000000..f1c0562 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Compiler.c @@ -0,0 +1,424 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include +//#include +#include +#include +#include "Compiler.h" +#include "eval.h" + +#define LLB_DSIZE (65536-64) +typedef struct _llBlock { + struct _llBlock *next; + int sizeused; + char block[LLB_DSIZE]; +} llBlock; + +typedef struct _startPtr { + struct _startPtr *next; + void *startptr; +} startPtr; + +typedef struct { + llBlock *blocks; + startPtr *startpts; + } codeHandleType; + +static llBlock *blocks_head = NULL; + +double computTable[16384]; +double *nextBlock=computTable; + +extern CRITICAL_SECTION g_eval_cs; + +static void *newBlock(int size); +static void freeBlocks(llBlock *start); + + +void _asm_sin(void); +void _asm_cos(void); +void _asm_tan(void); +void _asm_int(void); +void _asm_asin(void); +void _asm_acos(void); +void _asm_atan(void); +void _asm_atan2(void); +void _asm_sqr(void); +void _asm_sqrt(void); +void _asm_pow(void); +void _asm_exp(void); +void _asm_log(void); +void _asm_log10(void); +void _asm_abs(void); +void _asm_min(void); +void _asm_max(void); +void _asm_sig(void); +void _asm_sign(void); +void _asm_rand(void); +void _asm_band(void); +void _asm_bor(void); +void _asm_bnot(void); +void _asm_if(void); +void _asm_equal(void); +void _asm_below(void); +void _asm_above(void); +void _asm_assign(void); +void _asm_add(void); +void _asm_sub(void); +void _asm_mul(void); +void _asm_div(void); +void _asm_mod(void); +void _asm_or(void); +void _asm_and(void); +void _asm_uplus(void); +void _asm_uminus(void); +void _asm_function3(void); +void _asm_function3_end(void); +void _asm_function2(void); +void _asm_function2_end(void); +void _asm_function1(void); +void _asm_function1_end(void); +void _asm_simpleValue(void); +void _asm_simpleValue_end(void); + +functionType fnTable[27] = {{ "sin", _asm_sin, 1 }, + { "cos", _asm_cos, 1 }, + { "tan", _asm_tan, 1 }, + { "int", _asm_int, 1 }, + { "asin", _asm_asin, 1 }, + { "acos", _asm_acos, 1 }, + { "atan", _asm_atan, 1 }, + { "atan2", _asm_atan2, 2 }, + { "sqr", _asm_sqr, 1 }, + { "sqrt", _asm_sqrt, 1 }, + { "pow", _asm_pow, 2 }, + { "exp", _asm_exp, 1 }, + { "log", _asm_log, 1 }, + { "log10", _asm_log10, 1 }, + { "abs", _asm_abs, 1 }, + { "min", _asm_min, 2 }, + { "max", _asm_max, 2 }, + { "sigmoid",_asm_sig, 2 } , + { "sign", _asm_sign, 1 } , + { "rand", _asm_rand, 1 } , + { "band", _asm_band, 2 } , + { "bor", _asm_bor, 2 } , + { "bnot", _asm_bnot, 1 } , + { "if", _asm_if, 3 }, + { "equal", _asm_equal, 2 }, + { "below", _asm_below, 2 }, + { "above", _asm_above, 2 }, + }; + + +//--------------------------------------------------------------------------------------------------------------- +void *realAddress(void *fn) +{ +#if defined(_DEBUG) + unsigned char *ptr = (char *)fn; + if(*ptr == 0xE9) + ptr += (*(int *)((ptr+1))+5); + return ptr; +#else + // Release Mode + return fn; +#endif +} + +//#define realAddress(a) a + +//--------------------------------------------------------------------------------------------------------------- +static void freeBlocks(llBlock *start) +{ + while (start) + { + llBlock *llB = start->next; + VirtualFree(start, 0, MEM_RELEASE); + start=llB; + } +} + +//--------------------------------------------------------------------------------------------------------------- +static void *newBlock(int size) +{ + llBlock *llb; + int alloc_size; + if (blocks_head && (LLB_DSIZE - blocks_head->sizeused) >= size) + { + void *t=blocks_head->block+blocks_head->sizeused; + blocks_head->sizeused+=size; + return t; + } + alloc_size=sizeof(llBlock); + if ((int)size > LLB_DSIZE) alloc_size += size - LLB_DSIZE; + llb = (llBlock *)VirtualAlloc(NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // grab bigger block if absolutely necessary (heh) + llb->sizeused=size; + llb->next = blocks_head; + blocks_head = llb; + return llb->block; +} + +//--------------------------------------------------------------------------------------------------------------- +static int *findFBlock(char *p) +{ + while (*(int *)p != 0xFFFFFFFF) p++; + return (int*)p; +} + + +//--------------------------------------------------------------------------------------------------------------- +int createCompiledValue(double value, double *addrValue) +{ + int size; + char *block; + double *dupValue; + int i =0; + char *p; + char txt[512]; + + //size=(int)_asm_simpleValue_end-(int)_asm_simpleValue; + size = 0x10; + block=(char *)newBlock(size); + + if (addrValue == NULL) + *(dupValue = (double *)newBlock(sizeof(double))) = value; + else + dupValue = addrValue; + + memcpy(block, realAddress(_asm_simpleValue), size); + + p = block; + while (*(int *)p != 0xFFFFFFFF) + { + txt[i++] = *p; + p++; + }; + txt[i] = 0; + + *findFBlock(block)=(int)dupValue; + + return ((int)(block)); + +} + +//--------------------------------------------------------------------------------------------------------------- +int getFunctionAddress(int fntype, int fn) +{ + switch (fntype) + { + case MATH_SIMPLE: + switch (fn) + { + case FN_ASSIGN: + return (int)realAddress(_asm_assign); + case FN_ADD: + return (int)realAddress(_asm_add); + case FN_SUB: + return (int)realAddress(_asm_sub); + case FN_MULTIPLY: + return (int)realAddress(_asm_mul); + case FN_DIVIDE: + return (int)realAddress(_asm_div); + case FN_MODULO: + return (int)realAddress(_asm_mod); + case FN_AND: + return (int)realAddress(_asm_and); + case FN_OR: + return (int)realAddress(_asm_or); + case FN_UPLUS: + return (int)realAddress(_asm_uplus); + case FN_UMINUS: + return (int)realAddress(_asm_uminus); + } + case MATH_FN: + return (int)realAddress(fnTable[fn].afunc); + } + return 0; +} + + +//--------------------------------------------------------------------------------------------------------------- +int createCompiledFunction3(int fntype, int fn, int code1, int code2, int code3) +{ + int *p; + int size; + char *block; + +// size=(int)_asm_function3_end-(int)_asm_function3; + size = 0x30; + block=(char *)newBlock(size); + + memcpy(block, realAddress(_asm_function3), size); + + p=findFBlock(block); *p++=code1; + p=findFBlock((char*)p); *p++=code2; + p=findFBlock((char*)p); *p++=code3; + p=findFBlock((char*)p); *p++=getFunctionAddress(fntype, fn); + + return ((int)(block)); +} + +//--------------------------------------------------------------------------------------------------------------- +int createCompiledFunction2(int fntype, int fn, int code1, int code2) +{ + int *p; + int size; + char *block; + +// size=(int)_asm_function2_end-(int)_asm_function2; + size = 0x20; + block=(char *)newBlock(size); + + memcpy(block, realAddress(_asm_function2), size); + + p=findFBlock(block); *p++=code1; + p=findFBlock((char*)p); *p++=code2; + p=findFBlock((char*)p); *p++=getFunctionAddress(fntype, fn); + + return ((int)(block)); +} + + +//--------------------------------------------------------------------------------------------------------------- +int createCompiledFunction1(int fntype, int fn, int code) +{ + int size; + int *p; + char *block; + +// size=(int)_asm_function1_end-(int)_asm_function1; + size = 0x20; + block=(char *)newBlock(size); + + memcpy(block, realAddress(_asm_function1), size); + + p=findFBlock(block); *p++=code; + p=findFBlock((char*)p); *p++=getFunctionAddress(fntype, fn); + + return ((int)(block)); +} + +//------------------------------------------------------------------------------ +int compileCode(char *expression) +{ + char expr[4096]; + codeHandleType *handle; + startPtr *scode=NULL; + blocks_head=0; + + if (!expression || !*expression) return 0; + if (!varTable) return 0; + + handle = (codeHandleType*)newBlock(sizeof(codeHandleType)); + + if (!handle) return 0; + + memset(handle,0,sizeof(codeHandleType)); + + while (*expression) + { + startPtr *tmp; + char *expr_ptr; + int l=4095; + colCount=0; + + // single out segment + while (*expression == ';' || *expression == ' ' || *expression == '\n' || + *expression == '\r' || *expression == '\t') expression++; + if (!*expression) break; + expr_ptr = expr; + while (l-->0) + { + int a=*expression; + if (a) expression++; + if (!a || a == ';') break; + if (a == '\n' || a=='\r' || a=='\t') a=' '; + *expr_ptr++ = a; + } + *expr_ptr = 0; + + // parse + tmp=(startPtr*) newBlock(sizeof(startPtr)); + if (!tmp) break; + tmp->startptr=compileExpression(expr); + if (!tmp->startptr) { scode=NULL; break; } + tmp->next=NULL; + if (!scode) scode=handle->startpts=tmp; + else + { + scode->next=tmp; + scode=tmp; + } + } + + // check to see if failed on the first startingCode + if (!scode) + { + freeBlocks(blocks_head); // free blocks + handle=NULL; // return NULL (after resetting blocks_head) + } + else handle->blocks = blocks_head; + + blocks_head=0; + + return (int)handle; +} + +//------------------------------------------------------------------------------ +void executeCode(int handle) +{ + codeHandleType *h = (codeHandleType *)handle; + startPtr *p; + if (!h) return; +// EnterCriticalSection(&g_eval_cs); + p=h->startpts; + while (p) + { + void *startPoint=p->startptr; + if (!startPoint) break; + p=p->next; + nextBlock=computTable; + __asm pusha // Lets cover our ass + __asm call startPoint + __asm popa + } +// LeaveCriticalSection(&g_eval_cs); +} + +//------------------------------------------------------------------------------ +void freeCode(int handle) +{ + codeHandleType *h = (codeHandleType *)handle; + if (h != NULL) + { + freeBlocks(h->blocks); + } +} + diff --git a/lib/vis_milkdrop/evallib/Compiler.h b/lib/vis_milkdrop/evallib/Compiler.h new file mode 100644 index 0000000..8781876 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Compiler.h @@ -0,0 +1,74 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +. +*/ +#ifndef __COMPILER_H +#define __COMPILER_H + +#define FN_ASSIGN 0 +#define FN_MULTIPLY 1 +#define FN_DIVIDE 2 +#define FN_MODULO 3 +#define FN_ADD 4 +#define FN_SUB 5 +#define FN_AND 6 +#define FN_OR 7 +#define FN_UMINUS 8 +#define FN_UPLUS 9 + +#define MATH_SIMPLE 0 +#define MATH_FN 1 + +#ifdef __cplusplus +extern "C" { +#endif + + +int compileCode(char *exp); +void executeCode(int handle); +void freeCode(int handle); + + + +typedef struct { + char *name; + void *afunc; + int nParams; + } functionType; +extern functionType fnTable[27]; + +int createCompiledValue(double value, double *addrValue); +int createCompiledFunction1(int fntype, int fn, int code); +int createCompiledFunction2(int fntype, int fn, int code1, int code2); +int createCompiledFunction3(int fntype, int fn, int code1, int code2, int code3); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/vis_milkdrop/evallib/Gettok.c b/lib/vis_milkdrop/evallib/Gettok.c new file mode 100644 index 0000000..02dd6b0 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Gettok.c @@ -0,0 +1,6 @@ +/* + * Bob Denny 28-Aug-82 Remove reference to stdio.h + * Scott Guthery 20-Nov-83 Adapt for IBM PC & DeSmet C + */ + +#include "lex.h" diff --git a/lib/vis_milkdrop/evallib/LEX.H b/lib/vis_milkdrop/evallib/LEX.H new file mode 100644 index 0000000..2a6af32 --- /dev/null +++ b/lib/vis_milkdrop/evallib/LEX.H @@ -0,0 +1,53 @@ +/* + * Bob Denny 28-Aug-82 Remove reference to FILE *lexin to + * eliminate dependency on standard I/O library. Only + * lexgetc() used it, and it's there now. + * Add EOF definition for standalone uses. + * Corrected comment for llnxtmax. + * + * Scott Guthery 20-Nov-83 Adapt for IBM PC & DeSmet C. Removed + * equivalence of yylval and lexval since + * a multi-typed parser wants yylval to be + * typed to be the union of the types (YYSTYPE). + */ + +/* + * lex library header file -- accessed through + * #include + */ + +#include + +/* + * Description of scanning tables. The entries at the front of + * the struct must remain in place for the assembler routines to find. + */ +struct lextab { + int llendst; /* Last state number */ + char *lldefault; /* Default state table */ + char *llnext; /* Next state table */ + char *llcheck; /* Check table */ + int *llbase; /* Base table */ + int llnxtmax; /* Last in next table */ + int (*llmove)(); /* Move between states */ + char *llfinal; /* Final state descriptions */ + int (*llactr)(); /* Action routine */ + int *lllook; /* Look ahead vector if != NULL */ + char *llign; /* Ignore char vec if != NULL */ + char *llbrk; /* Break char vec if != NULL */ + char *llill; /* Illegal char vec if != NULL */ +}; + +#define NBPW 16 +#define LEXERR 256 +#define LEXSKIP (-1) +#define EOF (-1) +//#define NULL (0) +#define LEXECHO(fp) {lexecho((fp));} + +#define lextext llbuf +#define lexlast llend + +extern FILE *lexin; +extern llstin(); + diff --git a/lib/vis_milkdrop/evallib/LLSAVE.C b/lib/vis_milkdrop/evallib/LLSAVE.C new file mode 100644 index 0000000..23c5e47 --- /dev/null +++ b/lib/vis_milkdrop/evallib/LLSAVE.C @@ -0,0 +1,6 @@ +/* + * This is linked from lexlib to resolve a global in yylex which + * will be undefined if the user grammar has not defined any rules + * with right-context (look-ahead) + */ +char *llsave[1]; /* Look ahead buffer */ diff --git a/lib/vis_milkdrop/evallib/Lexget.c b/lib/vis_milkdrop/evallib/Lexget.c new file mode 100644 index 0000000..b4c76f9 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Lexget.c @@ -0,0 +1,20 @@ +/* + * lexget.c + * + * Bob Denny 28-Aug-82 Move stdio dependencies to lexerr(), lexget(), + * lexech() and mapch(). This is one of 4 modules + * in lexlib which depend upon the standard I/O package. + * + * Scott Guthery 20-Nov-83 Adapt for IBM PC & DeSmet C. + */ + +#include +#include "lex.h" +extern char expression[4096]; +extern int pos; +lexgetc() +{ +char c = expression[pos]; +if (c) pos++; + return( c != 0 ? c : -1); +} diff --git a/lib/vis_milkdrop/evallib/Lexswi.c b/lib/vis_milkdrop/evallib/Lexswi.c new file mode 100644 index 0000000..4999200 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Lexswi.c @@ -0,0 +1,23 @@ +/* + * lexswitch -- switch lex tables + */ + +/* + * Bob Denny 28-Aug-82 Remove reference to stdio.h + * Scott Guthery 20-Nov-83 Adapt for IBM PC & DeSmet C + */ + +#include "lex.h" + +extern struct lextab *_tabp; + +struct lextab * +lexswitch(lp) +struct lextab *lp; +{ + register struct lextab *olp; + + olp = _tabp; + _tabp = lp; + return(olp); +} diff --git a/lib/vis_milkdrop/evallib/Lextab.c b/lib/vis_milkdrop/evallib/Lextab.c new file mode 100644 index 0000000..a8a1f12 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Lextab.c @@ -0,0 +1,260 @@ +/* + * Created by IBM PC LEX from file "scan.l" + * - for use with standard I/O + */ + +#include +#include "lex.h" +#define LL16BIT int + +int _lmovb(struct lextab *lp, int c, int st) +{ + int base; + + while ((base = lp->llbase[st]+c) > lp->llnxtmax || + (lp->llcheck[base] & 0377) != st) { + + if (st != lp->llendst) { + base = lp->lldefault[st] & 0377; + st = base; + } + else + return(-1); + } + return(lp->llnext[base]&0377); +} + +int lexval; +char lbuf[]; + +#define YYSTYPE int +#include "cal_tab.h" +int c; + +extern YYSTYPE yylval; +int translate(int type); +void count(void); +void setLastVar(void); +int lookup(int *typeOfObject); + + +#define INTCONST 1 +#define DBLCONST 2 +#define HEXCONST 3 +#define VARIABLE 4 +#define OTHER 5 + +int _Alextab(__na__) +{ + if (__na__ >= 0 && __na__ <= 19) count(); + switch (__na__) + { + case 0: yylval = translate(HEXCONST); return VALUE; + case 1: yylval = translate(INTCONST); return VALUE; + case 2: yylval = translate(INTCONST); return VALUE; + case 3: yylval = translate(DBLCONST); return VALUE; + case 4: + case 5: setLastVar(); yylval = lookup(&__na__); return __na__; + case 6: return '+'; + case 7: return '-'; + case 8: return '*'; + case 9: return '/'; + case 10: return '%'; + case 11: return '&'; + case 12: return '|'; + case 13: return '('; + case 14: return ')'; + case 15: return '='; + case 16: return ','; + case 17: return ';'; + } + return (LEXSKIP); +} + + +char _Flextab[] = + { + 1, 18, 17, 16, 15, 14, 13, 12, + 11, 10, 9, 8, 7, 6, 4, 5, + 5, 4, 4, 3, 3, 3, 3, 4, + 0, 4, 5, 0, 5, 4, 1, 3, + 0, 2, -1, 1, -1, + }; + + +char _Nlextab[] = + { + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 1, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 1, 36, 36, 36, 36, 9, 8, 36, + 6, 5, 11, 13, 3, 12, 19, 10, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 36, 2, 36, 4, 36, 36, + 36, 29, 29, 29, 29, 29, 29, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 36, 36, 36, 36, 18, + 36, 29, 29, 29, 29, 29, 23, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 14, 18, + 18, 18, 18, 36, 7, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 36, + 36, 36, 36, 36, 36, 36, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 36, 36, 36, 36, 17, 36, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 36, 36, 36, 36, 36, 36, + 36, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 36, 36, 36, 36, 16, + 36, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 36, + 20, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 36, 36, 36, 36, 36, + 36, 36, 25, 25, 25, 25, 25, 25, + 36, 24, 36, 36, 36, 36, 36, 36, + 20, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 25, 25, 25, 25, 25, 25, + 36, 24, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 36, 36, 36, 36, + 36, 36, 36, 28, 28, 28, 28, 28, + 28, 36, 27, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 28, 28, 28, 28, 28, + 28, 31, 27, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 36, 36, 36, + 36, 36, 36, 36, 34, 34, 34, 33, + 34, 34, 36, 32, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 34, 34, 34, 33, + 34, 34, 36, 32, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 36, 36, + 36, 36, 36, 36, 36, 34, 34, 34, + 34, 34, 34, 36, 32, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 34, 34, 34, + 34, 34, 34, 36, 32, + }; + +char _Clextab[] = + { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, 0, 0, -1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -1, 0, -1, 0, -1, -1, + -1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, -1, -1, -1, 0, + -1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, 0, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, -1, + -1, -1, -1, -1, -1, -1, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + -1, -1, -1, -1, 14, -1, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, -1, -1, -1, -1, -1, -1, + -1, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, -1, -1, -1, -1, 15, + -1, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, -1, + 19, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, -1, -1, -1, -1, -1, + -1, -1, 23, 23, 23, 23, 23, 23, + -1, 23, -1, -1, -1, -1, -1, -1, + 19, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 23, 23, 23, 23, 23, 23, + -1, 23, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, -1, -1, -1, -1, + -1, -1, -1, 26, 26, 26, 26, 26, + 26, -1, 26, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 26, 26, 26, 26, 26, + 26, 30, 26, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, -1, -1, -1, + -1, -1, -1, -1, 30, 30, 30, 30, + 30, 30, -1, 30, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 30, 30, 30, 30, + 30, 30, -1, 30, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, -1, -1, + -1, -1, -1, -1, -1, 33, 33, 33, + 33, 33, 33, -1, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 33, 33, 33, + 33, 33, 33, -1, 33, + }; + +char _Dlextab[] = + { + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 15, 14, 14, 36, 36, 20, 19, 14, + 14, 23, 15, 15, 26, 23, 36, 19, + 36, 36, 33, 30, + }; + +int _Blextab[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 77, 152, + 0, 0, 0, 227, 237, 0, 0, 249, + 0, 0, 306, 0, 0, 0, 363, 0, + 0, 420, 0, 0, 0, + }; + +struct lextab lextab = { + 36, + _Dlextab, + _Nlextab, + _Clextab, + _Blextab, + 524, + _lmovb, + _Flextab, + _Alextab, + + NULL, + 0, + 0, + 0, + }; + + diff --git a/lib/vis_milkdrop/evallib/Lmovb.c b/lib/vis_milkdrop/evallib/Lmovb.c new file mode 100644 index 0000000..8be9ec7 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Lmovb.c @@ -0,0 +1,29 @@ +/* + * Bob Denny 28-Aug-82 Remove reference to stdio.h + * Scott Guthery 20-Nov-83 Adapt for IBM PC & DeSmet C + */ + +#include "lex.h" + +_lmovb(lp, c, st) +register int c, st; +register struct lextab *lp; +{ + int base; + + while ((base = lp->llbase[st]+c) > lp->llnxtmax || + (lp->llcheck[base] & 0377) != st) { + + if (st != lp->llendst) { +/* + * This miscompiled on Decus C many years ago: + * st = lp->lldefault[st] & 0377; + */ + base = lp->lldefault[st] & 0377; + st = base; + } + else + return(-1); + } + return(lp->llnext[base]&0377); +} diff --git a/lib/vis_milkdrop/evallib/Scan.l b/lib/vis_milkdrop/evallib/Scan.l new file mode 100644 index 0000000..2513433 --- /dev/null +++ b/lib/vis_milkdrop/evallib/Scan.l @@ -0,0 +1,54 @@ +%{ +#define YYSTYPE double +#include "cal_tab.h" +int c; + +extern YYSTYPE yylval; +double translate(int type); +void count(void); +void setLastVar(void); +int lookup(int *typeOfObject); +struct lextab *lexswitch(struct lextab *lp); + + +#define INTCONST 1 +#define DBLCONST 2 +#define HEXCONST 3 +#define VARIABLE 4 +#define OTHER 5 + +%} + +digit = [0-9]; +letter = [a-zA-Z_]; +hex = [a-fA-F0-9]; +/* -- */ +space = [\40]; +/*number = (digit* | "-" digit*);*/ +number = digit*; +exp = [Ee] number; +doubl = number "." (digit* | digit* exp); + +%% +hex hex* [hH] { count(); yylval = translate(HEXCONST); return VALUE; } +digit* { count(); yylval = translate(INTCONST); return VALUE; } +digit digit* [Dd] { count(); yylval = translate(INTCONST); return VALUE; } +doubl { count(); yylval = translate(DBLCONST); return VALUE; } +letter* { count(); { int typeOfObject; setLastVar(); yylval = lookup(&typeOfObject); return typeOfObject; }} +letter (letter|digit)* { count(); { int typeOfObject; setLastVar(); yylval = lookup(&typeOfObject); return typeOfObject; }} +'+' { count(); return '+'; } +'-' { count(); return '-'; } +'*' { count(); return '*'; } +'/' { count(); return '/'; } +'%' { count(); return '%'; } +'&' { count(); return '&'; } +'|' { count(); return '|'; } +'(' { count(); return '('; } +')' { count(); return ')'; } +'=' { count(); return '='; } +',' { count(); return ','; } +';' { count(); return ';'; } +[ \t\v\f] { count(); } +. { count(); } + +%% diff --git a/lib/vis_milkdrop/evallib/Yylex.c b/lib/vis_milkdrop/evallib/Yylex.c new file mode 100644 index 0000000..37d685d --- /dev/null +++ b/lib/vis_milkdrop/evallib/Yylex.c @@ -0,0 +1,172 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include "lex.h" + +#define ERROR 256 /* yacc's value */ + +static int llset(void); +static int llinp(char **exp); +static int lexgetc(char **exp) +{ + char c= **exp; + if (c) (*exp)++; + return( c != 0 ? c : -1); +} +static int tst__b(register int c, char tab[]) +{ + return (tab[(c >> 3) & 037] & (1 << (c & 07)) ); +} + +static char *llsave[16]; /* Look ahead buffer */ +static char llbuf[100]; /* work buffer */ +static char *llp1 = &llbuf[0]; /* pointer to next avail. in token */ +static char *llp2 = &llbuf[0]; /* pointer to end of lookahead */ +static char *llend = &llbuf[0]; /* pointer to end of token */ +static char *llebuf = &llbuf[sizeof llbuf]; +static int lleof; +static int yyline = 0; +extern struct lextab lextab; + +int gettoken(char *lltb, int lltbsiz) +{ + register char *lp, *tp, *ep; + + tp = lltb; + ep = tp+lltbsiz-1; + for (lp = llbuf; lp < llend && tp < ep;) + *tp++ = *lp++; + *tp = 0; + return(tp-lltb); +} + + +int yylex(char **exp) +{ + register int c, st; + int final, l, llk, i; + register struct lextab *lp; + char *cp; + + while (1) + { + llk = 0; + if (llset()) return(0); + st = 0; + final = -1; + lp = &lextab; + + do { + if (lp->lllook && (l = lp->lllook[st])) { + for (c=0; cllfinal[st]) != -1) { + final = i; + llend = llp1; + } + if ((c = llinp(exp)) < 0) + break; + if ((cp = lp->llbrk) && llk==0 && tst__b(c, cp)) { + llp1--; + break; + } + } while ((st = (*lp->llmove)(lp, c, st)) != -1); + + + if (llp2 < llp1) + llp2 = llp1; + if (final == -1) { + llend = llp1; + if (st == 0 && c < 0) + return(0); + if ((cp = lp->llill) && tst__b(c, cp)) { + continue; + } + return(ERROR); + } + if (c = (final >> 11) & 037) + llend = llsave[c-1]; + if ((c = (*lp->llactr)(final&03777)) >= 0) + return(c); + } +} + +void llinit(viud) +{ + llp1 = llp2 = llend = llbuf; + llebuf = llbuf + sizeof(llbuf); + lleof = yyline = 0; +} + + +static int llinp(char **exp) +{ + register c; + register struct lextab *lp; + register char *cp; + + lp = &lextab; + cp = lp->llign; /* Ignore class */ + for (;;) { + /* + * Get the next character from the save buffer (if possible) + * If the save buffer's empty, then return EOF or the next + * input character. Ignore the character if it's in the + * ignore class. + */ + c = (llp1 < llp2) ? *llp1 & 0377 : (lleof) ? EOF : lexgetc(exp); + if (c >= 0) { /* Got a character? */ + if (cp && tst__b(c, cp)) + continue; /* Ignore it */ + if (llp1 >= llebuf) { /* No, is there room? */ + return -1; + } + *llp1++ = c; /* Store in token buff */ + } else + lleof = 1; /* Set EOF signal */ + return(c); + } +} + +static int llset(void) +/* + * Return TRUE if EOF and nothing was moved in the look-ahead buffer + */ +{ + register char *lp1, *lp2; + + for (lp1 = llbuf, lp2 = llend; lp2 < llp2;) + *lp1++ = *lp2++; + llend = llp1 = llbuf; + llp2 = lp1; + return(lleof && lp1 == llbuf); +} diff --git a/lib/vis_milkdrop/evallib/cal.y b/lib/vis_milkdrop/evallib/cal.y new file mode 100644 index 0000000..3844ac0 --- /dev/null +++ b/lib/vis_milkdrop/evallib/cal.y @@ -0,0 +1,155 @@ + + %{ + #define YYSTYPE double + #include + #include + #include "Compiler.h" + #include "eval.h" + + yyerror(char *); + yylex(); + + extern int yyStackSize; + extern double result; + + int regs[26]; + int base; + + %} + + %token VALUE IDENTIFIER FUNCTION1 FUNCTION2 FUNCTION3 + + %left '|' + %left '&' + %left '+' '-' + %left '*' '/' '%' + %left UMINUS /*supplies precedence for unary minus */ + %left UPLUS /*supplies precedence for unary plus */ + + %% /*beginning of rules section */ + + stat : math_expr + { $$ = $1; result = $1; } + | IDENTIFIER '=' math_expr + { if (parseType == PARSE_EVAL) + { + setVar((int)$1, $3); + $$ = $3; + result = $3; + } + else + { + double i = setVar((int)$1, 0); + double v = createCompiledValue(0, &(varTable[(int)i].value)); + $$ = createCompiledFunction2(MATH_SIMPLE, FN_ASSIGN, v, $3); + result = $$; + } + } + ; + + value : VALUE { $$ = $1 } + + + primary_expr + : IDENTIFIER + { $$ = getVar((int)$1);} + | value + { $$ = $1;} + | '(' math_expr ')' + { $$ = $2;} + ; + + math_expr + : primary_expr + { $$ = $1; } + | math_expr '*' math_expr + { if (parseType == PARSE_EVAL) + $$ = $1 * $3; + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_MULTIPLY, $1, $3); + } + | math_expr '/' math_expr + { if (parseType == PARSE_EVAL) + $$ = $1 / $3; + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_DIVIDE, $1, $3); + } + | math_expr '%' math_expr + { if (parseType == PARSE_EVAL) + $$ = (double)((int)$1 % (int)$3); + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_MODULO, $1, $3); + } + | math_expr '+' math_expr + { if (parseType == PARSE_EVAL) + $$ = $1 + $3; + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_ADD, $1, $3); + } + | math_expr '-' math_expr + { if (parseType == PARSE_EVAL) + $$ = $1 - $3; + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_SUB, $1, $3); + } + | math_expr '&' math_expr + { if (parseType == PARSE_EVAL) + $$ = (double)((int)$1 & (int)$3); + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_AND, $1, $3); + } + | math_expr '|' math_expr + { if (parseType == PARSE_EVAL) + $$ = (double)((int)$1 | (int)$3); + else + $$ = createCompiledFunction2(MATH_SIMPLE, FN_OR, $1, $3); + } + | '-' math_expr %prec UMINUS + { if (parseType == PARSE_EVAL) + $$ = -$2; + else + $$ = createCompiledFunction1(MATH_SIMPLE, FN_UMINUS, $2); + } + | '+' math_expr %prec UPLUS + { if (parseType == PARSE_EVAL) + $$ = +$2; + else + $$ = createCompiledFunction1(MATH_SIMPLE, FN_UPLUS, $2); + } + | fonction + { $$ = $1; } + ; + + fonction + : FUNCTION1 '(' math_expr ')' + { if (parseType == PARSE_EVAL) + $$ = calcFunction1((int)$1, $3); + else + $$ = createCompiledFunction1(MATH_FN, (int)$1, $3); + } + | FUNCTION2 '(' math_expr ',' math_expr ')' + { if (parseType == PARSE_EVAL) + $$ = calcFunction2((int)$1, $3, $5); + else + $$ = createCompiledFunction2(MATH_FN, (int)$1, $3, $5); + } + | FUNCTION3 '(' math_expr ',' math_expr ',' math_expr ')' + { if (parseType == PARSE_EVAL) + $$ = calcFunction3((int)$1, $3, $5, $7); + else + $$ = createCompiledFunction3(MATH_FN, (int)$1, $3, $5, $7); + } + ; + + + + %% + main() + { + return(yyparse()); + } + + yywrap() + { + return(1); + } diff --git a/lib/vis_milkdrop/evallib/cal_tab.h b/lib/vis_milkdrop/evallib/cal_tab.h new file mode 100644 index 0000000..3621332 --- /dev/null +++ b/lib/vis_milkdrop/evallib/cal_tab.h @@ -0,0 +1,42 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#define VALUE 258 +#define IDENTIFIER 259 +#define FUNCTION1 260 +#define FUNCTION2 261 +#define FUNCTION3 262 +#define UMINUS 263 +#define UPLUS 264 + + +YYSTYPE yylval; diff --git a/lib/vis_milkdrop/evallib/cfunc.c b/lib/vis_milkdrop/evallib/cfunc.c new file mode 100644 index 0000000..30940b8 --- /dev/null +++ b/lib/vis_milkdrop/evallib/cfunc.c @@ -0,0 +1,879 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include +//#include +#include +#include +#include "Compiler.h" +#include "eval.h" +#pragma warning(disable: 4312) + +static float g_cmpaddtab[2]={0.0,1.0}; +static double g_closefact = 0.00001, g_half=0.5; +extern double *nextBlock; + + +// FUNCTION CALL TEMPLATES - THESE ARE NEVER ACTUALLY CALLED, +// BUT COPIED AND MODIFIED. +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_simpleValue(void) +{ + __asm + { + mov eax, 0FFFFFFFFh; + ret + } +} +__declspec ( naked ) void _asm_simpleValue_end(void){} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_function3(void) +{ + __asm + { + mov ecx, 0FFFFFFFFh + call ecx + push eax + mov ecx, 0FFFFFFFFh + call ecx + push eax + mov ecx, 0FFFFFFFFh + call ecx + pop ebx + pop ecx + mov edx, 0FFFFFFFFh + jmp edx + } +} +__declspec ( naked ) void _asm_function3_end(void){} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_function2(void) +{ + __asm + { + mov ecx, 0FFFFFFFFh + call ecx + push eax + mov ecx, 0FFFFFFFFh + call ecx + pop ebx + mov ecx, 0FFFFFFFFh + jmp ecx + } +} +__declspec ( naked ) void _asm_function2_end(void){} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_function1(void) +{ + __asm + { + mov ecx, 0FFFFFFFFh + call ecx + mov ecx, 0FFFFFFFFh + jmp ecx + } +} +__declspec ( naked ) void _asm_function1_end(void){} + +// END FUNCTION CALL TEMPLATES + + + +// our registers +static int a,b; +static double *res; + + +#define isnonzero(x) (fabs(x) > g_closefact) + +//--------------------------------------------------------------------------------------------------------------- +static double _rand(double x) +{ + if (x < 1.0) x=1.0; + return (double)(rand()%(int)max(x,1.0)); +} + +//--------------------------------------------------------------------------------------------------------------- +static double _band(double var, double var2) +{ +return isnonzero(var) && isnonzero(var2) ? 1 : 0; +} + +//--------------------------------------------------------------------------------------------------------------- +static double _bor(double var, double var2) +{ +return isnonzero(var) || isnonzero(var2) ? 1 : 0; +} + +//--------------------------------------------------------------------------------------------------------------- +static double _sig(double x, double constraint) +{ +double t = (1+exp(-x*constraint)); +return isnonzero(t) ? 1.0/t : 0; +} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_int(void) +{ + __asm mov dword ptr a, eax + + res = nextBlock++; + + _asm mov edx, DWORD PTR a + _asm fld QWORD PTR [edx] + _asm mov edx, DWORD PTR res + _asm fistp DWORD PTR [edx] + _asm fild DWORD PTR[edx] + _asm fstp QWORD PTR [edx] + _asm mov eax, res + _asm ret + +/* + MrC - The old version uses _ftol2_sse which stomps over our stack + *res = (double) ((int)(*((double*)a))); + __asm + { + mov eax, res + ret + } +*/ +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_asin(void) +{ + __asm mov dword ptr a, eax + + res = nextBlock++; + + *res = asin(*(double*)a); + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_acos(void) +{ + __asm mov dword ptr a, eax + + res = nextBlock++; + + *res = acos(*(double*)a); + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_atan(void) +{ + __asm mov dword ptr a, eax + + res = nextBlock++; + + *res = atan(*(double*)a); + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_atan2(void) +{ + __asm + { + mov dword ptr a, eax + mov dword ptr b, ebx + } + + res = nextBlock++; + *res = atan2(*(double*)b, *(double*)a); + __asm + { + mov eax, res + ret + } +} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_sig(void) +{ + __asm + { + mov dword ptr a, eax + mov dword ptr b, ebx + } + res = nextBlock++; + *res = _sig(*(double*)b, *(double*)a); + __asm + { + mov eax, dword ptr res + ret + } +} +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_rand(void) +{ + __asm + { + mov dword ptr a, eax + } + + res = nextBlock++; + *res = _rand(*(double*)a); + + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_band(void) +{ + __asm + { + mov dword ptr a, eax + mov dword ptr b, ebx + } + + res = nextBlock++; + *res = _band(*(double*)b, *(double*)a); + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_bor(void) +{ + __asm + { + mov dword ptr a, eax + mov dword ptr b, ebx + } + + res = nextBlock++; + *res = _bor(*(double*)b, *(double*)a); + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_pow(void) +{ + __asm + { + mov dword ptr a, eax + mov dword ptr b, ebx + } + + res = nextBlock++; + *res = pow(*(double*)b, *(double*)a); + __asm + { + mov eax, res + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_exp(void) +{ + __asm mov dword ptr a, eax + + res = nextBlock++; + + *res = exp(*(double*)a); + __asm + { + mov eax, res + ret + } +} + + + + + + + + + + +// these below are all asm, no loops, radness + + + + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_sin(void) +{ + __asm + { + fld qword ptr [eax] + mov eax, nextBlock + fsin + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_cos(void) +{ + __asm + { + fld qword ptr [eax] + mov eax, nextBlock + fcos + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_tan(void) +{ + __asm + { + fld qword ptr [eax] + mov eax, nextBlock + fsincos + fdiv + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_sqr(void) +{ + __asm + { + fld qword ptr [eax] + fld st(0) + mov eax, nextBlock + fmul + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_sqrt(void) +{ + __asm + { + fld qword ptr [eax] + mov eax, nextBlock + fabs + fsqrt + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_log(void) +{ + __asm + { + fld1 + fldl2e + fdiv + fld qword ptr [eax] + mov eax, nextBlock + fyl2x + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_log10(void) +{ + __asm + { + fld1 + fldl2t + fdiv + fld qword ptr [eax] + mov eax, nextBlock + fyl2x + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_abs(void) +{ + __asm + { + fld qword ptr [eax] + mov eax, nextBlock + fabs + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_assign(void) +{ + __asm + { + mov ecx, [eax] + mov edx, [eax+4] + mov [ebx], ecx + mov [ebx+4], edx + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_add(void) +{ + __asm + { + fld qword ptr [eax] + mov eax, nextBlock + fld qword ptr [ebx] + fadd + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_sub(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + mov eax, nextBlock + fsub + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_mul(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + mov eax, nextBlock + fmul + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_div(void) +{ + __asm + { + fld qword ptr [ebx] + fdiv qword ptr [eax] + mov eax, nextBlock + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_mod(void) +{ + __asm + { + fld qword ptr [ebx] + + fld qword ptr [eax] + fsub dword ptr [g_cmpaddtab+4] + fabs + fadd qword ptr [eax] + fadd dword ptr [g_cmpaddtab+4] + + fmul qword ptr [g_half] + + mov ebx, nextBlock + + fistp dword ptr [ebx] + fistp dword ptr [ebx+4] + mov eax, [ebx+4] + xor edx, edx + div dword ptr [ebx] + mov [ebx], edx + fild dword ptr [ebx] + fstp qword ptr [ebx] + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx // eax is still good + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_or(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + mov eax, nextBlock + fistp qword ptr [eax] + fistp qword ptr [eax+8] + mov ebx, [eax] + or [eax+4], ebx + mov ebx, [eax+8] + or [eax+12], ebx + fild qword ptr [eax] + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_and(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + mov eax, nextBlock + fistp qword ptr [eax] + fistp qword ptr [eax+8] + mov ebx, [eax] + and [eax+4], ebx + mov ebx, [eax+8] + and [eax+12], ebx + fild qword ptr [eax] + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_uplus(void) +{ + __asm + { + mov ebx, nextBlock + mov ecx, [eax] + mov [ebx], ecx + mov ecx, [eax+4] + mov [ebx+4], ecx + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_uminus(void) +{ + __asm + { + mov ebx, nextBlock + mov ecx, [eax] + mov [ebx], ecx + mov ecx, [eax+4] + xor ecx, 0x80000000 + mov [ebx+4], ecx + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + ret + } +} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_sign(void) +{ + __asm + { + fld qword ptr [eax] + fld st(0) + fabs + mov eax, nextBlock + fld qword ptr [g_closefact] + fadd + fdiv + fstp qword ptr [eax] + add eax, 8 + mov nextBlock, eax + sub eax, 8 + ret + } +} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_bnot(void) +{ + __asm + { + mov ebx, nextBlock + fld qword ptr [g_closefact] + fld qword ptr [eax] + fabs + fcompp + fstsw ax + shr eax, 6 + and eax, (1<<2) + add eax, offset g_cmpaddtab + fld dword ptr [eax] + fstp qword ptr [ebx] + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_if(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld qword ptr [g_closefact] + fld qword ptr [ecx] + fabs + fcompp + fstsw ax + mov ebx, nextBlock + fstp qword ptr [ebx] + fstp qword ptr [ebx+8] + shr eax, 5 + and eax, (1<<3) + add eax, ebx + fld qword ptr [eax] + fstp qword ptr [ebx] + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_equal(void) +{ + __asm + { + fld qword ptr [g_closefact] + fld qword ptr [eax] + fld qword ptr [ebx] + fsub + fabs + fcompp + fstsw ax + shr eax, 6 + and eax, (1<<2) + add eax, offset g_cmpaddtab + fld dword ptr [eax] + mov eax, nextBlock + fstp qword ptr [eax] + mov ebx, eax + add ebx, 8 + mov nextBlock, ebx + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_below(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + mov ebx, nextBlock + fcompp + fstsw ax + shr eax, 6 + and eax, (1<<2) + add eax, offset g_cmpaddtab + fld dword ptr [eax] + fstp qword ptr [ebx] + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + ret + } +} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void _asm_above(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + mov ebx, nextBlock + fcompp + fstsw ax + shr eax, 6 + and eax, (1<<2) + add eax, offset g_cmpaddtab + fld dword ptr [eax] + fstp qword ptr [ebx] + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + ret + } +} + + +__declspec ( naked ) void _asm_min(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld st(1) + mov eax, nextBlock + fld st(1) + add eax, 8 + fsub + mov nextBlock, eax + fabs // stack contains fabs(1-2),1,2 + fchs + sub eax, 8 + fadd + fadd + fld qword ptr [g_half] + fmul + fstp qword ptr [eax] + ret + } +} + +__declspec ( naked ) void _asm_max(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld st(1) + mov eax, nextBlock + fld st(1) + add eax, 8 + fsub + mov nextBlock, eax + fabs // stack contains fabs(1-2),1,2 + sub eax, 8 + fadd + fadd + fld qword ptr [g_half] + fmul + fstp qword ptr [eax] + ret + } +} diff --git a/lib/vis_milkdrop/evallib/eval.c b/lib/vis_milkdrop/evallib/eval.c new file mode 100644 index 0000000..ffb7cbb --- /dev/null +++ b/lib/vis_milkdrop/evallib/eval.c @@ -0,0 +1,238 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include +//#include +#include +#include +#include +#include +#include +#include "cal_tab.h" +#include "compiler.h" +#include "eval.h" + +#define INTCONST 1 +#define DBLCONST 2 +#define HEXCONST 3 +#define VARIABLE 4 +#define OTHER 5 + +#define strnicmp _strnicmp +#define strcmpi _strcmpi + +int yyparse(char *exp); +void llinit(void); +int gettoken(char *lltb, int lltbsiz); +char yytext[256]=""; +char expression[4096]=""; +char lastVar[256]=""; +int *errPtr; +int result; +int colCount=0; + +varType *varTable; + + +//------------------------------------------------------------------------------ +void *compileExpression(char *exp) +{ + int errv=0; + errPtr=&errv; + llinit(); + if (!yyparse(exp) && !*errPtr) + { + return (void*)result; + } + return 0; +} + +// NOTE: be sure to initialize & clean these up from your app! (InitializeCriticalSection(&g_eval_cs);) +CRITICAL_SECTION g_eval_cs; +BOOL g_eval_cs_valid; + +//------------------------------------------------------------------------------ +void resetVars(varType *vars) +{ + if (!g_eval_cs_valid) + { + g_eval_cs_valid = TRUE; +// InitializeCriticalSection(&g_eval_cs); + } + +// if (vars) EnterCriticalSection(&g_eval_cs); + varTable=vars; +// if (!vars) LeaveCriticalSection(&g_eval_cs); +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +void setLastVar(void) +{ + gettoken(lastVar, sizeof lastVar); +} + +//------------------------------------------------------------------------------ +int setVar(int varNum, double value) +{ + int i=varNum; + if (varNum < 0) + for (i=0;i= '0' && a <= '9') v+=a-'0'; + else if (a >= 'A' && a <= 'F') v+=10+a-'A'; + else if (a >= 'a' && a <= 'f') v+=10+a-'a'; + else break; + v<<=4; + } + return createCompiledValue((double)v, NULL); + } + return 0; +} + +//------------------------------------------------------------------------------ +int objectId(int nParams) +{ + switch (nParams) + { + case 1: return FUNCTION1; + case 2: return FUNCTION2; + case 3: return FUNCTION3; + } + return IDENTIFIER; +} + +//------------------------------------------------------------------------------ +int lookup(int *typeOfObject) +{ + int i; + gettoken(yytext, sizeof yytext); + for (i=0;i +#include +#include "fft.h" + +#define PI 3.141592653589793238462643383279502884197169399f + +#define SafeDeleteArray(x) { if (x) { delete [] x; x = 0; } } + + +/*****************************************************************************/ + +FFT::FFT() +{ + NFREQ = 0; + + envelope = 0; + equalize = 0; + bitrevtable = 0; + cossintable = 0; + temp1 = 0; + temp2 = 0; +} + +/*****************************************************************************/ + +FFT::~FFT() +{ + CleanUp(); +} + +/*****************************************************************************/ + +void FFT::Init(int samples_in, int samples_out, int bEqualize, float envelope_power) +{ + // samples_in: # of waveform samples you'll feed into the FFT + // samples_out: # of frequency samples you want out; MUST BE A POWER OF 2. + + CleanUp(); + + m_samples_in = samples_in; + NFREQ = samples_out*2; + + InitBitRevTable(); + InitCosSinTable(); + if (envelope_power > 0) + InitEnvelopeTable(envelope_power); + if (bEqualize) + InitEqualizeTable(); + temp1 = new float[NFREQ]; + temp2 = new float[NFREQ]; +} + +/*****************************************************************************/ + +void FFT::CleanUp() +{ + SafeDeleteArray(envelope); + SafeDeleteArray(equalize); + SafeDeleteArray(bitrevtable); + SafeDeleteArray(cossintable); + SafeDeleteArray(temp1); + SafeDeleteArray(temp2); +} + +/*****************************************************************************/ + +void FFT::InitEqualizeTable() +{ + int i; + float scaling = -0.02f; + float inv_half_nfreq = 1.0f/(float)(NFREQ/2); + + equalize = new float[NFREQ/2]; + + for (i=0; i i) + { + temp = bitrevtable[i]; + bitrevtable[i] = bitrevtable[j]; + bitrevtable[j] = temp; + } + + m = NFREQ >> 1; + + while (m >= 1 && j >= m) + { + j -= m; + m >>= 1; + } + + j += m; + } +} + +/*****************************************************************************/ + +void FFT::InitCosSinTable() +{ + + int i,dftsize,tabsize; + float theta; + + dftsize = 2; + tabsize = 0; + while (dftsize <= NFREQ) + { + tabsize++; + dftsize <<= 1; + } + + cossintable = new float[tabsize][2]; + + dftsize = 2; + i = 0; + while (dftsize <= NFREQ) + { + theta = (float)(-2.0f*PI/(float)dftsize); + cossintable[i][0] = (float)cosf(theta); + cossintable[i][1] = (float)sinf(theta); + i++; + dftsize <<= 1; + } +} + +/*****************************************************************************/ + +void FFT::time_to_frequency_domain(float *in_wavedata, float *out_spectraldata) +{ + // Converts time-domain samples from in_wavedata[] + // into frequency-domain samples in out_spectraldata[]. + // The array lengths are the two parameters to Init(). + + // The last sample of the output data will represent the frequency + // that is 1/4th of the input sampling rate. For example, + // if the input wave data is sampled at 44,100 Hz, then the last + // sample of the spectral data output will represent the frequency + // 11,025 Hz. The first sample will be 0 Hz; the frequencies of + // the rest of the samples vary linearly in between. + // Note that since human hearing is limited to the range 200 - 20,000 + // Hz. 200 is a low bass hum; 20,000 is an ear-piercing high shriek. + // Each time the frequency doubles, that sounds like going up an octave. + // That means that the difference between 200 and 300 Hz is FAR more + // than the difference between 5000 and 5100, for example! + // So, when trying to analyze bass, you'll want to look at (probably) + // the 200-800 Hz range; whereas for treble, you'll want the 1,400 - + // 11,025 Hz range. + // If you want to get 3 bands, try it this way: + // a) 11,025 / 200 = 55.125 + // b) to get the number of octaves between 200 and 11,025 Hz, solve for n: + // 2^n = 55.125 + // n = log 55.125 / log 2 + // n = 5.785 + // c) so each band should represent 5.785/3 = 1.928 octaves; the ranges are: + // 1) 200 - 200*2^1.928 or 200 - 761 Hz + // 2) 200*2^1.928 - 200*2^(1.928*2) or 761 - 2897 Hz + // 3) 200*2^(1.928*2) - 200*2^(1.928*3) or 2897 - 11025 Hz + + // A simple sine-wave-based envelope is convolved with the waveform + // data before doing the FFT, to emeliorate the bad frequency response + // of a square (i.e. nonexistent) filter. + + // You might want to slightly damp (blur) the input if your signal isn't + // of a very high quality, to reduce high-frequency noise that would + // otherwise show up in the output. + + int j, m, i, dftsize, hdftsize, t; + float wr, wi, wpi, wpr, wtemp, tempr, tempi; + + if (!bitrevtable) return; + //if (!envelope) return; + //if (!equalize) return; + if (!temp1) return; + if (!temp2) return; + if (!cossintable) return; + + // 1. set up input to the fft + if (envelope) + { + for (i=0; i> 1; + + for (m = 0; m < hdftsize; m+=1) + { + for (i = m; i < NFREQ; i+=dftsize) + { + j = i + hdftsize; + tempr = wr*real[j] - wi*imag[j]; + tempi = wr*imag[j] + wi*real[j]; + real[j] = real[i] - tempr; + imag[j] = imag[i] - tempi; + real[i] += tempr; + imag[i] += tempi; + } + + wr = (wtemp=wr)*wpr - wi*wpi; + wi = wi*wpr + wtemp*wpi; + } + + dftsize <<= 1; + t++; + } + + // 3. take the magnitude & equalize it (on a log10 scale) for output + if (equalize) + for (i=0; i +#include +//#include +//#include +#include +#include +#include +//#include + + + +#define D3DCOLOR_RGBA_01(r,g,b,a) D3DCOLOR_RGBA(((int)(r*255)),((int)(g*255)),((int)(b*255)),((int)(a*255))) +#define FRAND ((rand() % 7381)/7380.0f) +//#define D3D_OVERLOADS + +#define VERT_CLIP 0.75f // warning: top/bottom can get clipped if you go < 0.65! + +//extern CPlugin* g_plugin; // declared in main.cpp +//extern bool g_bDebugOutput; // declared in support.cpp + +int g_title_font_sizes[] = +{ + // NOTE: DO NOT EXCEED 64 FONTS HERE. + 6, 8, 10, 12, 14, 16, + 20, 26, 32, 38, 44, 50, 56, + 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, + 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, + 480, 512 /**/ +}; + +//#define COMPILE_MULTIMON_STUBS 1 +//#include + +// This function evaluates whether the floating-point +// control Word is set to single precision/round to nearest/ +// exceptions disabled. If not, the +// function changes the control Word to set them and returns +// TRUE, putting the old control Word value in the passback +// location pointed to by pwOldCW. +BOOL MungeFPCW( WORD *pwOldCW ) +{ + BOOL ret = FALSE; + WORD wTemp, wSave; + + __asm fstcw wSave + if (wSave & 0x300 || // Not single mode + 0x3f != (wSave & 0x3f) || // Exceptions enabled + wSave & 0xC00) // Not round to nearest mode + { + __asm + { + mov ax, wSave + and ax, not 300h ;; single mode + or ax, 3fh ;; disable all exceptions + and ax, not 0xC00 ;; round to nearest mode + mov wTemp, ax + fldcw wTemp + } + ret = TRUE; + } + if (pwOldCW) *pwOldCW = wSave; + return ret; +} + + +void RestoreFPCW(WORD wSave) +{ + __asm fldcw wSave +} + +int GetNumToSpawn(float fTime, float fDeltaT, float fRate, float fRegularity, int iNumSpawnedSoFar) +{ + // PARAMETERS + // ------------ + // fTime: sum of all fDeltaT's so far (excluding this one) + // fDeltaT: time window for this frame + // fRate: avg. rate (spawns per second) of generation + // fRegularity: regularity of generation + // 0.0: totally chaotic + // 0.2: getting chaotic / very jittered + // 0.4: nicely jittered + // 0.6: slightly jittered + // 0.8: almost perfectly regular + // 1.0: perfectly regular + // iNumSpawnedSoFar: the total number of spawnings so far + // + // RETURN VALUE + // ------------ + // The number to spawn for this frame (add this to your net count!). + // + // COMMENTS + // ------------ + // The spawn values returned will, over time, match + // (within 1%) the theoretical totals expected based on the + // amount of time passed and the average generation rate. + // + // UNRESOLVED ISSUES + // ----------------- + // actual results of mixed gen. (0 < reg < 1) are about 1% too low + // in the long run (vs. analytical expectations). Decided not + // to bother fixing it since it's only 1% (and VERY consistent). + + + float fNumToSpawnReg; + float fNumToSpawnIrreg; + float fNumToSpawn; + + // compute # spawned based on regular generation + fNumToSpawnReg = ((fTime + fDeltaT) * fRate) - iNumSpawnedSoFar; + + // compute # spawned based on irregular (random) generation + if (fDeltaT <= 1.0f / fRate) + { + // case 1: avg. less than 1 spawn per frame + if ((rand() % 16384)/16384.0f < fDeltaT * fRate) + fNumToSpawnIrreg = 1.0f; + else + fNumToSpawnIrreg = 0.0f; + } + else + { + // case 2: avg. more than 1 spawn per frame + fNumToSpawnIrreg = fDeltaT * fRate; + fNumToSpawnIrreg *= 2.0f*(rand() % 16384)/16384.0f; + } + + // get linear combo. of regular & irregular + fNumToSpawn = fNumToSpawnReg*fRegularity + fNumToSpawnIrreg*(1.0f - fRegularity); + + // round to nearest integer for result + return (int)(fNumToSpawn + 0.49f); +} + + +/* +char szHelp[] = +{ + // note: this is a string-of-null-terminated-strings; the whole thing ends with a double null termination. + // each substring will be drawn on its own line, and the strings are drawn in BOTTOM-UP order.. + // (this is just an effort to keep the file size low) + "ESC: exit\0" + + " \0" + "F9: toggle stereo 3D mode\0" + "F8: change directory/drive\0" + "F7: refresh milk_msg.ini\0" + "F6: show preset rating\0" + "F5: show fps\0" + "F4: show preset name\0" + "F2,F3: show song title,length\0" + "F1: show help\0" + + " \0" + "N: show per-frame variable moNitor\0" + "S: save preset\0" + "M: (preset editing) menu\0" + + " \0" + "scroll lock: locks current preset\0" + "+/-: rate current preset\0" + "L: load specific preset\0" + "R: toggle random(/sequential) preset order\0" + "H: instant Hard cut (to next preset)\0" + "spacebar: transition to next preset\0" + + " \0" + "left/right arrows: seek 5 sec. [+SHIFT=seek 30]\0" + "up/down arrows: adjust volume\0" + "P: playlist\0" + "U: toggle shuffle\0" + "z/x/c/v/b: prev/play/pause/stop/next\0" + + " \0" + "Y/K: enter custom message/sprite mode [see docs!]\0" + "##: show custom message/sprite (##=00-99)\0" + "T: launch song title animation\0" + + "\0\0" +}; +*/ + + +bool CPlugin::OnResizeTextWindow() +{ + /* + if (!m_hTextWnd) + return false; + + RECT rect; + GetClientRect(m_hTextWnd, &rect); + + if (rect.right - rect.left != m_nTextWndWidth || + rect.bottom - rect.top != m_nTextWndHeight) + { + m_nTextWndWidth = rect.right - rect.left; + m_nTextWndHeight = rect.bottom - rect.top; + + // first, resize fonts if necessary + //if (!InitFont()) + //return false; + + // then resize the memory bitmap used for double buffering + if (m_memDC) + { + SelectObject(m_memDC, m_oldBM); // delete our doublebuffer + DeleteObject(m_memDC); + DeleteObject(m_memBM); + m_memDC = NULL; + m_memBM = NULL; + m_oldBM = NULL; + } + + HDC hdc = GetDC(m_hTextWnd); + if (!hdc) return false; + + m_memDC = CreateCompatibleDC(hdc); + m_memBM = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top); + m_oldBM = (HBITMAP)SelectObject(m_memDC,m_memBM); + + ReleaseDC(m_hTextWnd, hdc); + + // save new window pos + WriteRealtimeConfig(); + }*/ + + return true; +} + + +void CPlugin::ClearGraphicsWindow() +{ + // clear the window contents, to avoid a 1-pixel-thick border of noise that sometimes sticks around + /* + RECT rect; + GetClientRect(GetPluginWindow(), &rect); + + HDC hdc = GetDC(GetPluginWindow()); + FillRect(hdc, &rect, m_hBlackBrush); + ReleaseDC(GetPluginWindow(), hdc); + */ +} + +/* +bool CPlugin::OnResizeGraphicsWindow() +{ + // NO LONGER NEEDED, SINCE PLUGIN SHELL CREATES A NEW DIRECTX + // OBJECT WHENEVER WINDOW IS RESIZED. +} +*/ + +bool CPlugin::RenderStringToTitleTexture() // m_szSongMessage +{ +#if 0 + if (!m_lpDDSTitle) // this *can* be NULL, if not much video mem! + return false; + + if (m_supertext.szText[0]==0) + return false; + + LPDIRECT3DDEVICE8 lpDevice = GetDevice(); + if (!lpDevice) + return false; + + char szTextToDraw[512]; + sprintf(szTextToDraw, " %s ", m_supertext.szText); //add a space @ end for italicized fonts; and at start, too, because it's centered! + + // Remember the original backbuffer and zbuffer + LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer; + lpDevice->GetRenderTarget( &pBackBuffer ); +// lpDevice->GetDepthStencilSurface( &pZBuffer ); + + // set render target to m_lpDDSTitle + { + lpDevice->SetTexture(0, NULL); + + IDirect3DSurface8* pNewTarget = NULL; + if (m_lpDDSTitle->GetSurfaceLevel(0, &pNewTarget) != D3D_OK) + { + SafeRelease(pBackBuffer); +// SafeRelease(pZBuffer); + return false; + } + lpDevice->SetRenderTarget(pNewTarget, NULL); + pNewTarget->Release(); + + lpDevice->SetTexture(0, NULL); + } + + // clear the texture to black + { + lpDevice->SetVertexShader( WFVERTEX_FORMAT ); + lpDevice->SetTexture(0, NULL); + + lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + + // set up a quad + WFVERTEX verts[4]; + for (int i=0; i<4; i++) + { + verts[i].x = (i%2==0) ? -1 : 1; + verts[i].y = (i/2==0) ? -1 : 1; + verts[i].z = 0; + verts[i].Diffuse = 0xFF000000; + } + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(WFVERTEX)); + } + + /*// 1. clip title if too many chars + if (m_supertext.bIsSongTitle) + { + // truncate song title if too long; don't clip custom messages, though! + int clip_chars = 32; + int user_title_size = GetFontHeight(SONGTITLE_FONT); + + #define MIN_CHARS 8 // max clip_chars *for BIG FONTS* + #define MAX_CHARS 64 // max clip chars *for tiny fonts* + float t = (user_title_size-10)/(float)(128-10); + t = min(1,max(0,t)); + clip_chars = (int)(MAX_CHARS - (MAX_CHARS-MIN_CHARS)*t); + + if ((int)strlen(szTextToDraw) > clip_chars+3) + lstrcpy(&szTextToDraw[clip_chars], "..."); + }*/ + + bool ret = true; + + // use 2 lines; must leave room for bottom of 'g' characters and such! + RECT rect; + rect.left = 0; + rect.right = m_nTitleTexSizeX; + rect.top = m_nTitleTexSizeY* 1/21; // otherwise, top of '%' could be cut off (1/21 seems safe) + rect.bottom = m_nTitleTexSizeY*17/21; // otherwise, bottom of 'g' could be cut off (18/21 seems safe, but we want some leeway) + + if (!m_supertext.bIsSongTitle) + { + // custom msg -> pick font to use that will best fill the texture + + HFONT gdi_font = NULL; + LPD3DXFONT d3dx_font = NULL; + + int lo = 0; + int hi = sizeof(g_title_font_sizes)/sizeof(int) - 1; + + // limit the size of the font used: + + //int user_title_size = GetFontHeight(SONGTITLE_FONT); + //while (g_title_font_sizes[hi] > user_title_size*2 && hi>4) + // hi--; + + RECT temp; + while (1)//(lo < hi-1) + { + int mid = (lo+hi)/2; + + // create new gdi font at 'mid' size: + gdi_font = CreateFont(g_title_font_sizes[mid], 0, 0, 0, m_supertext.bBold ? 900 : 400, m_supertext.bItal, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, m_fontinfo[SONGTITLE_FONT].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, DEFAULT_PITCH, m_supertext.nFontFace); + if (gdi_font) + { + // create new d3dx font at 'mid' size: + if (D3DXCreateFont(lpDevice, gdi_font, &d3dx_font) == D3D_OK) + { + if (lo == hi-1) + break; // DONE; but the 'lo'-size font is ready for use! + + // compute size of text if drawn w/font of THIS size: + temp = rect; + int h = d3dx_font->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX, 0xFFFFFFFF); + + // adjust & prepare to reiterate: + if (temp.right >= rect.right || h > rect.bottom-rect.top) + hi = mid; + else + lo = mid; + + SafeRelease(d3dx_font); + } + + DeleteObject(gdi_font); gdi_font=NULL; + } + } + + if (gdi_font && d3dx_font) + { + // do actual drawing + set m_supertext.nFontSizeUsed; use 'lo' size + int h = d3dx_font->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX | DT_CENTER, 0xFFFFFFFF); + temp.left = 0; + temp.right = m_nTitleTexSizeX; // now allow text to go all the way over, since we're actually drawing! + temp.top = m_nTitleTexSizeY/2 - h/2; + temp.bottom = m_nTitleTexSizeY/2 + h/2; + m_supertext.nFontSizeUsed = d3dx_font->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_NOPREFIX | DT_CENTER, 0xFFFFFFFF); + + ret = true; + } + else + { + ret = false; + } + + // clean up font: + SafeRelease(d3dx_font); + if (gdi_font) DeleteObject(gdi_font); gdi_font=NULL; + } + else // song title + { + RECT temp = rect; + + // do actual drawing + set m_supertext.nFontSizeUsed; use 'lo' size + int h = m_d3dx_title_font_doublesize->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX | DT_CENTER | DT_END_ELLIPSIS, 0xFFFFFFFF); + temp.left = 0; + temp.right = m_nTitleTexSizeX; // now allow text to go all the way over, since we're actually drawing! + temp.top = m_nTitleTexSizeY/2 - h/2; + temp.bottom = m_nTitleTexSizeY/2 + h/2; + m_supertext.nFontSizeUsed = m_d3dx_title_font_doublesize->DrawText(szTextToDraw, -1, &temp, DT_SINGLELINE | DT_NOPREFIX | DT_CENTER | DT_END_ELLIPSIS, 0xFFFFFFFF); + } + + // Change the rendertarget back to the original setup + lpDevice->SetTexture(0, NULL); + lpDevice->SetRenderTarget( pBackBuffer, NULL ); + SafeRelease(pBackBuffer); + SafeRelease(pZBuffer); + + return ret; +#endif + return false; +} + +void CPlugin::LoadPerFrameEvallibVars(CState* pState) +{ + // load the 'var_pf_*' variables in this CState object with the correct values. + // for vars that affect pixel motion, that means evaluating them at time==-1, + // (i.e. no blending w/blendto value); the blending of the file dx/dy + // will be done *after* execution of the per-vertex code. + // for vars that do NOT affect pixel motion, evaluate them at the current time, + // so that if they're blending, both states see the blended value. + + // 1. vars that affect pixel motion: (eval at time==-1) + *pState->var_pf_zoom = (double)pState->m_fZoom.eval(-1);//GetTime()); + *pState->var_pf_zoomexp = (double)pState->m_fZoomExponent.eval(-1);//GetTime()); + *pState->var_pf_rot = (double)pState->m_fRot.eval(-1);//GetTime()); + *pState->var_pf_warp = (double)pState->m_fWarpAmount.eval(-1);//GetTime()); + *pState->var_pf_cx = (double)pState->m_fRotCX.eval(-1);//GetTime()); + *pState->var_pf_cy = (double)pState->m_fRotCY.eval(-1);//GetTime()); + *pState->var_pf_dx = (double)pState->m_fXPush.eval(-1);//GetTime()); + *pState->var_pf_dy = (double)pState->m_fYPush.eval(-1);//GetTime()); + *pState->var_pf_sx = (double)pState->m_fStretchX.eval(-1);//GetTime()); + *pState->var_pf_sy = (double)pState->m_fStretchY.eval(-1);//GetTime()); + // read-only: + *pState->var_pf_time = (double)(GetTime() - m_fStartTime); + *pState->var_pf_fps = (double)GetFps(); + *pState->var_pf_bass = (double)mysound.imm_rel[0]; + *pState->var_pf_mid = (double)mysound.imm_rel[1]; + *pState->var_pf_treb = (double)mysound.imm_rel[2]; + *pState->var_pf_bass_att = (double)mysound.avg_rel[0]; + *pState->var_pf_mid_att = (double)mysound.avg_rel[1]; + *pState->var_pf_treb_att = (double)mysound.avg_rel[2]; + *pState->var_pf_frame = (double)GetFrame(); + //*pState->var_pf_monitor = 0; -leave this as it was set in the per-frame INIT code! + *pState->var_pf_q1 = pState->q_values_after_init_code[0];//0.0f; + *pState->var_pf_q2 = pState->q_values_after_init_code[1];//0.0f; + *pState->var_pf_q3 = pState->q_values_after_init_code[2];//0.0f; + *pState->var_pf_q4 = pState->q_values_after_init_code[3];//0.0f; + *pState->var_pf_q5 = pState->q_values_after_init_code[4];//0.0f; + *pState->var_pf_q6 = pState->q_values_after_init_code[5];//0.0f; + *pState->var_pf_q7 = pState->q_values_after_init_code[6];//0.0f; + *pState->var_pf_q8 = pState->q_values_after_init_code[7];//0.0f; + *pState->var_pf_monitor = pState->monitor_after_init_code; + *pState->var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime); + + // 2. vars that do NOT affect pixel motion: (eval at time==now) + *pState->var_pf_decay = (double)pState->m_fDecay.eval(GetTime()); + *pState->var_pf_wave_a = (double)pState->m_fWaveAlpha.eval(GetTime()); + *pState->var_pf_wave_r = (double)pState->m_fWaveR.eval(GetTime()); + *pState->var_pf_wave_g = (double)pState->m_fWaveG.eval(GetTime()); + *pState->var_pf_wave_b = (double)pState->m_fWaveB.eval(GetTime()); + *pState->var_pf_wave_x = (double)pState->m_fWaveX.eval(GetTime()); + *pState->var_pf_wave_y = (double)pState->m_fWaveY.eval(GetTime()); + *pState->var_pf_wave_mystery= (double)pState->m_fWaveParam.eval(GetTime()); + *pState->var_pf_wave_mode = (double)pState->m_nWaveMode; //?!?! -why won't it work if set to pState->m_nWaveMode??? + *pState->var_pf_ob_size = (double)pState->m_fOuterBorderSize.eval(GetTime()); + *pState->var_pf_ob_r = (double)pState->m_fOuterBorderR.eval(GetTime()); + *pState->var_pf_ob_g = (double)pState->m_fOuterBorderG.eval(GetTime()); + *pState->var_pf_ob_b = (double)pState->m_fOuterBorderB.eval(GetTime()); + *pState->var_pf_ob_a = (double)pState->m_fOuterBorderA.eval(GetTime()); + *pState->var_pf_ib_size = (double)pState->m_fInnerBorderSize.eval(GetTime()); + *pState->var_pf_ib_r = (double)pState->m_fInnerBorderR.eval(GetTime()); + *pState->var_pf_ib_g = (double)pState->m_fInnerBorderG.eval(GetTime()); + *pState->var_pf_ib_b = (double)pState->m_fInnerBorderB.eval(GetTime()); + *pState->var_pf_ib_a = (double)pState->m_fInnerBorderA.eval(GetTime()); + *pState->var_pf_mv_x = (double)pState->m_fMvX.eval(GetTime()); + *pState->var_pf_mv_y = (double)pState->m_fMvY.eval(GetTime()); + *pState->var_pf_mv_dx = (double)pState->m_fMvDX.eval(GetTime()); + *pState->var_pf_mv_dy = (double)pState->m_fMvDY.eval(GetTime()); + *pState->var_pf_mv_l = (double)pState->m_fMvL.eval(GetTime()); + *pState->var_pf_mv_r = (double)pState->m_fMvR.eval(GetTime()); + *pState->var_pf_mv_g = (double)pState->m_fMvG.eval(GetTime()); + *pState->var_pf_mv_b = (double)pState->m_fMvB.eval(GetTime()); + *pState->var_pf_mv_a = (double)pState->m_fMvA.eval(GetTime()); + *pState->var_pf_echo_zoom = (double)pState->m_fVideoEchoZoom.eval(GetTime()); + *pState->var_pf_echo_alpha = (double)pState->m_fVideoEchoAlpha.eval(GetTime()); + *pState->var_pf_echo_orient = (double)pState->m_nVideoEchoOrientation; + // new in v1.04: + *pState->var_pf_wave_usedots = (double)pState->m_bWaveDots; + *pState->var_pf_wave_thick = (double)pState->m_bWaveThick; + *pState->var_pf_wave_additive = (double)pState->m_bAdditiveWaves; + *pState->var_pf_wave_brighten = (double)pState->m_bMaximizeWaveColor; + *pState->var_pf_darken_center = (double)pState->m_bDarkenCenter; + *pState->var_pf_gamma = (double)pState->m_fGammaAdj.eval(GetTime()); + *pState->var_pf_wrap = (double)pState->m_bTexWrap; + *pState->var_pf_invert = (double)pState->m_bInvert; + *pState->var_pf_brighten = (double)pState->m_bBrighten; + *pState->var_pf_darken = (double)pState->m_bDarken; + *pState->var_pf_solarize = (double)pState->m_bSolarize; + *pState->var_pf_meshx = (double)m_nGridX; + *pState->var_pf_meshy = (double)m_nGridY; +} + +void CPlugin::RunPerFrameEquations() +{ + // run per-frame calculations + + int num_reps = (m_pState->m_bBlending) ? 2 : 1; + for (int rep=0; repvar_pv_time = *pState->var_pf_time; + *pState->var_pv_fps = *pState->var_pf_fps; + *pState->var_pv_frame = *pState->var_pf_frame; + *pState->var_pv_progress = *pState->var_pf_progress; + *pState->var_pv_bass = *pState->var_pf_bass; + *pState->var_pv_mid = *pState->var_pf_mid; + *pState->var_pv_treb = *pState->var_pf_treb; + *pState->var_pv_bass_att = *pState->var_pf_bass_att; + *pState->var_pv_mid_att = *pState->var_pf_mid_att; + *pState->var_pv_treb_att = *pState->var_pf_treb_att; + *pState->var_pv_meshx = (double)m_nGridX; + *pState->var_pv_meshy = (double)m_nGridY; + //*pState->var_pv_monitor = *pState->var_pf_monitor; + + // execute once-per-frame expressions: +#ifndef _NO_EXPR_ + if (pState->m_pf_codehandle) + { + resetVars(pState->m_pf_vars); + if (pState->m_pf_codehandle) + { + executeCode(pState->m_pf_codehandle); + } + resetVars(NULL); + } +#endif + + // save some things for next frame: + pState->monitor_after_init_code = *pState->var_pf_monitor; + + // save some things for per-vertex code: + *pState->var_pv_q1 = *pState->var_pf_q1; + *pState->var_pv_q2 = *pState->var_pf_q2; + *pState->var_pv_q3 = *pState->var_pf_q3; + *pState->var_pv_q4 = *pState->var_pf_q4; + *pState->var_pv_q5 = *pState->var_pf_q5; + *pState->var_pv_q6 = *pState->var_pf_q6; + *pState->var_pv_q7 = *pState->var_pf_q7; + *pState->var_pv_q8 = *pState->var_pf_q8; + + // (a few range checks:) + *pState->var_pf_gamma = max(0 , min( 8, *pState->var_pf_gamma )); + *pState->var_pf_echo_zoom = max(0.001, min( 1000, *pState->var_pf_echo_zoom)); + + if (m_pState->m_bRedBlueStereo || m_bAlways3D) + { + // override wave colors + *pState->var_pf_wave_r = 0.35f*(*pState->var_pf_wave_r) + 0.65f; + *pState->var_pf_wave_g = 0.35f*(*pState->var_pf_wave_g) + 0.65f; + *pState->var_pf_wave_b = 0.35f*(*pState->var_pf_wave_b) + 0.65f; + } + } + + if (m_pState->m_bBlending) + { + // For all variables that do NOT affect pixel motion, blend them NOW, + // so later the user can just access m_pState->m_pf_whatever. + double mix = (double)CosineInterp(m_pState->m_fBlendProgress); + double mix2 = 1.0 - mix; + *m_pState->var_pf_decay = mix*(*m_pState->var_pf_decay ) + mix2*(*m_pOldState->var_pf_decay ); + *m_pState->var_pf_wave_a = mix*(*m_pState->var_pf_wave_a ) + mix2*(*m_pOldState->var_pf_wave_a ); + *m_pState->var_pf_wave_r = mix*(*m_pState->var_pf_wave_r ) + mix2*(*m_pOldState->var_pf_wave_r ); + *m_pState->var_pf_wave_g = mix*(*m_pState->var_pf_wave_g ) + mix2*(*m_pOldState->var_pf_wave_g ); + *m_pState->var_pf_wave_b = mix*(*m_pState->var_pf_wave_b ) + mix2*(*m_pOldState->var_pf_wave_b ); + *m_pState->var_pf_wave_x = mix*(*m_pState->var_pf_wave_x ) + mix2*(*m_pOldState->var_pf_wave_x ); + *m_pState->var_pf_wave_y = mix*(*m_pState->var_pf_wave_y ) + mix2*(*m_pOldState->var_pf_wave_y ); + *m_pState->var_pf_wave_mystery = mix*(*m_pState->var_pf_wave_mystery) + mix2*(*m_pOldState->var_pf_wave_mystery); + // wave_mode: exempt (integer) + *m_pState->var_pf_ob_size = mix*(*m_pState->var_pf_ob_size ) + mix2*(*m_pOldState->var_pf_ob_size ); + *m_pState->var_pf_ob_r = mix*(*m_pState->var_pf_ob_r ) + mix2*(*m_pOldState->var_pf_ob_r ); + *m_pState->var_pf_ob_g = mix*(*m_pState->var_pf_ob_g ) + mix2*(*m_pOldState->var_pf_ob_g ); + *m_pState->var_pf_ob_b = mix*(*m_pState->var_pf_ob_b ) + mix2*(*m_pOldState->var_pf_ob_b ); + *m_pState->var_pf_ob_a = mix*(*m_pState->var_pf_ob_a ) + mix2*(*m_pOldState->var_pf_ob_a ); + *m_pState->var_pf_ib_size = mix*(*m_pState->var_pf_ib_size ) + mix2*(*m_pOldState->var_pf_ib_size ); + *m_pState->var_pf_ib_r = mix*(*m_pState->var_pf_ib_r ) + mix2*(*m_pOldState->var_pf_ib_r ); + *m_pState->var_pf_ib_g = mix*(*m_pState->var_pf_ib_g ) + mix2*(*m_pOldState->var_pf_ib_g ); + *m_pState->var_pf_ib_b = mix*(*m_pState->var_pf_ib_b ) + mix2*(*m_pOldState->var_pf_ib_b ); + *m_pState->var_pf_ib_a = mix*(*m_pState->var_pf_ib_a ) + mix2*(*m_pOldState->var_pf_ib_a ); + *m_pState->var_pf_mv_x = mix*(*m_pState->var_pf_mv_x ) + mix2*(*m_pOldState->var_pf_mv_x ); + *m_pState->var_pf_mv_y = mix*(*m_pState->var_pf_mv_y ) + mix2*(*m_pOldState->var_pf_mv_y ); + *m_pState->var_pf_mv_dx = mix*(*m_pState->var_pf_mv_dx ) + mix2*(*m_pOldState->var_pf_mv_dx ); + *m_pState->var_pf_mv_dy = mix*(*m_pState->var_pf_mv_dy ) + mix2*(*m_pOldState->var_pf_mv_dy ); + *m_pState->var_pf_mv_l = mix*(*m_pState->var_pf_mv_l ) + mix2*(*m_pOldState->var_pf_mv_l ); + *m_pState->var_pf_mv_r = mix*(*m_pState->var_pf_mv_r ) + mix2*(*m_pOldState->var_pf_mv_r ); + *m_pState->var_pf_mv_g = mix*(*m_pState->var_pf_mv_g ) + mix2*(*m_pOldState->var_pf_mv_g ); + *m_pState->var_pf_mv_b = mix*(*m_pState->var_pf_mv_b ) + mix2*(*m_pOldState->var_pf_mv_b ); + *m_pState->var_pf_mv_a = mix*(*m_pState->var_pf_mv_a ) + mix2*(*m_pOldState->var_pf_mv_a ); + *m_pState->var_pf_echo_zoom = mix*(*m_pState->var_pf_echo_zoom ) + mix2*(*m_pOldState->var_pf_echo_zoom ); + *m_pState->var_pf_echo_alpha = mix*(*m_pState->var_pf_echo_alpha ) + mix2*(*m_pOldState->var_pf_echo_alpha ); + *m_pState->var_pf_echo_orient = (mix < 0.5f) ? *m_pOldState->var_pf_echo_orient : *m_pState->var_pf_echo_orient; + // added in v1.04: + *m_pState->var_pf_wave_usedots = (mix < 0.5f) ? *m_pOldState->var_pf_wave_usedots : *m_pState->var_pf_wave_usedots ; + *m_pState->var_pf_wave_thick = (mix < 0.5f) ? *m_pOldState->var_pf_wave_thick : *m_pState->var_pf_wave_thick ; + *m_pState->var_pf_wave_additive= (mix < 0.5f) ? *m_pOldState->var_pf_wave_additive : *m_pState->var_pf_wave_additive; + *m_pState->var_pf_wave_brighten= (mix < 0.5f) ? *m_pOldState->var_pf_wave_brighten : *m_pState->var_pf_wave_brighten; + *m_pState->var_pf_darken_center= (mix < 0.5f) ? *m_pOldState->var_pf_darken_center : *m_pState->var_pf_darken_center; + *m_pState->var_pf_gamma = mix*(*m_pState->var_pf_gamma ) + mix2*(*m_pOldState->var_pf_gamma ); + *m_pState->var_pf_wrap = (mix < 0.5f) ? *m_pOldState->var_pf_wrap : *m_pState->var_pf_wrap ; + *m_pState->var_pf_invert = (mix < 0.5f) ? *m_pOldState->var_pf_invert : *m_pState->var_pf_invert ; + *m_pState->var_pf_brighten = (mix < 0.5f) ? *m_pOldState->var_pf_brighten : *m_pState->var_pf_brighten ; + *m_pState->var_pf_darken = (mix < 0.5f) ? *m_pOldState->var_pf_darken : *m_pState->var_pf_darken ; + *m_pState->var_pf_solarize = (mix < 0.5f) ? *m_pOldState->var_pf_solarize : *m_pState->var_pf_solarize ; + } +} + +void CPlugin::RenderFrame(int bRedraw) +{ + int i; + + float fDeltaT = 1.0f/GetFps(); + + // update time + /* + float fDeltaT = (GetFrame()==0) ? 1.0f/30.0f : GetTime() - m_prev_time; + DWORD dwTime = GetTickCount(); + float fDeltaT = (dwTime - m_dwPrevTickCount)*0.001f; + if (GetFrame() > 64) + { + fDeltaT = (fDeltaT)*0.2f + 0.8f*(1.0f/m_fps); + if (fDeltaT > 2.0f/m_fps) + { + char buf[64]; + sprintf(buf, "fixing time gap of %5.3f seconds", fDeltaT); + dumpmsg(buf); + + fDeltaT = 1.0f/m_fps; + } + } + m_dwPrevTickCount = dwTime; + GetTime() += fDeltaT; + */ + + if (GetFrame()==0) + { + m_fStartTime = GetTime(); + m_fPresetStartTime = GetTime(); + } + + if (m_fNextPresetTime < 0) + { + float dt = m_fTimeBetweenPresetsRand * (rand()%1000)*0.001f; + m_fNextPresetTime = GetTime() + m_fBlendTimeAuto + m_fTimeBetweenPresets + dt; + } + + /* + if (m_bPresetLockedByUser || m_bPresetLockedByCode) + { + // if the user has the preset LOCKED, or if they're in the middle of + // saving it, then keep extending the time at which the auto-switch will occur + // (by the length of this frame). + + m_fPresetStartTime += fDeltaT; + m_fNextPresetTime += fDeltaT; + }*/ + + // update fps + /* + if (GetFrame() < 4) + { + m_fps = 0.0f; + } + else if (GetFrame() <= 64) + { + m_fps = GetFrame() / (float)(GetTime() - m_fTimeHistory[0]); + } + else + { + m_fps = 64.0f / (float)(GetTime() - m_fTimeHistory[m_nTimeHistoryPos]); + } + m_fTimeHistory[m_nTimeHistoryPos] = GetTime(); + m_nTimeHistoryPos = (m_nTimeHistoryPos + 1) % 64; + */ + + // limit fps, if necessary + /* + if (m_nFpsLimit > 0 && (GetFrame() % 64) == 0 && GetFrame() > 64) + { + float spf_now = 1.0f / m_fps; + float spf_desired = 1.0f / (float)m_nFpsLimit; + + float new_sleep = m_fFPSLimitSleep + (spf_desired - spf_now)*1000.0f; + + if (GetFrame() <= 128) + m_fFPSLimitSleep = new_sleep; + else + m_fFPSLimitSleep = m_fFPSLimitSleep*0.8f + 0.2f*new_sleep; + + if (m_fFPSLimitSleep < 0) m_fFPSLimitSleep = 0; + if (m_fFPSLimitSleep > 100) m_fFPSLimitSleep = 100; + + //sprintf(m_szUserMessage, "sleep=%f", m_fFPSLimitSleep); + //m_fShowUserMessageUntilThisTime = GetTime() + 3.0f; + } + + static float deficit; + if (GetFrame()==0) deficit = 0; + float ideal_sleep = (m_fFPSLimitSleep + deficit); + int actual_sleep = (int)ideal_sleep; + if (actual_sleep > 0) + Sleep(actual_sleep); + deficit = ideal_sleep - actual_sleep; + if (deficit < 0) deficit = 0; // just in case + if (deficit > 1) deficit = 1; // just in case + */ + + // randomly change the preset, if it's time + if (m_fNextPresetTime < GetTime()) + { + LoadRandomPreset(m_fBlendTimeAuto); + } +/* + // randomly spawn Song Title, if time + if (m_fTimeBetweenRandomSongTitles > 0 && + !m_supertext.bRedrawSuperText && + GetTime() >= m_supertext.fStartTime + m_supertext.fDuration + 1.0f/GetFps()) + { + int n = GetNumToSpawn(GetTime(), fDeltaT, 1.0f/m_fTimeBetweenRandomSongTitles, 0.5f, m_nSongTitlesSpawned); + if (n > 0) + { + LaunchSongTitleAnim(); + m_nSongTitlesSpawned += n; + } + } + + // randomly spawn Custom Message, if time + if (m_fTimeBetweenRandomCustomMsgs > 0 && + !m_supertext.bRedrawSuperText && + GetTime() >= m_supertext.fStartTime + m_supertext.fDuration + 1.0f/GetFps()) + { + int n = GetNumToSpawn(GetTime(), fDeltaT, 1.0f/m_fTimeBetweenRandomCustomMsgs, 0.5f, m_nCustMsgsSpawned); + if (n > 0) + { + LaunchCustomMessage(-1); + m_nCustMsgsSpawned += n; + } + } +*/ + // update m_fBlendProgress; + if (m_pState->m_bBlending) + { + m_pState->m_fBlendProgress = (GetTime() - m_pState->m_fBlendStartTime) / m_pState->m_fBlendDuration; + if (m_pState->m_fBlendProgress > 1.0f) + { + m_pState->m_bBlending = false; + } + } + + // handle hard cuts here (just after new sound analysis) + static float m_fHardCutThresh; + if (GetFrame() == 0) + m_fHardCutThresh = m_fHardCutLoudnessThresh*2.0f; + if (GetFps() > 1.0f && !m_bHardCutsDisabled && !m_bPresetLockedByUser && !m_bPresetLockedByCode) + { + if (mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2] > m_fHardCutThresh*3.0f) + { + LoadRandomPreset(0.0f); + m_fHardCutThresh *= 2.0f; + } + else + { + float halflife_modified = m_fHardCutHalflife*0.5f; + //thresh = (thresh - 1.5f)*0.99f + 1.5f; + float k = -0.69315f / halflife_modified; + float single_frame_multiplier = powf(2.7183f, k / GetFps()); + m_fHardCutThresh = (m_fHardCutThresh - m_fHardCutLoudnessThresh)*single_frame_multiplier + m_fHardCutLoudnessThresh; + } + } + + // smooth & scale the audio data, according to m_state, for display purposes + float scale = m_pState->m_fWaveScale.eval(GetTime()) / 128.0f; + mysound.fWave[0][0] *= scale; + mysound.fWave[1][0] *= scale; + float mix2 = m_pState->m_fWaveSmoothing.eval(GetTime()); + float mix1 = scale*(1.0f - mix2); + for (i=1; i<576; i++) + { + mysound.fWave[0][i] = mysound.fWave[0][i]*mix1 + mysound.fWave[0][i-1]*mix2; + mysound.fWave[1][i] = mysound.fWave[1][i]*mix1 + mysound.fWave[1][i-1]*mix2; + } + + RunPerFrameEquations(); + + // restore any lost surfaces + //m_lpDD->RestoreAllSurfaces(); + + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + // Remember the original backbuffer and zbuffer + LPDIRECT3DSURFACE9 pBackBuffer, pZBuffer; + lpDevice->GetRenderTarget(0, &pBackBuffer ); + lpDevice->GetDepthStencilSurface( &pZBuffer ); + + D3DSURFACE_DESC desc; + pBackBuffer->GetDesc(&desc); + + m_backBufferWidth = desc.Width; + m_backBufferHeight = desc.Height; + + // set up render state + { + DWORD texaddr = (*m_pState->var_pf_wrap) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP; + lpDevice->SetRenderState(D3DRS_WRAP0, 0); + lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, texaddr); + lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, texaddr); + lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, texaddr); + + lpDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD ); + lpDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE ); + lpDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); + lpDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); + lpDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); + lpDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); + lpDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE ); + lpDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + lpDevice->SetRenderState( D3DRS_AMBIENT, 0xFFFFFFFF ); //? +// lpDevice->SetRenderState( D3DRS_CLIPPING, TRUE ); + + // set min/mag/mip filtering modes; use anisotropy if available. + if (m_bAnisotropicFiltering && (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)) + lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); +// else if (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) + else + lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); +// else +// SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT); + + if (m_bAnisotropicFiltering && (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)) + lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); + else +// else if (GetCaps()->TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) + lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + // else +// SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + + lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); + + // note: this texture stage state setup works for 0 or 1 texture. + // if you set a texture, it will be modulated with the current diffuse color. + // if you don't set a texture, it will just use the current diffuse color. + lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER) + lpDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE); + /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES) + lpDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);*/ + + // NOTE: don't forget to call SetTexture and SetVertexShader before drawing! + // Examples: + // SPRITEVERTEX verts[4]; // has texcoords + // lpDevice->SetTexture(0, m_sprite_tex); + // lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT ); + // + // WFVERTEX verts[4]; // no texcoords + // lpDevice->SetTexture(0, NULL); + // lpDevice->SetVertexShader( WFVERTEX_FORMAT ); + } + + // render string to m_lpDDSTitle, if necessary + if (m_supertext.bRedrawSuperText) + { + if (!RenderStringToTitleTexture()) + m_supertext.fStartTime = -1.0f; + m_supertext.bRedrawSuperText = false; + } + + // set up to render [from NULL] to VS0 (for motion vectors). + { + lpDevice->SetTexture(0, NULL); + + IDirect3DSurface9* pNewTarget = NULL; + if (m_lpVS[0]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK) + return; + lpDevice->SetRenderTarget(0, pNewTarget); + pNewTarget->Release(); + lpDevice->SetDepthStencilSurface( NULL ); + + lpDevice->SetTexture(0, NULL); + } + + // draw motion vectors to VS0 + DrawMotionVectors(); + + // set up to render [from VS0] to VS1. + { + lpDevice->SetTexture(0, NULL); + + IDirect3DSurface9* pNewTarget = NULL; + if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK) + return; + lpDevice->SetRenderTarget(0, pNewTarget); + lpDevice->SetDepthStencilSurface( NULL ); + pNewTarget->Release(); + } + + // do the warping for this frame + if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER) + lpDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE); + /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES) + lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);*/ + WarpedBlitFromVS0ToVS1(); + if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER) + lpDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE); + /*if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES) + lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, TRUE);*/ + + // draw audio data + DrawCustomShapes(); // draw these first; better for feedback if the waves draw *over* them. + DrawCustomWaves(); + DrawWave(mysound.fWave[0], mysound.fWave[1]); + DrawSprites(); + + // if song title animation just ended, render it into the VS: + if (m_supertext.fStartTime >= 0 && + GetTime() >= m_supertext.fStartTime + m_supertext.fDuration && + !m_supertext.bRedrawSuperText) + { + m_supertext.fStartTime = -1.0f; // 'off' state + ShowSongTitleAnim(m_nTexSize, m_nTexSize, 1.0f); + } + + // Change the rendertarget back to the original setup + lpDevice->SetTexture(0, NULL); + // WISO: lpDevice->SetRenderTarget( pBackBuffer, pZBuffer ); + lpDevice->SetRenderTarget(0, pBackBuffer); + lpDevice->SetDepthStencilSurface( pZBuffer ); + + SafeRelease(pBackBuffer); + SafeRelease(pZBuffer); + + /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES) + lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);*/ + + // show it to user + ShowToUser(bRedraw); + + + // finally, render song title animation to back buffer + if (m_supertext.fStartTime >= 0 && + GetTime() < m_supertext.fStartTime + m_supertext.fDuration && + !m_supertext.bRedrawSuperText) + { + float fProgress = (GetTime() - m_supertext.fStartTime) / m_supertext.fDuration; + ShowSongTitleAnim(GetWidth(), GetHeight(), fProgress); + } + + DrawUserSprites(); + + // flip buffers + IDirect3DTexture9* pTemp = m_lpVS[0]; + m_lpVS[0] = m_lpVS[1]; + m_lpVS[1] = pTemp; + + /* WISO: if (GetCaps()->RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES) + lpDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);*/ + if (GetCaps()->RasterCaps & D3DPRASTERCAPS_DITHER) + lpDevice->SetRenderState(D3DRS_DITHERENABLE, FALSE); +} + + +void CPlugin::DrawMotionVectors() +{ + // FLEXIBLE MOTION VECTOR FIELD + if ((float)*m_pState->var_pf_mv_a >= 0.001f) + { + //------------------------------------------------------- + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, NULL); + lpDevice->SetFVF(WFVERTEX_FORMAT); + //------------------------------------------------------- + + int x,y; + + int nX = (int)(*m_pState->var_pf_mv_x);// + 0.999f); + int nY = (int)(*m_pState->var_pf_mv_y);// + 0.999f); + float dx = (float)*m_pState->var_pf_mv_x - nX; + float dy = (float)*m_pState->var_pf_mv_y - nY; + if (nX > 64) { nX = 64; dx = 0; } + if (nY > 48) { nY = 48; dy = 0; } + + if (nX > 0 && nY > 0) + { + /* + float dx2 = m_fMotionVectorsTempDx;//(*m_pState->var_pf_mv_dx) * 0.05f*GetTime(); // 0..1 range + float dy2 = m_fMotionVectorsTempDy;//(*m_pState->var_pf_mv_dy) * 0.05f*GetTime(); // 0..1 range + if (GetFps() > 2.0f && GetFps() < 300.0f) + { + dx2 += (float)(*m_pState->var_pf_mv_dx) * 0.05f / GetFps(); + dy2 += (float)(*m_pState->var_pf_mv_dy) * 0.05f / GetFps(); + } + if (dx2 > 1.0f) dx2 -= (int)dx2; + if (dy2 > 1.0f) dy2 -= (int)dy2; + if (dx2 < 0.0f) dx2 = 1.0f - (-dx2 - (int)(-dx2)); + if (dy2 < 0.0f) dy2 = 1.0f - (-dy2 - (int)(-dy2)); + // hack: when there is only 1 motion vector on the screem, to keep it in + // the center, we gradually migrate it toward 0.5. + dx2 = dx2*0.995f + 0.5f*0.005f; + dy2 = dy2*0.995f + 0.5f*0.005f; + // safety catch + if (dx2 < 0 || dx2 > 1 || dy2 < 0 || dy2 > 1) + { + dx2 = 0.5f; + dy2 = 0.5f; + } + m_fMotionVectorsTempDx = dx2; + m_fMotionVectorsTempDy = dy2;*/ + float dx2 = (float)(*m_pState->var_pf_mv_dx); + float dy2 = (float)(*m_pState->var_pf_mv_dy); + + float len_mult = (float)*m_pState->var_pf_mv_l; + if (dx < 0) dx = 0; + if (dy < 0) dy = 0; + if (dx > 1) dx = 1; + if (dy > 1) dy = 1; + //dx = dx * 1.0f/(float)nX; + //dy = dy * 1.0f/(float)nY; + float inv_texsize = 1.0f/(float)m_nTexSize; + float min_len = 1.0f*inv_texsize; + + + WFVERTEX v[(64+1)*2]; + ZeroMemory(v, sizeof(WFVERTEX)*(64+1)*2); + v[0].Diffuse = D3DCOLOR_RGBA_01((float)*m_pState->var_pf_mv_r,(float)*m_pState->var_pf_mv_g,(float)*m_pState->var_pf_mv_b,(float)*m_pState->var_pf_mv_a); + for (x=1; x<(nX+1)*2; x++) + v[x].Diffuse = v[0].Diffuse; + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + for (y=0; y 0.0001f && fy < 0.9999f) + { + int n = 0; + for (x=0; x 0.0001f && fx < 0.9999f) + { + float fx2, fy2; + ReversePropagatePoint(fx, fy, &fx2, &fy2); // NOTE: THIS IS REALLY A REVERSE-PROPAGATION + //fx2 = fx*2 - fx2; + //fy2 = fy*2 - fy2; + //fx2 = fx + 1.0f/(float)m_nTexSize; + //fy2 = 1-(fy + 1.0f/(float)m_nTexSize); + + // enforce minimum trail lengths: + { + float dx = (fx2 - fx); + float dy = (fy2 - fy); + dx *= len_mult; + dy *= len_mult; + float len = sqrtf(dx*dx + dy*dy); + + if (len > min_len) + { + + } + else if (len > 0.00000001f) + { + len = min_len/len; + dx *= len; + dy *= len; + } + else + { + dx = min_len; + dy = min_len; + } + + fx2 = fx + dx; + fy2 = fy + dy; + } + /**/ + + v[n].x = fx * 2.0f - 1.0f; + v[n].y = fy * 2.0f - 1.0f; + v[n+1].x = fx2 * 2.0f - 1.0f; + v[n+1].y = fy2 * 2.0f - 1.0f; + + // actually, project it in the reverse direction + //v[n+1].x = v[n].x*2.0f - v[n+1].x;// + dx*2; + //v[n+1].y = v[n].y*2.0f - v[n+1].y;// + dy*2; + //v[n].x += dx*2; + //v[n].y += dy*2; + + n += 2; + } + } + + // draw it + if (n != 0) + lpDevice->DrawPrimitiveUP(D3DPT_LINELIST, n/2, v, sizeof(WFVERTEX)); + } + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + } +} + +/* +void CPlugin::UpdateSongInfo() +{ + if (m_bShowSongTitle || m_bSongTitleAnims) + { + char szOldSongMessage[512]; + strcpy(szOldSongMessage, m_szSongMessage); + + if (::GetWindowText(m_hWndParent, m_szSongMessage, sizeof(m_szSongMessage))) + { + // remove ' - Winamp' at end + if (strlen(m_szSongMessage) > 9) + { + int check_pos = strlen(m_szSongMessage) - 9; + if (strcmp(" - Winamp", (char *)(m_szSongMessage + check_pos)) == 0) + m_szSongMessage[check_pos] = 0; + } + + // remove ' - Winamp [Paused]' at end + if (strlen(m_szSongMessage) > 18) + { + int check_pos = strlen(m_szSongMessage) - 18; + if (strcmp(" - Winamp [Paused]", (char *)(m_szSongMessage + check_pos)) == 0) + m_szSongMessage[check_pos] = 0; + } + + // remove song # and period from beginning + char *p = m_szSongMessage; + while (*p >= '0' && *p <= '9') p++; + if (*p == '.' && *(p+1) == ' ') + { + p += 2; + int pos = 0; + while (*p != 0) + { + m_szSongMessage[pos++] = *p; + p++; + } + m_szSongMessage[pos++] = 0; + } + + // fix &'s for display + /* + { + int pos = 0; + int len = strlen(m_szSongMessage); + while (m_szSongMessage[pos]) + { + if (m_szSongMessage[pos] == '&') + { + for (int x=len; x>=pos; x--) + m_szSongMessage[x+1] = m_szSongMessage[x]; + len++; + pos++; + } + pos++; + } + }*/ +/* + if (m_bSongTitleAnims && + ((strcmp(szOldSongMessage, m_szSongMessage) != 0) || (GetFrame()==0))) + { + // launch song title animation + LaunchSongTitleAnim(); + + /* + m_supertext.bRedrawSuperText = true; + m_supertext.bIsSongTitle = true; + strcpy(m_supertext.szText, m_szSongMessage); + strcpy(m_supertext.nFontFace, m_szTitleFontFace); + m_supertext.fFontSize = (float)m_nTitleFontSize; + m_supertext.bBold = m_bTitleFontBold; + m_supertext.bItal = m_bTitleFontItalic; + m_supertext.fX = 0.5f; + m_supertext.fY = 0.5f; + m_supertext.fGrowth = 1.0f; + m_supertext.fDuration = m_fSongTitleAnimDuration; + m_supertext.nColorR = 255; + m_supertext.nColorG = 255; + m_supertext.nColorB = 255; + + m_supertext.fStartTime = GetTime(); + */ +/* } + } + else + { + sprintf(m_szSongMessage, ""); + } + } + + m_nTrackPlaying = SendMessage(m_hWndParent,WM_USER, 0, 125); + + // append song time + if (m_bShowSongTime && m_nSongPosMS >= 0) + { + float time_s = m_nSongPosMS*0.001f; + + int minutes = (int)(time_s/60); + time_s -= minutes*60; + int seconds = (int)time_s; + time_s -= seconds; + int dsec = (int)(time_s*100); + + sprintf(m_szSongTime, "%d:%02d.%02d", minutes, seconds, dsec); + } + + // append song length + if (m_bShowSongLen && m_nSongLenMS > 0) + { + int len_s = m_nSongLenMS/1000; + int minutes = len_s/60; + int seconds = len_s - minutes*60; + + char buf[512]; + sprintf(buf, " / %d:%02d", minutes, seconds); + strcat(m_szSongTime, buf); + } +} +*/ + +bool CPlugin::ReversePropagatePoint(float fx, float fy, float *fx2, float *fy2) +{ + //float fy = y/(float)nMotionVectorsY; + int y0 = (int)(fy*m_nGridY); + float dy = fy*m_nGridY - y0; + + //float fx = x/(float)nMotionVectorsX; + int x0 = (int)(fx*m_nGridX); + float dx = fx*m_nGridX - x0; + + int x1 = x0 + 1; + int y1 = y0 + 1; + + if (x0 < 0) return false; + if (y0 < 0) return false; + //if (x1 < 0) return false; + //if (y1 < 0) return false; + //if (x0 > m_nGridX) return false; + //if (y0 > m_nGridY) return false; + if (x1 > m_nGridX) return false; + if (y1 > m_nGridY) return false; + + float tu, tv; + tu = m_verts[y0*(m_nGridX+1)+x0].tu * (1-dx)*(1-dy); + tv = m_verts[y0*(m_nGridX+1)+x0].tv * (1-dx)*(1-dy); + tu += m_verts[y0*(m_nGridX+1)+x1].tu * (dx)*(1-dy); + tv += m_verts[y0*(m_nGridX+1)+x1].tv * (dx)*(1-dy); + tu += m_verts[y1*(m_nGridX+1)+x0].tu * (1-dx)*(dy); + tv += m_verts[y1*(m_nGridX+1)+x0].tv * (1-dx)*(dy); + tu += m_verts[y1*(m_nGridX+1)+x1].tu * (dx)*(dy); + tv += m_verts[y1*(m_nGridX+1)+x1].tv * (dx)*(dy); + + *fx2 = tu; + *fy2 = 1.0f - tv; + return true; + +} + + +void CPlugin::WarpedBlitFromVS0ToVS1() +{ + MungeFPCW(NULL); // puts us in single-precision mode & disables exceptions + + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, m_lpVS[0]); + lpDevice->SetFVF( SPRITEVERTEX_FORMAT ); + + // warp stuff + float fWarpTime = GetTime() * m_pState->m_fWarpAnimSpeed; + float fWarpScale = m_pState->m_fWarpScale.eval(GetTime()); + float fWarpScaleInv = 1.0f; + if(fWarpScale != 0.0f) + fWarpScaleInv = 1.0f / fWarpScale; + float f[4]; + f[0] = 11.68f + 4.0f*cosf(fWarpTime*1.413f + 10); + f[1] = 8.77f + 3.0f*cosf(fWarpTime*1.113f + 7); + f[2] = 10.54f + 3.0f*cosf(fWarpTime*1.233f + 3); + f[3] = 11.49f + 4.0f*cosf(fWarpTime*0.933f + 5); + + int num_reps = (m_pState->m_bBlending) ? 2 : 1; + float fCosineBlend = 0.50f*(m_pState->m_fBlendProgress) + 0.50f*CosineInterp(m_pState->m_fBlendProgress); + float fCosineBlend2 = 0.40f*(m_pState->m_fBlendProgress) + 0.60f*CosineInterp(m_pState->m_fBlendProgress); + + // decay + float fDecay = (float)(*m_pState->var_pf_decay); + + // texel alignment + float texel_offset = 0.5f / (float)m_nTexSize; + + //if (m_pState->m_bBlending) + // fDecay = fDecay*(fCosineBlend) + (1.0f-fCosineBlend)*((float)(*m_pOldState->var_pf_decay)); + + if (m_bAutoGamma && GetFrame()==0) + { + if (strstr(GetDriverDescription(), "nvidia") || + strstr(GetDriverDescription(), "nVidia") || + strstr(GetDriverDescription(), "NVidia") || + strstr(GetDriverDescription(), "NVIDIA")) + m_n16BitGamma = 2; + else if (strstr(GetDriverDescription(), "ATI RAGE MOBILITY M")) + m_n16BitGamma = 2; + else + m_n16BitGamma = 0; + } + + if (m_n16BitGamma > 0 && + (GetBackBufFormat()==D3DFMT_R5G6B5 || GetBackBufFormat()==D3DFMT_X1R5G5B5 || GetBackBufFormat()==D3DFMT_A1R5G5B5 || GetBackBufFormat()==D3DFMT_A4R4G4B4) && + fDecay < 0.9999f) + { + fDecay = min(fDecay, (32.0f - m_n16BitGamma)/32.0f); + } + + D3DCOLOR cDecay = D3DCOLOR_RGBA_01(fDecay,fDecay,fDecay,1); + + + for (int rep=0; repm_pv_vars); + + // cache the doubles as floats so that computations are a bit faster + float fZoom = (float)(*pState->var_pf_zoom); + float fZoomExp = (float)(*pState->var_pf_zoomexp); + float fRot = (float)(*pState->var_pf_rot); + float fWarp = (float)(*pState->var_pf_warp); + float fCX = (float)(*pState->var_pf_cx); + float fCY = (float)(*pState->var_pf_cy); + float fDX = (float)(*pState->var_pf_dx); + float fDY = (float)(*pState->var_pf_dy); + float fSX = (float)(*pState->var_pf_sx); + float fSY = (float)(*pState->var_pf_sy); + + int n = 0; + + for (int y=0; y<=m_nGridY; y++) + { + for (int x=0; x<=m_nGridX; x++) + { + // Note: x, y, z are now set at init. time - no need to mess with them! + //m_verts[n].x = i/(float)m_nGridX*2.0f - 1.0f; + //m_verts[n].y = j/(float)m_nGridY*2.0f - 1.0f; + //m_verts[n].z = 0.0f; + + if (pState->m_pp_codehandle) + { + // restore all the variables to their original states, + // run the user-defined equations, + // then move the results into local vars for computation as floats + + *pState->var_pv_x = (double)(m_verts[n].x*0.5f + 0.5f); + *pState->var_pv_y = (double)(m_verts[n].y*-0.5f + 0.5f); + *pState->var_pv_rad = (double)m_vertinfo[n].rad; + *pState->var_pv_ang = (double)m_vertinfo[n].ang; + *pState->var_pv_zoom = *pState->var_pf_zoom; + *pState->var_pv_zoomexp = *pState->var_pf_zoomexp; + *pState->var_pv_rot = *pState->var_pf_rot; + *pState->var_pv_warp = *pState->var_pf_warp; + *pState->var_pv_cx = *pState->var_pf_cx; + *pState->var_pv_cy = *pState->var_pf_cy; + *pState->var_pv_dx = *pState->var_pf_dx; + *pState->var_pv_dy = *pState->var_pf_dy; + *pState->var_pv_sx = *pState->var_pf_sx; + *pState->var_pv_sy = *pState->var_pf_sy; + /* + *pState->var_pv_q1 = *pState->var_pf_q1; + *pState->var_pv_q2 = *pState->var_pf_q2; + *pState->var_pv_q3 = *pState->var_pf_q3; + *pState->var_pv_q4 = *pState->var_pf_q4; + *pState->var_pv_q5 = *pState->var_pf_q5; + *pState->var_pv_q6 = *pState->var_pf_q6; + *pState->var_pv_q7 = *pState->var_pf_q7; + *pState->var_pv_q8 = *pState->var_pf_q8; + */ + //*pState->var_pv_time = *pState->var_pv_time; // (these are all now initialized + //*pState->var_pv_bass = *pState->var_pv_bass; // just once per frame) + //*pState->var_pv_mid = *pState->var_pv_mid; + //*pState->var_pv_treb = *pState->var_pv_treb; + //*pState->var_pv_bass_att = *pState->var_pv_bass_att; + //*pState->var_pv_mid_att = *pState->var_pv_mid_att; + //*pState->var_pv_treb_att = *pState->var_pv_treb_att; + +#ifndef _NO_EXPR_ + executeCode(pState->m_pp_codehandle); +#endif + + fZoom = (float)(*pState->var_pv_zoom); + fZoomExp = (float)(*pState->var_pv_zoomexp); + fRot = (float)(*pState->var_pv_rot); + fWarp = (float)(*pState->var_pv_warp); + fCX = (float)(*pState->var_pv_cx); + fCY = (float)(*pState->var_pv_cy); + fDX = (float)(*pState->var_pv_dx); + fDY = (float)(*pState->var_pv_dy); + fSX = (float)(*pState->var_pv_sx); + fSY = (float)(*pState->var_pv_sy); + } + + float fZoom2 = powf(fZoom, powf(fZoomExp, m_vertinfo[n].rad*2.0f - 1.0f)); + + // initial texcoords, w/built-in zoom factor + float fZoom2Inv = 1.0f/fZoom2; + float u = m_verts[n].x*0.5f*fZoom2Inv + 0.5f; + float v = -m_verts[n].y*0.5f*fZoom2Inv + 0.5f; + + // stretch on X, Y: + u = (u - fCX)/fSX + fCX; + v = (v - fCY)/fSY + fCY; + + // warping: + //if (fWarp > 0.001f || fWarp < -0.001f) + //{ + u += fWarp*0.0035f*sinf(fWarpTime*0.333f + fWarpScaleInv*(m_verts[n].x*f[0] - m_verts[n].y*f[3])); + v += fWarp*0.0035f*cosf(fWarpTime*0.375f - fWarpScaleInv*(m_verts[n].x*f[2] + m_verts[n].y*f[1])); + u += fWarp*0.0035f*cosf(fWarpTime*0.753f - fWarpScaleInv*(m_verts[n].x*f[1] - m_verts[n].y*f[2])); + v += fWarp*0.0035f*sinf(fWarpTime*0.825f + fWarpScaleInv*(m_verts[n].x*f[0] + m_verts[n].y*f[3])); + //} + + // rotation: + float u2 = u - fCX; + float v2 = v - fCY; + + float cos_rot = cosf(fRot); + float sin_rot = sinf(fRot); + u = u2*cos_rot - v2*sin_rot + fCX; + v = u2*sin_rot + v2*cos_rot + fCY; + + // translation: + u -= fDX - texel_offset; + v -= fDY - texel_offset; + + if (rep==0) + { + //m_verts[n].Diffuse = cDecay; // see below + m_verts[n].tu = u; + m_verts[n].tv = v; + } + else + { + float mix2 = m_vertinfo[n].a*m_pState->m_fBlendProgress + m_vertinfo[n].c;//fCosineBlend2; + mix2 = max(0,min(1,mix2)); + m_verts[n].tu = m_verts[n].tu*(mix2) + u*(1-mix2); + m_verts[n].tv = m_verts[n].tv*(mix2) + v*(1-mix2); + } + + /* + if (rep==num_reps-1) + { + m_verts[n].tu += 0.25f*(FRAND*2-1)/(float)m_nTexSize; + m_verts[n].tv += 0.25f*(FRAND*2-1)/(float)m_nTexSize; + } + */ + + n++; + } + } + + /* + pState->q_values_after_init_code[0] = *pState->var_pv_q1; + pState->q_values_after_init_code[1] = *pState->var_pv_q2; + pState->q_values_after_init_code[2] = *pState->var_pv_q3; + pState->q_values_after_init_code[3] = *pState->var_pv_q4; + pState->q_values_after_init_code[4] = *pState->var_pv_q5; + pState->q_values_after_init_code[5] = *pState->var_pv_q6; + pState->q_values_after_init_code[6] = *pState->var_pv_q7; + pState->q_values_after_init_code[7] = *pState->var_pv_q8; + */ + + resetVars(NULL); + } + + + + // hurl the triangle strips at the video card + + int poly; + + for (poly=0; polyDrawPrimitiveUP(D3DPT_TRIANGLESTRIP, m_nGridX, (void*)m_verts_temp, sizeof(SPRITEVERTEX)); + } +} + +void CPlugin::DrawCustomShapes() +{ + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + //lpDevice->SetTexture(0, m_lpVS[0]);//NULL); + //lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT ); + + int num_reps = (m_pState->m_bBlending) ? 2 : 1; + for (int rep=0; repm_fBlendProgress : (1-m_pState->m_fBlendProgress); + + for (int i=0; im_shape[i].enabled) + { + /* + int bAdditive = 0; + int nSides = 3;//3 + ((int)GetTime() % 8); + int bThickOutline = 0; + float x = 0.5f + 0.1f*cosf(GetTime()*0.8f+1); + float y = 0.5f + 0.1f*sinf(GetTime()*0.8f+1); + float rad = 0.15f + 0.07f*sinf(GetTime()*1.1f+3); + float ang = GetTime()*1.5f; + + // inside colors + float r = 1; + float g = 0; + float b = 0; + float a = 0.4f;//0.1f + 0.1f*sinf(GetTime()*0.31f); + + // outside colors + float r2 = 0; + float g2 = 1; + float b2 = 0; + float a2 = 0; + + // border colors + float border_r = 1; + float border_g = 1; + float border_b = 1; + float border_a = 0.5f; + */ + + // 1. execute per-frame code + LoadCustomShapePerFrameEvallibVars(pState, i); + + #ifndef _NO_EXPR_ + if (pState->m_shape[i].m_pf_codehandle) + { + resetVars(pState->m_shape[i].m_pf_vars); + executeCode(pState->m_shape[i].m_pf_codehandle); + resetVars(NULL); + } + #endif + + // save changes to t1-t8 this frame + /* + pState->m_shape[i].t_values_after_init_code[0] = *pState->m_shape[i].var_pf_t1; + pState->m_shape[i].t_values_after_init_code[1] = *pState->m_shape[i].var_pf_t2; + pState->m_shape[i].t_values_after_init_code[2] = *pState->m_shape[i].var_pf_t3; + pState->m_shape[i].t_values_after_init_code[3] = *pState->m_shape[i].var_pf_t4; + pState->m_shape[i].t_values_after_init_code[4] = *pState->m_shape[i].var_pf_t5; + pState->m_shape[i].t_values_after_init_code[5] = *pState->m_shape[i].var_pf_t6; + pState->m_shape[i].t_values_after_init_code[6] = *pState->m_shape[i].var_pf_t7; + pState->m_shape[i].t_values_after_init_code[7] = *pState->m_shape[i].var_pf_t8; + */ + + int sides = (int)(*pState->m_shape[i].var_pf_sides); + if (sides<3) sides=3; + if (sides>100) sides=100; + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, ((int)(*pState->m_shape[i].var_pf_additive) != 0) ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA); + + SPRITEVERTEX v[512]; // for textured shapes (has texcoords) + WFVERTEX v2[512]; // for untextured shapes + borders + + v[0].x = (float)(*pState->m_shape[i].var_pf_x* 2-1);// * ASPECT; + v[0].y = (float)(*pState->m_shape[i].var_pf_y*-2+1); + v[0].z = 0; + v[0].tu = 0.5f; + v[0].tv = 0.5f; + v[0].Diffuse = + ((((int)(*pState->m_shape[i].var_pf_a * 255 * alpha_mult)) & 0xFF) << 24) | + ((((int)(*pState->m_shape[i].var_pf_r * 255)) & 0xFF) << 16) | + ((((int)(*pState->m_shape[i].var_pf_g * 255)) & 0xFF) << 8) | + ((((int)(*pState->m_shape[i].var_pf_b * 255)) & 0xFF) ); + v[1].Diffuse = + ((((int)(*pState->m_shape[i].var_pf_a2 * 255 * alpha_mult)) & 0xFF) << 24) | + ((((int)(*pState->m_shape[i].var_pf_r2 * 255)) & 0xFF) << 16) | + ((((int)(*pState->m_shape[i].var_pf_g2 * 255)) & 0xFF) << 8) | + ((((int)(*pState->m_shape[i].var_pf_b2 * 255)) & 0xFF) ); + + for (int j=1; jm_shape[i].var_pf_rad*cosf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_ang + 3.1415927f*0.25f)*ASPECT; // DON'T TOUCH! + v[j].y = v[0].y + (float)*pState->m_shape[i].var_pf_rad*sinf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_ang + 3.1415927f*0.25f); // DON'T TOUCH! + v[j].z = 0; + v[j].tu = 0.5f + 0.5f*cosf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_tex_ang + 3.1415927f*0.25f)/((float)*pState->m_shape[i].var_pf_tex_zoom) * ASPECT; // DON'T TOUCH! + v[j].tv = 0.5f + 0.5f*sinf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_tex_ang + 3.1415927f*0.25f)/((float)*pState->m_shape[i].var_pf_tex_zoom); // DON'T TOUCH! + v[j].Diffuse = v[1].Diffuse; + } + v[sides+1] = v[1]; + + if ((int)(*pState->m_shape[i].var_pf_textured) != 0) + { + // draw textured version + lpDevice->SetTexture(0, m_lpVS[0]); + lpDevice->SetFVF( SPRITEVERTEX_FORMAT ); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, sides, (void*)v, sizeof(SPRITEVERTEX)); + } + else + { + // no texture + for (int j=0; j < sides+2; j++) + { + v2[j].x = v[j].x; + v2[j].y = v[j].y; + v2[j].z = v[j].z; + v2[j].Diffuse = v[j].Diffuse; + } + lpDevice->SetTexture(0, NULL); + lpDevice->SetFVF( WFVERTEX_FORMAT ); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, sides, (void*)v2, sizeof(WFVERTEX)); + } + + + // DRAW BORDER + if (*pState->m_shape[i].var_pf_border_a > 0) + { + lpDevice->SetTexture(0, NULL); + lpDevice->SetFVF( WFVERTEX_FORMAT ); + + v2[0].Diffuse = + ((((int)(*pState->m_shape[i].var_pf_border_a * 255 * alpha_mult)) & 0xFF) << 24) | + ((((int)(*pState->m_shape[i].var_pf_border_r * 255)) & 0xFF) << 16) | + ((((int)(*pState->m_shape[i].var_pf_border_g * 255)) & 0xFF) << 8) | + ((((int)(*pState->m_shape[i].var_pf_border_b * 255)) & 0xFF) ); + for (int j=0; jm_shape[i].var_pf_thick) != 0) ? 4 : 1; + float x_inc = 2.0f / (float)m_nTexSize; + for (int it=0; itDrawPrimitiveUP(D3DPT_LINESTRIP, sides, (void*)&v2[1], sizeof(WFVERTEX)); + } + + lpDevice->SetTexture(0, m_lpVS[0]); + lpDevice->SetFVF( SPRITEVERTEX_FORMAT ); + } + } + } + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); +} + +void CPlugin::LoadCustomShapePerFrameEvallibVars(CState* pState, int i) +{ + *pState->m_shape[i].var_pf_time = (double)(GetTime() - m_fStartTime); + *pState->m_shape[i].var_pf_frame = (double)GetFrame(); + *pState->m_shape[i].var_pf_fps = (double)GetFps(); + *pState->m_shape[i].var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime); + *pState->m_shape[i].var_pf_bass = (double)mysound.imm_rel[0]; + *pState->m_shape[i].var_pf_mid = (double)mysound.imm_rel[1]; + *pState->m_shape[i].var_pf_treb = (double)mysound.imm_rel[2]; + *pState->m_shape[i].var_pf_bass_att = (double)mysound.avg_rel[0]; + *pState->m_shape[i].var_pf_mid_att = (double)mysound.avg_rel[1]; + *pState->m_shape[i].var_pf_treb_att = (double)mysound.avg_rel[2]; + *pState->m_shape[i].var_pf_q1 = *pState->var_pf_q1;//pState->q_values_after_init_code[0];//0.0f; + *pState->m_shape[i].var_pf_q2 = *pState->var_pf_q2;//pState->q_values_after_init_code[1];//0.0f; + *pState->m_shape[i].var_pf_q3 = *pState->var_pf_q3;//pState->q_values_after_init_code[2];//0.0f; + *pState->m_shape[i].var_pf_q4 = *pState->var_pf_q4;//pState->q_values_after_init_code[3];//0.0f; + *pState->m_shape[i].var_pf_q5 = *pState->var_pf_q5;//pState->q_values_after_init_code[4];//0.0f; + *pState->m_shape[i].var_pf_q6 = *pState->var_pf_q6;//pState->q_values_after_init_code[5];//0.0f; + *pState->m_shape[i].var_pf_q7 = *pState->var_pf_q7;//pState->q_values_after_init_code[6];//0.0f; + *pState->m_shape[i].var_pf_q8 = *pState->var_pf_q8;//pState->q_values_after_init_code[7];//0.0f; + *pState->m_shape[i].var_pf_t1 = pState->m_shape[i].t_values_after_init_code[0];//0.0f; + *pState->m_shape[i].var_pf_t2 = pState->m_shape[i].t_values_after_init_code[1];//0.0f; + *pState->m_shape[i].var_pf_t3 = pState->m_shape[i].t_values_after_init_code[2];//0.0f; + *pState->m_shape[i].var_pf_t4 = pState->m_shape[i].t_values_after_init_code[3];//0.0f; + *pState->m_shape[i].var_pf_t5 = pState->m_shape[i].t_values_after_init_code[4];//0.0f; + *pState->m_shape[i].var_pf_t6 = pState->m_shape[i].t_values_after_init_code[5];//0.0f; + *pState->m_shape[i].var_pf_t7 = pState->m_shape[i].t_values_after_init_code[6];//0.0f; + *pState->m_shape[i].var_pf_t8 = pState->m_shape[i].t_values_after_init_code[7];//0.0f; + *pState->m_shape[i].var_pf_x = pState->m_shape[i].x; + *pState->m_shape[i].var_pf_y = pState->m_shape[i].y; + *pState->m_shape[i].var_pf_rad = pState->m_shape[i].rad; + *pState->m_shape[i].var_pf_ang = pState->m_shape[i].ang; + *pState->m_shape[i].var_pf_tex_zoom = pState->m_shape[i].tex_zoom; + *pState->m_shape[i].var_pf_tex_ang = pState->m_shape[i].tex_ang; + *pState->m_shape[i].var_pf_sides = pState->m_shape[i].sides; + *pState->m_shape[i].var_pf_additive = pState->m_shape[i].additive; + *pState->m_shape[i].var_pf_textured = pState->m_shape[i].textured; + *pState->m_shape[i].var_pf_thick = pState->m_shape[i].thickOutline; + *pState->m_shape[i].var_pf_r = pState->m_shape[i].r; + *pState->m_shape[i].var_pf_g = pState->m_shape[i].g; + *pState->m_shape[i].var_pf_b = pState->m_shape[i].b; + *pState->m_shape[i].var_pf_a = pState->m_shape[i].a; + *pState->m_shape[i].var_pf_r2 = pState->m_shape[i].r2; + *pState->m_shape[i].var_pf_g2 = pState->m_shape[i].g2; + *pState->m_shape[i].var_pf_b2 = pState->m_shape[i].b2; + *pState->m_shape[i].var_pf_a2 = pState->m_shape[i].a2; + *pState->m_shape[i].var_pf_border_r = pState->m_shape[i].border_r; + *pState->m_shape[i].var_pf_border_g = pState->m_shape[i].border_g; + *pState->m_shape[i].var_pf_border_b = pState->m_shape[i].border_b; + *pState->m_shape[i].var_pf_border_a = pState->m_shape[i].border_a; +} + +void CPlugin::LoadCustomWavePerFrameEvallibVars(CState* pState, int i) +{ + *pState->m_wave[i].var_pf_time = (double)(GetTime() - m_fStartTime); + *pState->m_wave[i].var_pf_frame = (double)GetFrame(); + *pState->m_wave[i].var_pf_fps = (double)GetFps(); + *pState->m_wave[i].var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime); + *pState->m_wave[i].var_pf_bass = (double)mysound.imm_rel[0]; + *pState->m_wave[i].var_pf_mid = (double)mysound.imm_rel[1]; + *pState->m_wave[i].var_pf_treb = (double)mysound.imm_rel[2]; + *pState->m_wave[i].var_pf_bass_att = (double)mysound.avg_rel[0]; + *pState->m_wave[i].var_pf_mid_att = (double)mysound.avg_rel[1]; + *pState->m_wave[i].var_pf_treb_att = (double)mysound.avg_rel[2]; + *pState->m_wave[i].var_pf_q1 = *pState->var_pf_q1;//pState->q_values_after_init_code[0];//0.0f; + *pState->m_wave[i].var_pf_q2 = *pState->var_pf_q2;//pState->q_values_after_init_code[1];//0.0f; + *pState->m_wave[i].var_pf_q3 = *pState->var_pf_q3;//pState->q_values_after_init_code[2];//0.0f; + *pState->m_wave[i].var_pf_q4 = *pState->var_pf_q4;//pState->q_values_after_init_code[3];//0.0f; + *pState->m_wave[i].var_pf_q5 = *pState->var_pf_q5;//pState->q_values_after_init_code[4];//0.0f; + *pState->m_wave[i].var_pf_q6 = *pState->var_pf_q6;//pState->q_values_after_init_code[5];//0.0f; + *pState->m_wave[i].var_pf_q7 = *pState->var_pf_q7;//pState->q_values_after_init_code[6];//0.0f; + *pState->m_wave[i].var_pf_q8 = *pState->var_pf_q8;//pState->q_values_after_init_code[7];//0.0f; + *pState->m_wave[i].var_pf_t1 = pState->m_wave[i].t_values_after_init_code[0];//0.0f; + *pState->m_wave[i].var_pf_t2 = pState->m_wave[i].t_values_after_init_code[1];//0.0f; + *pState->m_wave[i].var_pf_t3 = pState->m_wave[i].t_values_after_init_code[2];//0.0f; + *pState->m_wave[i].var_pf_t4 = pState->m_wave[i].t_values_after_init_code[3];//0.0f; + *pState->m_wave[i].var_pf_t5 = pState->m_wave[i].t_values_after_init_code[4];//0.0f; + *pState->m_wave[i].var_pf_t6 = pState->m_wave[i].t_values_after_init_code[5];//0.0f; + *pState->m_wave[i].var_pf_t7 = pState->m_wave[i].t_values_after_init_code[6];//0.0f; + *pState->m_wave[i].var_pf_t8 = pState->m_wave[i].t_values_after_init_code[7];//0.0f; + *pState->m_wave[i].var_pf_r = pState->m_wave[i].r; + *pState->m_wave[i].var_pf_g = pState->m_wave[i].g; + *pState->m_wave[i].var_pf_b = pState->m_wave[i].b; + *pState->m_wave[i].var_pf_a = pState->m_wave[i].a; +} + +void CPlugin::DrawCustomWaves() +{ + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, NULL); + lpDevice->SetFVF( WFVERTEX_FORMAT ); + + // note: read in all sound data from CPluginShell's m_sound + int num_reps = (m_pState->m_bBlending) ? 2 : 1; + for (int rep=0; repm_fBlendProgress : (1-m_pState->m_fBlendProgress); + + for (int i=0; im_wave[i].enabled) + { + int nSamples = pState->m_wave[i].samples; + int max_samples = pState->m_wave[i].bSpectrum ? 512 : NUM_WAVEFORM_SAMPLES; + if (nSamples > max_samples) + nSamples = max_samples; + nSamples -= pState->m_wave[i].sep; + + if ((nSamples >= 2) || (pState->m_wave[i].bUseDots && nSamples >= 1)) + { + int j; + float tempdata[2][512]; + float mult = ((pState->m_wave[i].bSpectrum) ? 0.15f : 0.004f) * pState->m_wave[i].scaling * pState->m_fWaveScale.eval(-1); + float *pdata1 = (pState->m_wave[i].bSpectrum) ? m_sound.fSpectrum[0] : m_sound.fWaveform[0]; + float *pdata2 = (pState->m_wave[i].bSpectrum) ? m_sound.fSpectrum[1] : m_sound.fWaveform[1]; + + // initialize tempdata[2][512] + int j0 = (pState->m_wave[i].bSpectrum) ? 0 : (max_samples - nSamples)/2/**(1-pState->m_wave[i].bSpectrum)*/ - pState->m_wave[i].sep/2; + int j1 = (pState->m_wave[i].bSpectrum) ? 0 : (max_samples - nSamples)/2/**(1-pState->m_wave[i].bSpectrum)*/ + pState->m_wave[i].sep/2; + float t = (pState->m_wave[i].bSpectrum) ? (max_samples - pState->m_wave[i].sep)/(float)nSamples : 1; + float mix1 = powf(pState->m_wave[i].smoothing*0.98f, 0.5f); // lower exponent -> more default smoothing + float mix2 = 1-mix1; + // SMOOTHING: + tempdata[0][0] = pdata1[j0]; + tempdata[1][0] = pdata2[j1]; + for (j=1; j=0; j--) + { + tempdata[0][j] = tempdata[0][j]*mix2 + tempdata[0][j+1]*mix1; + tempdata[1][j] = tempdata[1][j]*mix2 + tempdata[1][j+1]*mix1; + } + // finally, scale to final size: + for (j=0; jm_wave[i].var_pp_time = *pState->m_wave[i].var_pf_time; + *pState->m_wave[i].var_pp_fps = *pState->m_wave[i].var_pf_fps; + *pState->m_wave[i].var_pp_frame = *pState->m_wave[i].var_pf_frame; + *pState->m_wave[i].var_pp_progress = *pState->m_wave[i].var_pf_progress; + *pState->m_wave[i].var_pp_bass = *pState->m_wave[i].var_pf_bass; + *pState->m_wave[i].var_pp_mid = *pState->m_wave[i].var_pf_mid; + *pState->m_wave[i].var_pp_treb = *pState->m_wave[i].var_pf_treb; + *pState->m_wave[i].var_pp_bass_att = *pState->m_wave[i].var_pf_bass_att; + *pState->m_wave[i].var_pp_mid_att = *pState->m_wave[i].var_pf_mid_att; + *pState->m_wave[i].var_pp_treb_att = *pState->m_wave[i].var_pf_treb_att; + + executeCode(pState->m_wave[i].m_pf_codehandle); + + *pState->m_wave[i].var_pp_q1 = *pState->m_wave[i].var_pf_q1; + *pState->m_wave[i].var_pp_q2 = *pState->m_wave[i].var_pf_q2; + *pState->m_wave[i].var_pp_q3 = *pState->m_wave[i].var_pf_q3; + *pState->m_wave[i].var_pp_q4 = *pState->m_wave[i].var_pf_q4; + *pState->m_wave[i].var_pp_q5 = *pState->m_wave[i].var_pf_q5; + *pState->m_wave[i].var_pp_q6 = *pState->m_wave[i].var_pf_q6; + *pState->m_wave[i].var_pp_q7 = *pState->m_wave[i].var_pf_q7; + *pState->m_wave[i].var_pp_q8 = *pState->m_wave[i].var_pf_q8; + *pState->m_wave[i].var_pp_t1 = *pState->m_wave[i].var_pf_t1; + *pState->m_wave[i].var_pp_t2 = *pState->m_wave[i].var_pf_t2; + *pState->m_wave[i].var_pp_t3 = *pState->m_wave[i].var_pf_t3; + *pState->m_wave[i].var_pp_t4 = *pState->m_wave[i].var_pf_t4; + *pState->m_wave[i].var_pp_t5 = *pState->m_wave[i].var_pf_t5; + *pState->m_wave[i].var_pp_t6 = *pState->m_wave[i].var_pf_t6; + *pState->m_wave[i].var_pp_t7 = *pState->m_wave[i].var_pf_t7; + *pState->m_wave[i].var_pp_t8 = *pState->m_wave[i].var_pf_t8; + + // 2. for each point, execute per-point code + + #ifndef _NO_EXPR_ + resetVars(pState->m_wave[i].m_pp_vars); + #endif + + // to do: + // -add any of the m_wave[i].xxx menu-accessible vars to the code? + WFVERTEX v[512]; + float j_mult = 1.0f/(float)(nSamples-1); + for (j=0; jm_wave[i].var_pp_sample = t; + *pState->m_wave[i].var_pp_value1 = value1; + *pState->m_wave[i].var_pp_value2 = value2; + *pState->m_wave[i].var_pp_x = 0.5f + value1; + *pState->m_wave[i].var_pp_y = 0.5f + value2; + *pState->m_wave[i].var_pp_r = *pState->m_wave[i].var_pf_r; + *pState->m_wave[i].var_pp_g = *pState->m_wave[i].var_pf_g; + *pState->m_wave[i].var_pp_b = *pState->m_wave[i].var_pf_b; + *pState->m_wave[i].var_pp_a = *pState->m_wave[i].var_pf_a; + + #ifndef _NO_EXPR_ + executeCode(pState->m_wave[i].m_pp_codehandle); + #endif + + v[j].x = (float)(*pState->m_wave[i].var_pp_x* 2-1);//*ASPECT; + v[j].y = (float)(*pState->m_wave[i].var_pp_y*-2+1); + v[j].z = 0; + v[j].Diffuse = + ((((int)(*pState->m_wave[i].var_pp_a * 255 * alpha_mult)) & 0xFF) << 24) | + ((((int)(*pState->m_wave[i].var_pp_r * 255)) & 0xFF) << 16) | + ((((int)(*pState->m_wave[i].var_pp_g * 255)) & 0xFF) << 8) | + ((((int)(*pState->m_wave[i].var_pp_b * 255)) & 0xFF) ); + } + + #ifndef _NO_EXPR_ + resetVars(NULL); + #endif + + // save changes to t1-t8 this frame + /* + pState->m_wave[i].t_values_after_init_code[0] = *pState->m_wave[i].var_pp_t1; + pState->m_wave[i].t_values_after_init_code[1] = *pState->m_wave[i].var_pp_t2; + pState->m_wave[i].t_values_after_init_code[2] = *pState->m_wave[i].var_pp_t3; + pState->m_wave[i].t_values_after_init_code[3] = *pState->m_wave[i].var_pp_t4; + pState->m_wave[i].t_values_after_init_code[4] = *pState->m_wave[i].var_pp_t5; + pState->m_wave[i].t_values_after_init_code[5] = *pState->m_wave[i].var_pp_t6; + pState->m_wave[i].t_values_after_init_code[6] = *pState->m_wave[i].var_pp_t7; + pState->m_wave[i].t_values_after_init_code[7] = *pState->m_wave[i].var_pp_t8; + */ + + // 3. draw it + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, pState->m_wave[i].bAdditive ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA); + + float ptsize = ((m_nTexSize >= 1024) ? 2.0f : 1.0f) + (pState->m_wave[i].bDrawThick ? 1.0f : 0.0f); + if (pState->m_wave[i].bUseDots) + lpDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&ptsize) ); + + int its = (pState->m_wave[i].bDrawThick && !pState->m_wave[i].bUseDots) ? 4 : 1; + float x_inc = 2.0f / (float)m_nTexSize; + for (int it=0; itDrawPrimitiveUP(pState->m_wave[i].bUseDots ? D3DPT_POINTLIST : D3DPT_LINESTRIP, nSamples - (pState->m_wave[i].bUseDots ? 0 : 1), (void*)v, sizeof(WFVERTEX)); + } + + ptsize = 1.0f; + if (pState->m_wave[i].bUseDots) + lpDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&ptsize) ); + } + } + } + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); +} + +void CPlugin::DrawWave(float *fL, float *fR) +{ + //return; + + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, NULL); + lpDevice->SetFVF( WFVERTEX_FORMAT ); + + int i; + WFVERTEX v1[576+1], v2[576+1]; + + /* + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD); //D3DSHADE_FLAT + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE); + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + if (m_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER) + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE); + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE); + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_COLORVERTEX, TRUE); + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME); // vs. SOLID + m_lpD3DDev->lpDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, D3DCOLOR_RGBA_01(1,1,1,1)); + + hr = m_lpD3DDev->SetTexture(0, NULL); + if (hr != D3D_OK) + { + //dumpmsg("Draw(): ERROR: SetTexture"); + //IdentifyD3DError(hr); + } + */ + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, (*m_pState->var_pf_wave_additive) ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA); + + //float cr = m_pState->m_waveR.eval(GetTime()); + //float cg = m_pState->m_waveG.eval(GetTime()); + //float cb = m_pState->m_waveB.eval(GetTime()); + float cr = (float)(*m_pState->var_pf_wave_r); + float cg = (float)(*m_pState->var_pf_wave_g); + float cb = (float)(*m_pState->var_pf_wave_b); + float cx = (float)(*m_pState->var_pf_wave_x); + float cy = (float)(*m_pState->var_pf_wave_y); // note: it was backwards (top==1) in the original milkdrop, so we keep it that way! + float fWaveParam = (float)(*m_pState->var_pf_wave_mystery); + + /*if (m_pState->m_bBlending) + { + cr = cr*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_r)); + cg = cg*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_g)); + cb = cb*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_b)); + cx = cx*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_x)); + cy = cy*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_y)); + fWaveParam = fWaveParam*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_mystery)); + }*/ + + if (cr < 0) cr = 0; + if (cg < 0) cg = 0; + if (cb < 0) cb = 0; + if (cr > 1) cr = 1; + if (cg > 1) cg = 1; + if (cb > 1) cb = 1; + + // maximize color: + if (*m_pState->var_pf_wave_brighten) + { + float fMaximizeWaveColorAmount = 1.0f; + float max = cr; + if (max < cg) max = cg; + if (max < cb) max = cb; + if (max > 0.01f) + { + cr = cr/max*fMaximizeWaveColorAmount + cr*(1.0f - fMaximizeWaveColorAmount); + cg = cg/max*fMaximizeWaveColorAmount + cg*(1.0f - fMaximizeWaveColorAmount); + cb = cb/max*fMaximizeWaveColorAmount + cb*(1.0f - fMaximizeWaveColorAmount); + } + } + + float fWavePosX = cx*2.0f - 1.0f; // go from 0..1 user-range to -1..1 D3D range + float fWavePosY = cy*2.0f - 1.0f; + + float bass_rel = mysound.imm[0]; + float mid_rel = mysound.imm[1]; + float treble_rel = mysound.imm[2]; + + int sample_offset = 0; + int new_wavemode = (int)(*m_pState->var_pf_wave_mode) % NUM_WAVES; // since it can be changed from per-frame code! + + int its = (m_pState->m_bBlending && (new_wavemode != m_pState->m_nOldWaveMode)) ? 2 : 1; + int nVerts1 = 0; + int nVerts2 = 0; + int nBreak1 = -1; + int nBreak2 = -1; + float alpha1, alpha2; + + for (int it=0; itm_nOldWaveMode; + int nVerts = NUM_WAVEFORM_SAMPLES; // allowed to peek ahead 64 (i.e. left is [i], right is [i+64]) + int nBreak = -1; + + WFVERTEX *v = (it==0) ? v1 : v2; + ZeroMemory(v, sizeof(WFVERTEX)*nVerts); + + float alpha = (float)(*m_pState->var_pf_wave_a);//m_pState->m_fWaveAlpha.eval(GetTime()); + + switch(wave) + { + case 0: + // circular wave + + nVerts /= 2; + sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts * 12/10); // only call this once nVerts is final! + + if (m_pState->m_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + { + float inv_nverts_minus_one = 1.0f/(float)(nVerts-1); + + for (i=0; im_bBlending) + { + nVerts++; + memcpy(&v[nVerts-1], &v[0], sizeof(WFVERTEX)); + } + + break; + + case 1: + // x-y osc. that goes around in a spiral, in time + + alpha *= 1.25f; + if (m_pState->m_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + nVerts /= 2; + + for (i=0; im_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + for (i=0; im_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + for (i=0; i m_nTexSize/3) + nVerts = m_nTexSize/3; + + sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts + 25); // only call this once nVerts is final! + + /* + if (treble_rel > treb_thresh_for_wave6) + { + //alpha = 1.0f; + treb_thresh_for_wave6 = treble_rel * 1.025f; + } + else + { + alpha *= 0.2f; + treb_thresh_for_wave6 *= 0.996f; // fixme: make this fps-independent + } + */ + + if (m_pState->m_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + { + float w1 = 0.45f + 0.5f*(fWaveParam*0.5f + 0.5f); // 0.1 - 0.9 + float w2 = 1.0f - w1; + + float inv_nverts = 1.0f/(float)(nVerts); + + for (i=0; i1) + { + v[i].x = v[i].x*w2 + w1*(v[i-1].x*2.0f - v[i-2].x); + v[i].y = v[i].y*w2 + w1*(v[i-1].y*2.0f - v[i-2].y); + } + } + + /* + // center on Y + float avg_y = 0; + for (i=0; im_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + { + float cos_rot = cosf(GetTime()*0.3f); + float sin_rot = sinf(GetTime()*0.3f); + + for (i=0; i m_nTexSize/3) + nVerts = m_nTexSize/3; + + if (wave==8) + nVerts = 256; + else + sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts); // only call this once nVerts is final! + + if (m_pState->m_bModWaveAlphaByVolume) + alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime())); + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha); + + { + float ang = 1.57f*fWaveParam; // from -PI/2 to PI/2 + float dx = cosf(ang); + float dy = sinf(ang); + + float edge_x[2], edge_y[2]; + + //edge_x[0] = fWavePosX - dx*3.0f; + //edge_y[0] = fWavePosY - dy*3.0f; + //edge_x[1] = fWavePosX + dx*3.0f; + //edge_y[1] = fWavePosY + dy*3.0f; + edge_x[0] = fWavePosX*cosf(ang + 1.57f) - dx*3.0f; + edge_y[0] = fWavePosX*sinf(ang + 1.57f) - dy*3.0f; + edge_x[1] = fWavePosX*cosf(ang + 1.57f) + dx*3.0f; + edge_y[1] = fWavePosX*sinf(ang + 1.57f) + dy*3.0f; + + + for (i=0; i<2; i++) // for each point defining the line + { + // clip the point against 4 edges of screen + // be a bit lenient (use +/-1.1 instead of +/-1.0) + // so the dual-wave doesn't end too soon, after the channels are moved apart + for (int j=0; j<4; j++) + { + float t; + bool bClip = false; + + switch(j) + { + case 0: + if (edge_x[i] > 1.1f) + { + t = (1.1f - edge_x[1-i]) / (edge_x[i] - edge_x[1-i]); + bClip = true; + } + break; + case 1: + if (edge_x[i] < -1.1f) + { + t = (-1.1f - edge_x[1-i]) / (edge_x[i] - edge_x[1-i]); + bClip = true; + } + break; + case 2: + if (edge_y[i] > 1.1f) + { + t = (1.1f - edge_y[1-i]) / (edge_y[i] - edge_y[1-i]); + bClip = true; + } + break; + case 3: + if (edge_y[i] < -1.1f) + { + t = (-1.1f - edge_y[1-i]) / (edge_y[i] - edge_y[1-i]); + bClip = true; + } + break; + } + + if (bClip) + { + float dx = edge_x[i] - edge_x[1-i]; + float dy = edge_y[i] - edge_y[1-i]; + edge_x[i] = edge_x[1-i] + dx*t; + edge_y[i] = edge_y[1-i] + dy*t; + } + } + } + + dx = (edge_x[1] - edge_x[0]) / (float)nVerts; + dy = (edge_y[1] - edge_y[0]) / (float)nVerts; + float ang2 = atan2f(dy,dx); + float perp_dx = cosf(ang2 + 1.57f); + float perp_dy = sinf(ang2 + 1.57f); + + if (wave == 6) + for (i=0; ivar_pf_wave_usedots) ? D3DPT_POINTLIST : D3DPT_LINESTRIP; + //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v, nVerts, NULL); + + for (i=0; im_fBlendProgress); + float mix2 = 1.0f - mix; + + // blend 2 waveforms + if (nVerts2 > 0) + { + // note: this won't yet handle the case where (nBreak1 > 0 && nBreak2 > 0) + // in this case, code must break wave into THREE segments + float m = (nVerts2-1)/(float)nVerts1; + float x,y; + for (int i=0; i 0) + { + alpha1 = alpha1*(mix) + alpha2*(1.0f-mix); + } + + // apply color & alpha + // ALSO reverse all y values, to stay consistent with the pre-VMS milkdrop, + // which DIDN'T: + v1[0].Diffuse = D3DCOLOR_RGBA_01(cr, cg, cb, alpha1); + for (i=0; ivar_pf_wave_usedots) ? D3DPT_POINTLIST : D3DPT_LINESTRIP; + float x_inc = 2.0f / (float)m_nTexSize; + int drawing_its = ((*m_pState->var_pf_wave_thick || *m_pState->var_pf_wave_usedots) && (m_nTexSize >= 512)) ? 4 : 1; + + for (int it=0; itDrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v1, nVerts1, NULL); + if (*m_pState->var_pf_wave_usedots) + lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nVerts1, (void*)v1, sizeof(WFVERTEX)); + else + lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts1-1, (void*)v1, sizeof(WFVERTEX)); + } + else + { + //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v1, nBreak1, NULL); + //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)&v1[nBreak1], nVerts1-nBreak1, NULL); + if (*m_pState->var_pf_wave_usedots) + { + lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nBreak1, (void*)v1, sizeof(WFVERTEX)); + lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nVerts1-nBreak1, (void*)&v1[nBreak1], sizeof(WFVERTEX)); + } + else + { + lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nBreak1-1, (void*)v1, sizeof(WFVERTEX)); + lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts1-nBreak1-1, (void*)&v1[nBreak1], sizeof(WFVERTEX)); + } + } + } + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); +} + + + +void CPlugin::DrawSprites() +{ + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, NULL); + lpDevice->SetFVF( WFVERTEX_FORMAT ); + + if (*m_pState->var_pf_darken_center) + { + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);//SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + WFVERTEX v3[6]; + ZeroMemory(v3, sizeof(WFVERTEX)*6); + + // colors: + v3[0].Diffuse = D3DCOLOR_RGBA_01(0, 0, 0, 3.0f/32.0f); + v3[1].Diffuse = D3DCOLOR_RGBA_01(0, 0, 0, 0.0f/32.0f); + v3[2].Diffuse = v3[1].Diffuse; + v3[3].Diffuse = v3[1].Diffuse; + v3[4].Diffuse = v3[1].Diffuse; + v3[5].Diffuse = v3[1].Diffuse; + + // positioning: + float fHalfSize = 0.05f; + v3[0].x = 0.0f; + v3[1].x = 0.0f - fHalfSize*ASPECT; + v3[2].x = 0.0f; + v3[3].x = 0.0f + fHalfSize*ASPECT; + v3[4].x = 0.0f; + v3[5].x = v3[1].x; + v3[0].y = 0.0f; + v3[1].y = 0.0f; + v3[2].y = 0.0f - fHalfSize; + v3[3].y = 0.0f; + v3[4].y = 0.0f + fHalfSize; + v3[5].y = v3[1].y; + //v3[0].tu = 0; v3[1].tu = 1; v3[2].tu = 0; v3[3].tu = 1; + //v3[0].tv = 1; v3[1].tv = 1; v3[2].tv = 0; v3[3].tv = 0; + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 4, (LPVOID)v3, sizeof(WFVERTEX)); + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + + + // do borders + { + float fOuterBorderSize = (float)*m_pState->var_pf_ob_size; + float fInnerBorderSize = (float)*m_pState->var_pf_ib_size; + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + for (int it=0; it<2; it++) + { + WFVERTEX v3[4]; + ZeroMemory(v3, sizeof(WFVERTEX)*4); + + // colors: + float r = (it==0) ? (float)*m_pState->var_pf_ob_r : (float)*m_pState->var_pf_ib_r; + float g = (it==0) ? (float)*m_pState->var_pf_ob_g : (float)*m_pState->var_pf_ib_g; + float b = (it==0) ? (float)*m_pState->var_pf_ob_b : (float)*m_pState->var_pf_ib_b; + float a = (it==0) ? (float)*m_pState->var_pf_ob_a : (float)*m_pState->var_pf_ib_a; + if (a > 0.001f) + { + v3[0].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a); + v3[1].Diffuse = v3[0].Diffuse; + v3[2].Diffuse = v3[0].Diffuse; + v3[3].Diffuse = v3[0].Diffuse; + + // positioning: + float fInnerRad = (it==0) ? 1.0f - fOuterBorderSize : 1.0f - fOuterBorderSize - fInnerBorderSize; + float fOuterRad = (it==0) ? 1.0f : 1.0f - fOuterBorderSize; + v3[0].x = fInnerRad; + v3[1].x = fOuterRad; + v3[2].x = fOuterRad; + v3[3].x = fInnerRad; + v3[0].y = fInnerRad; + v3[1].y = fOuterRad; + v3[2].y = -fOuterRad; + v3[3].y = -fInnerRad; + + for (int rot=0; rot<4; rot++) + { + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, (LPVOID)v3, sizeof(WFVERTEX)); + + // rotate by 90 degrees + for (int v=0; v<4; v++) + { + float t = 1.570796327f; + float x = v3[v].x; + float y = v3[v].y; + v3[v].x = x*cosf(t) - y*sinf(t); + v3[v].y = x*sinf(t) + y*cosf(t); + } + } + } + } + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } +} + +/* +bool CPlugin::SetMilkdropRenderTarget(LPDIRECTDRAWSURFACE7 lpSurf, int w, int h, char *szErrorMsg) +{ + HRESULT hr = m_lpD3DDev->SetRenderTarget(lpSurf, 0); + if (hr != D3D_OK) + { + //if (szErrorMsg && szErrorMsg[0]) dumpmsg(szErrorMsg); + //IdentifyD3DError(hr); + return false; + } + + //DDSURFACEDESC2 ddsd; + //ddsd.dwSize = sizeof(ddsd); + //lpSurf->GetSurfaceDesc(&ddsd); + + D3DVIEWPORT7 viewData; + ZeroMemory(&viewData, sizeof(D3DVIEWPORT7)); + viewData.dwWidth = w; // not: in windowed mode, when lpSurf is the back buffer, chances are good that w,h are smaller than the full surface size (since real size is fullscreen, but we're only using a portion of it as big as the window). + viewData.dwHeight = h; + hr = m_lpD3DDev->SetViewport(&viewData); + + return true; +} +*/ + +void CPlugin::DrawUserSprites() // from system memory, to back buffer. +{ +#if 0 + + LPDIRECT3DDEVICE8 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, NULL); + lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT ); + + lpDevice->SetRenderState(D3DRS_WRAP0, 0); + SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(0, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP); + + // reset these to the standard safe mode: + SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + /* + lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); //D3DSHADE_GOURAUD + lpDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); + lpDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + if (m_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER) + lpDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + lpDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + lpDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE); + lpDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); // vs. wireframe + lpDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA_01(1,1,1,1)); + SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR ); + SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR ); + SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR ); + */ + + for (int iSlot=0; iSlot < NUM_TEX; iSlot++) + { + if (m_texmgr.m_tex[iSlot].pSurface) + { + int k; + + // set values of input variables: + *(m_texmgr.m_tex[iSlot].var_time) = (double)(GetTime() - m_texmgr.m_tex[iSlot].fStartTime); + *(m_texmgr.m_tex[iSlot].var_frame) = (double)(GetFrame() - m_texmgr.m_tex[iSlot].nStartFrame); + *(m_texmgr.m_tex[iSlot].var_fps) = (double)GetFps(); + *(m_texmgr.m_tex[iSlot].var_progress) = (double)m_pState->m_fBlendProgress; + *(m_texmgr.m_tex[iSlot].var_bass) = (double)mysound.imm_rel[0]; + *(m_texmgr.m_tex[iSlot].var_mid) = (double)mysound.imm_rel[1]; + *(m_texmgr.m_tex[iSlot].var_treb) = (double)mysound.imm_rel[2]; + *(m_texmgr.m_tex[iSlot].var_bass_att) = (double)mysound.avg_rel[0]; + *(m_texmgr.m_tex[iSlot].var_mid_att) = (double)mysound.avg_rel[1]; + *(m_texmgr.m_tex[iSlot].var_treb_att) = (double)mysound.avg_rel[2]; + + // evaluate expressions + #ifndef _NO_EXPR_ + if (m_texmgr.m_tex[iSlot].m_codehandle) + { + resetVars(m_texmgr.m_tex[iSlot].m_vars); + executeCode(m_texmgr.m_tex[iSlot].m_codehandle); + resetVars(NULL); + } + #endif + + bool bKillSprite = (*m_texmgr.m_tex[iSlot].var_done != 0.0); + bool bBurnIn = (*m_texmgr.m_tex[iSlot].var_burn != 0.0); + + // Remember the original backbuffer and zbuffer + LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer; + lpDevice->GetRenderTarget( &pBackBuffer ); + lpDevice->GetDepthStencilSurface( &pZBuffer ); + + if (/*bKillSprite &&*/ bBurnIn) + { + // set up to render [from NULL] to VS1 (for burn-in). + + lpDevice->SetTexture(0, NULL); + + IDirect3DSurface8* pNewTarget = NULL; + if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK) + return; + lpDevice->SetRenderTarget(pNewTarget, NULL); + pNewTarget->Release(); + + lpDevice->SetTexture(0, NULL); + } + + // finally, use the results to draw the sprite. + if (lpDevice->SetTexture(0, m_texmgr.m_tex[iSlot].pSurface) != D3D_OK) + return; + + SPRITEVERTEX v3[4]; + ZeroMemory(v3, sizeof(SPRITEVERTEX)*4); + + /* + int dest_w, dest_h; + { + LPDIRECT3DSURFACE8 pRT; + lpDevice->GetRenderTarget( &pRT ); + + D3DSURFACE_DESC desc; + pRT->GetDesc(&desc); + dest_w = desc.Width; + dest_h = desc.Height; + pRT->Release(); + }*/ + + float x = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_x) * 2.0f - 1.0f )); + float y = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_y) * 2.0f - 1.0f )); + float sx = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_sx) )); + float sy = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_sy) )); + float rot = (float)(*m_texmgr.m_tex[iSlot].var_rot); + int flipx = (*m_texmgr.m_tex[iSlot].var_flipx == 0.0) ? 0 : 1; + int flipy = (*m_texmgr.m_tex[iSlot].var_flipy == 0.0) ? 0 : 1; + float repeatx = min(100.0f, max(0.01f, (float)(*m_texmgr.m_tex[iSlot].var_repeatx) )); + float repeaty = min(100.0f, max(0.01f, (float)(*m_texmgr.m_tex[iSlot].var_repeaty) )); + + int blendmode = min(4, max(0, ((int)(*m_texmgr.m_tex[iSlot].var_blendmode)))); + float r = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_r)))); + float g = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_g)))); + float b = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_b)))); + float a = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_a)))); + + // set x,y coords + v3[0+flipx].x = -sx; + v3[1-flipx].x = sx; + v3[2+flipx].x = -sx; + v3[3-flipx].x = sx; + v3[0+flipy*2].y = -sy; + v3[1+flipy*2].y = -sy; + v3[2-flipy*2].y = sy; + v3[3-flipy*2].y = sy; + + // first aspect ratio: adjust for non-1:1 images + { + float aspect = m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].img_w; + + if (aspect < 1) + for (k=0; k<4; k++) v3[k].y *= aspect; // wide image + else + for (k=0; k<4; k++) v3[k].x /= aspect; // tall image + } + + // 2D rotation + { + float cos_rot = cosf(rot); + float sin_rot = sinf(rot); + for (k=0; k<4; k++) + { + float x2 = v3[k].x*cos_rot - v3[k].y*sin_rot; + float y2 = v3[k].x*sin_rot + v3[k].y*cos_rot; + v3[k].x = x2; + v3[k].y = y2; + } + } + + // translation + for (k=0; k<4; k++) + { + v3[k].x += x; + v3[k].y += y; + } + + // second aspect ratio: normalize to width of screen + { + float aspect = GetWidth() / (float)(GetHeight()); + + if (aspect > 1) + for (k=0; k<4; k++) v3[k].y *= aspect; + else + for (k=0; k<4; k++) v3[k].x /= aspect; + } + + // third aspect ratio: adjust for burn-in + if (bKillSprite && bBurnIn) // final render-to-VS1 + { + float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f); + if (aspect < 1.0f) + for (k=0; k<4; k++) v3[k].x *= aspect; + else + for (k=0; k<4; k++) v3[k].y /= aspect; + } + + // finally, flip 'y' for annoying DirectX + //for (k=0; k<4; k++) v3[k].y *= -1.0f; + + // set u,v coords + { + float dtu = 0.5f;// / (float)m_texmgr.m_tex[iSlot].tex_w; + float dtv = 0.5f;// / (float)m_texmgr.m_tex[iSlot].tex_h; + v3[0].tu = -dtu; + v3[1].tu = dtu;///*m_texmgr.m_tex[iSlot].img_w / (float)m_texmgr.m_tex[iSlot].tex_w*/ - dtu; + v3[2].tu = -dtu; + v3[3].tu = dtu;///*m_texmgr.m_tex[iSlot].img_w / (float)m_texmgr.m_tex[iSlot].tex_w*/ - dtu; + v3[0].tv = -dtv; + v3[1].tv = -dtv; + v3[2].tv = dtv;///*m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].tex_h*/ - dtv; + v3[3].tv = dtv;///*m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].tex_h*/ - dtv; + + // repeat on x,y + for (k=0; k<4; k++) + { + v3[k].tu = (v3[k].tu - 0.0f)*repeatx + 0.5f; + v3[k].tv = (v3[k].tv - 0.0f)*repeaty + 0.5f; + } + } + + // blendmodes src alpha: dest alpha: + // 0 blend r,g,b=modulate a=opacity SRCALPHA INVSRCALPHA + // 1 decal r,g,b=modulate a=modulate D3DBLEND_ONE D3DBLEND_ZERO + // 2 additive r,g,b=modulate a=modulate D3DBLEND_ONE D3DBLEND_ONE + // 3 srccolor r,g,b=no effect a=no effect SRCCOLOR INVSRCCOLOR + // 4 colorkey r,g,b=modulate a=no effect + switch(blendmode) + { + case 0: + default: + // alpha blend + + /* + Q. I am rendering with alpha blending and setting the alpha + of the diffuse vertex component to determine the opacity. + It works when there is no texture set, but as soon as I set + a texture the alpha that I set is no longer applied. Why? + + The problem originates in the texture blending stages, rather + than in the subsequent alpha blending. Alpha can come from + several possible sources. If this has not been specified, + then the alpha will be taken from the texture, if one is selected. + If no texture is selected, then the default will use the alpha + channel of the diffuse vertex component. + + Explicitly specifying the diffuse vertex component as the source + for alpha will insure that the alpha is drawn from the alpha value + you set, whether a texture is selected or not: + + pDevice->SetTextureStageState(D3DTSS_ALPHAOP,D3DTOP_SELECTARG1); + pDevice->SetTextureStageState(D3DTSS_ALPHAARG1,D3DTA_DIFFUSE); + + If you later need to use the texture alpha as the source, set + D3DTSS_ALPHAARG1 to D3DTA_TEXTURE. + */ + + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a); + break; + case 1: + // decal + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + //lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + //lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); + for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r*a,g*a,b*a,1); + break; + case 2: + // additive + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r*a,g*a,b*a,1); + break; + case 3: + // srccolor + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); + for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(1,1,1,1); + break; + case 4: + // color keyed texture: use the alpha value in the texture to + // determine which texels get drawn. + /*lpDevice->SetRenderState(D3DRS_ALPHAREF, 0); + lpDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL); + lpDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); + */ + + SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + // also, smoothly blend this in-between texels: + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a); + break; + } + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (LPVOID)v3, sizeof(SPRITEVERTEX)); + + if (/*bKillSprite &&*/ bBurnIn) // final render-to-VS1 + { + // Change the rendertarget back to the original setup + lpDevice->SetTexture(0, NULL); + lpDevice->SetRenderTarget( pBackBuffer, pZBuffer ); + lpDevice->SetTexture(0, m_texmgr.m_tex[iSlot].pSurface); + + // undo aspect ratio changes (that were used to fit it to VS1): + { + float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f); + if (aspect < 1.0f) + for (k=0; k<4; k++) v3[k].x /= aspect; + else + for (k=0; k<4; k++) v3[k].y *= aspect; + } + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (LPVOID)v3, sizeof(SPRITEVERTEX)); + } + + SafeRelease(pBackBuffer); + SafeRelease(pZBuffer); + + if (bKillSprite) + { + KillSprite(iSlot); + } + + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + } + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + + // reset these to the standard safe mode: + SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); +#endif +} + +void CPlugin::ShowToUser(int bRedraw) +{ + LPDIRECT3DDEVICE9 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, m_lpVS[1]); + lpDevice->SetFVF( SPRITEVERTEX_FORMAT ); + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + + float fZoom = 1.0f; + SPRITEVERTEX v3[4]; + ZeroMemory(v3, sizeof(SPRITEVERTEX)*4); + + D3DRECT rect; + rect.x1 = m_posX; + rect.x2 = m_posX + GetWidth(); + rect.y1 = m_posY; + rect.y2 = m_posY + GetHeight(); + + // WISO: lpDevice->SetScissors(1, false, &rect); + + + // extend the poly we draw by 1 pixel around the viewable image area, + // in case the video card wraps u/v coords with a +0.5-texel offset + // (otherwise, a 1-pixel-wide line of the image would wrap at the top and left edges). + +/* + float fOnePlusInvWidth = 1.0f + 1.0f/(float)GetWidth(); + float fOnePlusInvHeight = 1.0f + 1.0f/(float)GetHeight(); + + v3[0].x = -fOnePlusInvWidth; + v3[1].x = fOnePlusInvWidth; + v3[2].x = -fOnePlusInvWidth; + v3[3].x = fOnePlusInvWidth; + v3[0].y = fOnePlusInvHeight; + v3[1].y = fOnePlusInvHeight; + v3[2].y = -fOnePlusInvHeight; + v3[3].y = -fOnePlusInvHeight; +*/ + + v3[0].x = ((m_posX / (float)m_backBufferWidth) * 2.0f) - 1.0f; + v3[1].x = (((m_posX + GetWidth()) / (float)m_backBufferWidth) * 2.0f) - 1.0f; + v3[2].x = v3[0].x; + v3[3].x = v3[1].x; + v3[0].y = (((m_posY + GetHeight()) / (float)m_backBufferHeight) * 2.0f) - 1.0f; + v3[1].y = v3[0].y; + v3[2].y = ((m_posY / (float)m_backBufferHeight) * 2.0f) - 1.0f; + v3[3].y = v3[2].y; + + + + float aspect = (float)GetWidth() / (GetHeight() / ASPECT); // normal aspect in 1:1 pixels + aspect *= m_pixelRatio; // adjust for non-square TV pixels + float x_aspect_mult = 1.0f; + float y_aspect_mult = 1.0f; + + if (aspect>1) + y_aspect_mult = aspect; + else + x_aspect_mult = 1.0f/aspect; + + for (int n=0; n<4; n++) + { + v3[n].x *= x_aspect_mult; + v3[n].y *= y_aspect_mult; + } + + float xRange = v3[1].x - v3[0].x; + float yRange = v3[0].y - v3[2].y; + + + if (m_pState->m_bRedBlueStereo || m_bAlways3D) + { + // red/blue stereo 3D + // NOTE: video echo is not yet supported. + // NOTE: gamma IS now supported (As of v1.04), but it's really slow. + // -no biggie though; 3d effect dies w/high gamma, so it won't get used beyond 2.0X. + + float fGammaAdj = (float)*m_pState->var_pf_gamma;//m_pState->m_fGammaAdj.eval(GetTime()); + int gamma_passes = (int)(fGammaAdj + 0.999f); + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + + for (int pass=0; pass 1) m_verts[n].tu = 1; + } + else + { + //float du = fabsf((m_verts[n].x*0.5f + 0.5f) - m_verts[n].tu); + //float dv = fabsf(0.5f - (m_verts[n].y*0.5f) - m_verts[n].tv); + //float mag_motion = sqrtf(du*du+dv*dv); + //m_verts[n].tu = (m_verts[n].x*0.5f + 0.5f) - mag_motion*0.3f; + m_verts[n].tu = m_verts[n].x + 1.0f - m_verts[n].tu; + //if (m_verts[n].tu < 0) m_verts[n].tu = 0; + //if (m_verts[n].tu > 1) m_verts[n].tu = 1; + } + + n++; + } + } + + if (rep==0) + m_verts_temp[0].Diffuse = D3DCOLOR_RGBA_01(m_cRightEye3DColor[0]*colormult,m_cRightEye3DColor[1]*colormult,m_cRightEye3DColor[2]*colormult,1); // should be the color of right lens (~red) + else + m_verts_temp[0].Diffuse = D3DCOLOR_RGBA_01(m_cLeftEye3DColor[0]*colormult,m_cLeftEye3DColor[1]*colormult,m_cLeftEye3DColor[2]*colormult,1); // should be the color of left lens (~blue) + + for (int poly=1; polyDrawPrimitiveUP(D3DPT_TRIANGLESTRIP, m_nGridX, (void*)m_verts_temp, sizeof(SPRITEVERTEX)); + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + } + } + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + + } + else // regular display (non-stereo) + + { + float shade[4][3] = { + { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f } }; // for each vertex, then each comp. + + float fShaderAmount = m_pState->m_fShader.eval(GetTime()); + + if (fShaderAmount > 0.001f) + { + for (int i=0; i<4; i++) + { + shade[i][0] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0143f + 3 + i*21 + m_fRandStart[3]); + shade[i][1] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0107f + 1 + i*13 + m_fRandStart[1]); + shade[i][2] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0129f + 6 + i*9 + m_fRandStart[2]); + float max = ((shade[i][0] > shade[i][1]) ? shade[i][0] : shade[i][1]); + if (shade[i][2] > max) max = shade[i][2]; + for (int k=0; k<3; k++) + { + shade[i][k] /= max; + shade[i][k] = 0.5f + 0.5f*shade[i][k]; + } + for (int k=0; k<3; k++) + { + shade[i][k] = shade[i][k]*(fShaderAmount) + 1.0f*(1.0f - fShaderAmount); + } + v3[i].Diffuse = D3DCOLOR_RGBA_01(shade[i][0],shade[i][1],shade[i][2],1); + } + } + + float fVideoEchoZoom = (float)(*m_pState->var_pf_echo_zoom);//m_pState->m_fVideoEchoZoom.eval(GetTime()); + float fVideoEchoAlpha = (float)(*m_pState->var_pf_echo_alpha);//m_pState->m_fVideoEchoAlpha.eval(GetTime()); + int nVideoEchoOrientation = (int) (*m_pState->var_pf_echo_orient) % 4;//m_pState->m_nVideoEchoOrientation; + float fGammaAdj = (float)(*m_pState->var_pf_gamma);//m_pState->m_fGammaAdj.eval(GetTime()); + + if (m_pState->m_bBlending && + m_pState->m_fVideoEchoAlpha.eval(GetTime()) > 0.01f && + m_pState->m_fVideoEchoAlphaOld > 0.01f && + m_pState->m_nVideoEchoOrientation != m_pState->m_nVideoEchoOrientationOld) + { + if (m_pState->m_fBlendProgress < 0.5f) + { + nVideoEchoOrientation = m_pState->m_nVideoEchoOrientationOld; + fVideoEchoAlpha *= 1.0f - 2.0f*CosineInterp(m_pState->m_fBlendProgress); + } + else + { + fVideoEchoAlpha *= 2.0f*CosineInterp(m_pState->m_fBlendProgress) - 1.0f; + } + } + + if (fVideoEchoAlpha > 0.001f) + { + // video echo + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); + + for (int i=0; i<2; i++) + { + fZoom = (i==0) ? 1.0f : fVideoEchoZoom; + + float temp_lo = (0.5f - 0.5f/fZoom) + 0.5f / m_nTexSize; + float temp_hi = (0.5f + 0.5f/fZoom) + 0.5f / m_nTexSize; + + v3[0].tu = temp_lo; + v3[0].tv = temp_hi; + v3[1].tu = temp_hi; + v3[1].tv = temp_hi; + v3[2].tu = temp_lo; + v3[2].tv = temp_lo; + v3[3].tu = temp_hi; + v3[3].tv = temp_lo; + + // flipping + if (i==1) + { + for (int j=0; j<4; j++) + { + if (nVideoEchoOrientation % 2) + v3[j].tu = 1.0f - v3[j].tu; + if (nVideoEchoOrientation >= 2) + v3[j].tv = 1.0f - v3[j].tv; + } + } + + float mix = (i==1) ? fVideoEchoAlpha : 1.0f - fVideoEchoAlpha; + for (int k=0; k<4; k++) + v3[k].Diffuse = D3DCOLOR_RGBA_01(mix*shade[k][0],mix*shade[k][1],mix*shade[k][2],1); + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + if (i==0) + { + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + } + + if (fGammaAdj > 0.001f) + { + // draw layer 'i' a 2nd (or 3rd, or 4th...) time, additively + int nRedraws = (int)(fGammaAdj - 0.0001f); + float gamma; + + for (int nRedraw=0; nRedraw < nRedraws; nRedraw++) + { + if (nRedraw == nRedraws-1) + gamma = fGammaAdj - (int)(fGammaAdj - 0.0001f); + else + gamma = 1.0f; + + for (int k=0; k<4; k++) + v3[k].Diffuse = D3DCOLOR_RGBA_01(gamma*mix*shade[k][0],gamma*mix*shade[k][1],gamma*mix*shade[k][2],1); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + } + } + } + } + else + { + // no video echo + v3[0].tu = 0.5f / m_nTexSize; v3[1].tu = 1; v3[2].tu = 0.5f / m_nTexSize; v3[3].tu = 1; + v3[0].tv = 1; v3[1].tv = 1; v3[2].tv = 0.5f / m_nTexSize; v3[3].tv = 0.5f / m_nTexSize; + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); + + // draw it iteratively, solid the first time, and additively after that + int nPasses = (int)(fGammaAdj - 0.001f) + 1; + float gamma; + + for (int nPass=0; nPass < nPasses; nPass++) + { + if (nPass == nPasses - 1) + gamma = fGammaAdj - (float)nPass; + else + gamma = 1.0f; + + for (int k=0; k<4; k++) + v3[k].Diffuse = D3DCOLOR_RGBA_01(gamma*shade[k][0],gamma*shade[k][1],gamma*shade[k][2],1); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + if (nPass==0) + { + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + } + } + } +/* + SPRITEVERTEX v3[4]; + ZeroMemory(v3, sizeof(SPRITEVERTEX)*4); + float fOnePlusInvWidth = 1.0f + 1.0f/(float)GetWidth(); + float fOnePlusInvHeight = 1.0f + 1.0f/(float)GetHeight(); + v3[0].x = -fOnePlusInvWidth; + v3[1].x = fOnePlusInvWidth; + v3[2].x = -fOnePlusInvWidth; + v3[3].x = fOnePlusInvWidth; + v3[0].y = fOnePlusInvHeight; + v3[1].y = fOnePlusInvHeight; + v3[2].y = -fOnePlusInvHeight; + v3[3].y = -fOnePlusInvHeight; +*/ + for (int i=0; i<4; i++) v3[i].Diffuse = D3DCOLOR_RGBA_01(1,1,1,1); + + if (*m_pState->var_pf_brighten && + (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR ) && + (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_DESTCOLOR) + ) + { + // square root filter + + //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //? + //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //? + + lpDevice->SetTexture(0, NULL); + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + // first, a perfect invert + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + // then modulate by self (square it) + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + // then another perfect invert + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + } + + if (*m_pState->var_pf_darken && + (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_DESTCOLOR) + ) + { + // squaring filter + + //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //? + //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //? + + lpDevice->SetTexture(0, NULL); + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + //lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR); + //lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + //lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + } + + if (*m_pState->var_pf_solarize && + (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_DESTCOLOR ) && + (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR) + ) + { + //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //? + //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //? + + lpDevice->SetTexture(0, NULL); + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTCOLOR); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + } + + if (*m_pState->var_pf_invert && + (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR ) + ) + { + //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //? + //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //? + + lpDevice->SetTexture(0, NULL); + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX)); + } + + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } +} + + +void CPlugin::ShowSongTitleAnim(int w, int h, float fProgress) +{ +#if 0 + int i,x,y; + + if (!m_lpDDSTitle) // this *can* be NULL, if not much video mem! + return; + + LPDIRECT3DDEVICE8 lpDevice = GetDevice(); + if (!lpDevice) + return; + + lpDevice->SetTexture(0, m_lpDDSTitle); + lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT ); + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + + SPRITEVERTEX v3[128]; + ZeroMemory(v3, sizeof(SPRITEVERTEX)*128); + + if (m_supertext.bIsSongTitle) + { + // positioning: + float fSizeX = 50.0f / (float)m_supertext.nFontSizeUsed * powf(1.5f, m_supertext.fFontSize - 2.0f); + float fSizeY = fSizeX * m_nTitleTexSizeY/(float)m_nTitleTexSizeX;// * m_nWidth/(float)m_nHeight; + + if (fSizeX > 0.88f) + { + fSizeY *= 0.88f/fSizeX; + fSizeX = 0.88f; + } + + //fixme + if (fProgress < 1.0f)//(w!=h) // regular render-to-backbuffer + { + float aspect = w/(float)(h*4.0f/3.0f); + fSizeY *= aspect; + } + else // final render-to-VS0 + { + float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f); + if (aspect < 1.0f) + { + fSizeX *= aspect; + fSizeY *= aspect; + } + } + + //if (fSizeX > 0.92f) fSizeX = 0.92f; + //if (fSizeY > 0.92f) fSizeY = 0.92f; + i = 0; + float vert_clip = VERT_CLIP;//1.0f;//0.45f; // warning: visible clipping has been observed at 0.4! + for (y=0; y<8; y++) + { + for (x=0; x<16; x++) + { + v3[i].tu = x/15.0f; + v3[i].tv = (y/7.0f - 0.5f)*vert_clip + 0.5f; + v3[i].x = (v3[i].tu*2.0f - 1.0f)*fSizeX; + v3[i].y = (v3[i].tv*2.0f - 1.0f)*fSizeY; + i++; + } + } + + // warping + float ramped_progress = max(0.0f, 1-fProgress*1.5f); + float t2 = powf(ramped_progress, 1.8f)*1.3f; + for (y=0; y<8; y++) + { + for (x=0; x<16; x++) + { + i = y*16+x; + v3[i].x += t2*0.070f*sinf(GetTime()*0.31f + v3[i].x*0.39f - v3[i].y*1.94f); + v3[i].x += t2*0.044f*sinf(GetTime()*0.81f - v3[i].x*1.91f + v3[i].y*0.27f); + v3[i].x += t2*0.061f*sinf(GetTime()*1.31f + v3[i].x*0.61f + v3[i].y*0.74f); + v3[i].y += t2*0.061f*sinf(GetTime()*0.37f + v3[i].x*1.83f + v3[i].y*0.69f); + v3[i].y += t2*0.070f*sinf(GetTime()*0.67f + v3[i].x*0.42f - v3[i].y*1.39f); + v3[i].y += t2*0.087f*sinf(GetTime()*1.07f + v3[i].x*3.55f + v3[i].y*0.89f); + } + } + + // scale down over time + float scale = 1.01f/(powf(fProgress, 0.21f) + 0.01f); + for (i=0; i<128; i++) + { + v3[i].x *= scale; + v3[i].y *= scale; + } + } + else + { + // positioning: + float fSizeX = (float)m_nTexSize/1024.0f * 100.0f / (float)m_supertext.nFontSizeUsed * powf(1.033f, m_supertext.fFontSize - 50.0f); + float fSizeY = fSizeX * m_nTitleTexSizeY/(float)m_nTitleTexSizeX; + + //fixme + if (fProgress < 1.0f)//w!=h) // regular render-to-backbuffer + { + float aspect = w/(float)(h*4.0f/3.0f); + fSizeY *= aspect; + } + else // final render-to-VS0 + { + float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f); + if (aspect < 1.0f) + { + fSizeX *= aspect; + fSizeY *= aspect; + } + } + + //if (fSize > 0.92f) fSize = 0.92f; + i = 0; + float vert_clip = VERT_CLIP;//0.67f; // warning: visible clipping has been observed at 0.5 (for very short strings) and even 0.6 (for wingdings)! + for (y=0; y<8; y++) + { + for (x=0; x<16; x++) + { + v3[i].tu = x/15.0f; + v3[i].tv = (y/7.0f - 0.5f)*vert_clip + 0.5f; + v3[i].x = (v3[i].tu*2.0f - 1.0f)*fSizeX; + v3[i].y = (v3[i].tv*2.0f - 1.0f)*fSizeY; + i++; + } + } + + // apply 'growth' factor and move to user-specified (x,y) + //if (fabsf(m_supertext.fGrowth-1.0f) > 0.001f) + { + float t = (1.0f)*(1-fProgress) + (fProgress)*(m_supertext.fGrowth); + float dx = (m_supertext.fX*2-1); + float dy = (m_supertext.fY*2-1); + if (w!=h) // regular render-to-backbuffer + { + float aspect = w/(float)(h*4.0f/3.0f); + if (aspect < 1) + dx /= aspect; + else + dy *= aspect; + } + + for (i=0; i<128; i++) + { + // note: (x,y) are in (-1,1) range, but m_supertext.f{X|Y} are in (0..1) range + v3[i].x = (v3[i].x)*t + dx; + v3[i].y = (v3[i].y)*t + dy; + } + } + } + + WORD indices[7*15*6]; + i = 0; + for (y=0; y<7; y++) + { + for (x=0; x<15; x++) + { + indices[i++] = y*16 + x; + indices[i++] = y*16 + x + 1; + indices[i++] = y*16 + x + 16; + indices[i++] = y*16 + x + 1; + indices[i++] = y*16 + x + 16; + indices[i++] = y*16 + x + 17; + } + } + + // final flip on y + //for (i=0; i<128; i++) + // v3[i].y *= -1.0f; + for (i=0; i<128; i++) + v3[i].y /= ASPECT; + + for (int it=0; it<2; it++) + { + // colors + { + float t; + + if (m_supertext.bIsSongTitle) + t = powf(fProgress, 0.3f)*1.0f; + else + t = CosineInterp(min(1.0f, (fProgress/m_supertext.fFadeTime))); + + if (it==0) + v3[0].Diffuse = D3DCOLOR_RGBA_01(t,t,t,t); + else + v3[0].Diffuse = D3DCOLOR_RGBA_01(t*m_supertext.nColorR/255.0f,t*m_supertext.nColorG/255.0f,t*m_supertext.nColorB/255.0f,t); + + for (i=1; i<128; i++) + v3[i].Diffuse = v3[0].Diffuse; + } + + // nudge down & right for shadow, up & left for solid text + float offset_x = 0, offset_y = 0; + switch(it) + { + case 0: + offset_x = 2.0f/(float)m_nTitleTexSizeX; + offset_y = 2.0f/(float)m_nTitleTexSizeY; + break; + case 1: + offset_x = -4.0f/(float)m_nTitleTexSizeX; + offset_y = -4.0f/(float)m_nTitleTexSizeY; + break; + } + + for (i=0; i<128; i++) + { + v3[i].x += offset_x; + v3[i].y += offset_y; + } + + if (it == 0) + { + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);//SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); + } + else + { + lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCALPHA); + lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + } + + lpDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 128, 15*7*6/3, indices, D3DFMT_INDEX16, v3, sizeof(SPRITEVERTEX)); + } + + lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); +#endif +} diff --git a/lib/vis_milkdrop/plugin.cpp b/lib/vis_milkdrop/plugin.cpp new file mode 100644 index 0000000..35bb726 --- /dev/null +++ b/lib/vis_milkdrop/plugin.cpp @@ -0,0 +1,5782 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* +Order of Function Calls +----------------------- + The only code that will be called by the plugin framework are the + 12 virtual functions in plugin.h. But in what order are they called? + A breakdown follows. A function name in { } means that it is only + called under certain conditions. + + Order of function calls... + + When the PLUGIN launches + ------------------------ + INITIALIZATION + OverrideDefaults + MyPreInitialize + MyReadConfig + << DirectX gets initialized at this point >> + AllocateMyNonDx8Stuff + AllocateMyDX8Stuff + RUNNING + +--> { CleanUpMyDX8Stuff + AllocateMyDX8Stuff } // called together when user resizes window or toggles fullscreen<->windowed. + | MyRenderFn + | MyRenderUI + | { MyWindowProc } // called, between frames, on mouse/keyboard/system events. 100% threadsafe. + +----<< repeat >> + CLEANUP + CleanUpMyDX8Stuff + CleanUpMyNonDx8Stuff + << DirectX gets uninitialized at this point >> + + When the CONFIG PANEL launches + ------------------------------ + INITIALIZATION + OverrideDefaults + MyPreInitialize + MyReadConfig + << DirectX gets initialized at this point >> + RUNNING + { MyConfigTabProc } // called on startup & on keyboard events + CLEANUP + [ MyWriteConfig ] // only called if user clicked 'OK' to exit + << DirectX gets uninitialized at this point >> +*/ + +/* + NOTES + ----- + + To do + ----- + -VMS VERSION: + -based on vms 1.05, but the 'fix slow text' option has been added. + that includes m_lpDDSText, CTextManager (m_text), changes to + DrawDarkTranslucentBox, the replacement of all DrawText calls + (now routed through m_text), and adding the 'fix slow text' cb + to the config panel. + + -KILLED FEATURES: + -vj mode + + -NEW FEATURES FOR 1.04: + -added the following variables for per-frame scripting: (all booleans, except 'gamma') + wave_usedots, wave_thick, wave_additive, wave_brighten + gamma, darken_center, wrap, invert, brighten, darken, solarize + (also, note that echo_zoom, echo_alpha, and echo_orient were already in there, + but weren't covered in the documentation!) + d -fixed: spectrum w/512 samples + 256 separation -> infinite spike + d -reverted dumb changes to aspect ratio stuff + d -reverted wave_y fix; now it's backwards, just like it's always been + (i.e. for wave's y position, 0=bottom and 1=top, which is opposite + to the convention in the rest of milkdrop. decided to keep the + 'bug' so presets don't need modified.) + d -fixed: Krash: Inconsistency bug - pressing Escape while in the code windows + for custom waves completely takes you out of the editing menus, + rather than back to the custom wave menu + d -when editing code: fix display of '&' character + d -internal texture size now has a little more bias toward a finer texture, + based on the window size, when set to 'Auto'. (Before, for example, + to reach 1024x1024, the window had to be 768x768 or greater; now, it + only has to be 640x640 (25% of the way there). I adjusted it because + before, at in-between resolutions like 767x767, it looked very grainy; + now it will always look nice and crisp, at any window size, but still + won't cause too much aliasing (due to downsampling for display). + d -fixed: rova: + When creating presets have commented code // in the per_pixel section when cause error in preset. + Example nothing in per_frame and just comments in the per_pixel. EXamples on repuest I have a few. + d -added kill keys: + -CTRL+K kills all running sprites + -CTRL+T kills current song title anim + -CTRL+Y kills current custom message + d -notice to sprite users: + -in milk_img.ini, color key can't be a range anymore; it's + now limited to just a single color. 'colorkey_lo' and + 'colorkey_hi' have been replaced with just one setting, + 'colorkey'. + d -song titles + custom messages are working again + ? -fixed?: crashes on window resize [out of mem] + -Rova: BTW the same bug as krash with the window resizing. + -NOT due to the 'integrate w/winamp' option. + -> might be fixed now (had forgotten to release m_lpDDSText) + + d -added checkbox to config screen to automatically turn SCROLL LOCK on @ startup + d -added alphanumeric seeking to the playlist; while playlist is up, + you can now press A-Z and 0-9 to seek to the next song in the playlist + that starts with that character. + d - + d - + d - + d - + d - + ? - + ? - + ? - + d - + d - + d - + d - + d - + + -now when playlist is up, SHIFT+A-Z seeks upward (while lowercase/regular a-z seeks downward). + -custom shapes: + -OH MY GOD + -increased max. # of custom shapes (and waves) from 3 to 4 + -added 'texture' option, which allows you to use the last frame as a texture on the shape + -added "tex_ang" and "tex_zoom" params to control the texture coords + -each frame, custom shapes now draw BEFORE regular waveform + custom waves + -added init + per-frame vars: "texture", "additive", "thick", "tex_ang", "tex_zoom" + -fixed valid characters for filenames when importing/exporting custom shapes/waves; + also, it now gives error messages on error in import/export. + -cranked max. meshsize up to 96x72 + -Krash, Rova: now the 'q' variables, as modified by the preset per-frame equations, are again + readable by the custom waves + custom shapes. Sorry about that. Should be the end of the + 'q' confusion. + -added 'meshx' and 'meshy' [read-only] variables to the preset init, per-frame, and per-pixel + equations (...and inc'd the size of the global variable pool by 2). + -removed t1-t8 vars for Custom Shapes; they were unnecessary (since there's no per-point code there). + -protected custom waves from trying to draw when # of sample minus the separation is < 2 + (or 1 if drawing with dots) + -fixed some [minor] preset-blending bugs in the custom wave code + -created a visual map for the flow of values for the q1-q8 and t1-t8 variables: + q_and_t_vars.gif (or something). + -fixed clipping of onscreen text in low-video-memory situations. Now, if there isn't enough + video memory to create an offscreen texture that is at least 75% of the size of the + screen (or to create at least a 256x256 one), it won't bother using one, and will instead draw text directly to the screen. + Otherwise, if the texture is from 75%-99% of the screen size, text will now at least + appear in the correct position on the screen so that it will be visible; this will mean + that the right- and bottom-aligned text will no longer be fully right/bottom-aligned + to the edge of the screen. + -fixed blurry text + -VJ mode is partially restored; the rest will come with beta 7 or the final release. At the time of beta 6, VJ mode still has some glitches in it, but I'm working on them. Most notably, it doesn't resize the text image when you resize the window; that's next on my list. + + -now sprites can burn-in on any frame, not just on the last frame. + set 'burn' to one (in the sprite code) on any frame to make it burn in. + this will break some older sprites, but it's super easy to fix, and + I think it's worth it. =) thanks to papaw00dy for the suggestion! + -fixed the asymptotic-value bug with custom waves using spectral data & having < 512 samples (thanks to telek's example!) + -fixed motion vectors' reversed Y positioning. + -fixed truncation ("...") of long custom messages + -fixed that pesky bug w/the last line of code on a page + -fixed the x-positioning of custom waves & shapes. Before, if you were + saving some coordinates from the preset's per-frame equations (say in q1 and q2) + and then you set "x = q1; y = q2;" in a custom shape's per-frame code + (or in a custom wave's per-point code), the x position wouldn't really be + in the right place, because of aspect ratio multiplications. Before, you had + to actually write "x = (q1-0.5)*0.75 + 0.5; y = q2;" to get it to line up; + now it's fixed, though, and you can just write "x = q1; y = q2;". + -fixed some bugs where the plugin start up, in windowed mode, on the wrong window + (and hence run super slow). + -fixed some bugs w/a munged window frame when the "integrate with winamp" option + was checked. + + -preset ratings are no longer read in all at once; instead, they are scanned in + 1 per frame until they're all in. This fixes the long pauses when you switch + to a directory that has many hundreds of presets. If you want to switch + back to the old way (read them all in at once), there is an option for it + in the config panel. + -cranked max. mesh size up to 128x96 + -fixed bug in custom shape per-frame code, where t1-t8 vars were not + resetting, at the beginning of each frame, to the values that they had + @ the end of the custom shape init code's execution. + - + - + - + + + beta 2 thread: http://forums.winamp.com/showthread.php?threadid=142635 + beta 3 thread: http://forums.winamp.com/showthread.php?threadid=142760 + beta 4 thread: http://forums.winamp.com/showthread.php?threadid=143500 + beta 6 thread: http://forums.winamp.com/showthread.php?threadid=143974 + (+read about beat det: http://forums.winamp.com/showthread.php?threadid=102205) + +@ -code editing: when cursor is on 1st posn. in line, wrong line is highlighted!? + -requests: + -random sprites (...they can just write a prog for this, tho) + -Text-entry mode. + -Like your favorite online game, hit T or something to enter 'text entry' mode. Type a message, then either hit ESC to clear and cancel text-entry mode, or ENTER to display the text on top of the vis. Easier for custom messages than editing the INI file (and probably stopping or minimizing milkdrop to do it) and reloading. + -OR SKIP IT; EASY TO JUST EDIT, RELOAD, AND HIT 00. + -add 'AA' parameter to custom message text file? + -when mem is low, fonts get kicked out -> white boxes + -probably happening b/c ID3DXFont can't create a + temp surface to use to draw text, since all the + video memory is gobbled up. +* -add to installer: q_and_t_vars.gif +* -presets: + 1. pick final set + a. OK-do a pass weeding out slow presets (crank mesh size up) + b. OK-do 2nd pass; rate them & delete crappies + c. OK-merge w/set from 1.03; check for dupes; delete more suckies + 2. OK-check for cpu-guzzlers + 3. OK-check for big ones (>= 8kb) + 4. check for ultra-spastic-when-audio-quiet ones + 5. update all ratings + 6. zip 'em up for safekeeping +* -docs: + -link to milkdrop.co.uk + -preset authoring: + -there are 11 variable pools: + preset: + a) preset init & per-frame code + b) preset per-pixel code + custom wave 1: + c) init & per-frame code + d) per-point code + custom wave 2: + e) init & per-frame code + f) per-point code + custom wave 3: + g) init & per-frame code + h) per-point code + i) custom shape 1: init & per-frame code + j) custom shape 2: init & per-frame code + k) custom shape 3: init & per-frame code + + -all of these have predefined variables, the values of many of which + trickle down from init code, to per-frame code, to per-pixel code, + when the same variable is defined for each of these. + -however, variables that you define ("my_var = 5;") do NOT trickle down. + To allow you to pass custom values from, say, your per-frame code + to your per-pixel code, the variables q1 through q8 were created. + For custom waves and custom shapes, t1 through t8 work similarly. + -q1-q8: + -purpose: to allow [custom] values to carry from {the preset init + and/or per-frame equations}, TO: {the per-pixel equations}, + {custom waves}, and {custom shapes}. + -are first set in preset init code. + -are reset, at the beginning of each frame, to the values that + they had at the end of the preset init code. + -can be modified in per-frame code... + -changes WILL be passed on to the per-pixel code + -changes WILL pass on to the q1-q8 vars in the custom waves + & custom shapes code + -changes will NOT pass on to the next frame, though; + use your own (custom) variables for that. + -can be modified in per-pixel code... + -changes will pass on to the next *pixel*, but no further + -changes will NOT pass on to the q1-q8 vars in the custom + waves or custom shapes code. + -changes will NOT pass on to the next frame, after the + last pixel, though. + -CUSTOM SHAPES: q1-q8... + -are readable in both the custom shape init & per-frame code + -start with the same values as q1-q8 had at the end of the *preset* + per-frame code, this frame + -can be modified in the init code, but only for a one-time + pass-on to the per-frame code. For all subsequent frames + (after the first), the per-frame code will get the q1-q8 + values as described above. + -can be modified in the custom shape per-frame code, but only + as temporary variables; the changes will not pass on anywhere. + -CUSTOM WAVES: q1-q8... + -are readable in the custom wave init, per-frame, and per-point code + -start with the same values as q1-q8 had at the end of the *preset* + per-frame code, this frame + -can be modified in the init code, but only for a one-time + pass-on to the per-frame code. For all subsequent frames + (after the first), the per-frame code will get the q1-q8 + values as described above. + -can be modified in the custom wave per-frame code; changes will + pass on to the per-point code, but that's it. + -can be modified in the per-point code, and the modified values + will pass on from point to point, but won't carry beyond that. + -CUSTOM WAVES: t1-t8... + -allow you to generate & save values in the custom wave init code, + that can pass on to the per-frame and, more sigificantly, + per-point code (since it's in a different variable pool). + -... + + + + !-whatever the values of q1-q8 were at the end of the per-frame and per-pixel + code, these are copied to the q1-q8 variables in the custom wave & custom + shape code, for that frame. However, those values are separate. + For example, if you modify q1-q8 in the custom wave #1 code, those changes + will not be visible anywhere else; if you modify q1-q8 in the custom shape + #2 code, same thing. However, if you modify q1-q8 in the per-frame custom + wave code, those modified values WILL be visible to the per-point custom + wave code, and can be modified within it; but after the last point, + the values q1-q8 will be discarded; on the next frame, in custom wave #1 + per-frame code, the values will be freshly copied from the values of the + main q1-q8 after the preset's per-frame and per-point code have both been + executed. + -monitor: + -can be read/written in preset init code & preset per-frame code. + -not accessible from per-pixel code. + -if you write it on one frame, then that value persists to the next frame. + -t1-t8: + - + - + - + -regular docs: + -put in the stuff recommended by VMS (vidcap, etc.) + -add to troubleshooting: + 1) desktop mode icons not appearing? or + onscreen text looking like colored boxes? + -> try freeing up some video memory. lower your res; drop to 16 bit; + etc. TURN OFF AUTO SONGTITLES. + 1) slow desktop/fullscr mode? -> try disabling auto songtitles + desktop icons. + also try reducing texsize to 256x256, since that eats memory that the text surface could claim. + 2) + 3) + * -presets: + -add new + -fix 3d presets (bring gammas back down to ~1.0) + -check old ones, make sure they're ok + -"Rovastar - Bytes" + -check wave_y + * -document custom waves & shapes + * -slow text is mostly fixed... =( + -desktop icons + playlist both have begin/end around them now, but in desktop mode, + if you bring up playlist or Load menu, fps drops in half; press Esc, and fps doesn't go back up. + - + - + - + -DONE / v1.04: + -updated to VMS 1.05 + -[list benefits...] + - + - + -3d mode: + a) SWAPPED DEFAULT L/R LENS COLORS! All images on the web are left=red, right=blue! + b) fixed image display when viewing a 3D preset in a non-4:3 aspect ratio window + c) gamma now works for 3d presets! (note: you might have to update your old presets. + if they were 3D presets, the gamma was ignored and 1.0 was used; now, + if gamma was >1.0 in the old preset, it will probably appear extremely bright.) + d) added SHIFT+F9 and CTRL+C9 to inc/dec stereo separation + e) added default stereo separation to config panel + -cranked up the max. mesh size (was 48x36, now 64x48) and the default mesh size + (was 24x18, now 32x24) + -fixed aspect ratio for final display + -auto-texsize is now computed slightly differently; for vertically or horizontally-stretched + windows, the texsize is now biased more toward the larger dimension (vs. just the + average). + -added anisotropic filtering (for machines that support it) + -fixed bug where the values of many variables in the preset init code were not set prior + to execution of the init code (e.g. time, bass, etc. were all broken!) + -added various preset blend effects. In addition to the old uniform fade, there is + now a directional wipe, radial wipe, and plasma fade. + -FIXED SLOW TEXT for DX8 (at least, on the geforce 4). + Not using DT_RIGHT or DT_BOTTOM was the key. + + + -why does text kill it in desktop mode? + -text is SLOOW + -to do: add (and use) song title font + tooltip font + -re-test: menus, text, boxes, etc. + -re-test: TIME + -testing: + -make sure sound works perfectly. (had to repro old pre-vms sound analysis!) + -autogamma: currently assumes/requires that GetFrame() resets to 0 on a mode change + (i.e. windowed -> fullscreen)... is that the case? + -restore motion vectors + - + - + -restore lost surfaces + -test bRedraw flag (desktop mode/paused) + -search for //? in milkdropfs.cpp and fix things + + problem: no good soln for VJ mode + problem: D3DX won't give you solid background for your text. + soln: (for later-) create wrapper fn that draws w/solid bkg. + + SOLN?: use D3DX to draw all text (plugin.cpp stuff AND playlist); + then, for VJ mode, create a 2nd DxContext + w/its own window + windowproc + fonts. (YUCK) + 1) config panel: test, and add WM_HELP's (copy from tooltips) + 2) keyboard input: test; and... + -need to reset UI_MODE when playlist is turned on, and + -need to reset m_show_playlist when UI_MODE is changed. (?) + -(otherwise they can both show @ same time and will fight + for keys and draw over each other) + 3) comment out most of D3D stuff in milkdropfs.cpp, and then + get it running w/o any milkdrop, but with text, etc. + 4) sound + + Issues / To Do Later + -------------------- + 1) sprites: color keying stuff probably won't work any more... + 2) scroll lock: pull code from Monkey + 3) m_nGridY should not always be m_nGridX*3/4! + 4) get solid backgrounds for menus, waitstring code, etc. + (make a wrapper function!) + + 99) at end: update help screen + + Things that will be different + ----------------------------- + 1) font sizes are no longer relative to size of window; they are absolute. + 2) 'don't clear screen at startup' option is gone + 3) 'always on top' option is gone + 4) text will not be black-on-white when an inverted-color preset is showing + + -VJ mode: + -notes + 1. (remember window size/pos, and save it from session to session? nah.) + 2. (kiv: scroll lock) + 3. (VJ window + desktop mode:) + -ok w/o VJ mode + -w/VJ mode, regardless of 'fix slow text' option, probs w/focus; + click on vj window, and plugin window flashes to top of Z order! + -goes away if you comment out 1st call to PushWindowToJustBeforeDesktop()... + -when you disable PushWindowToJustBeforeDesktop: + -..and click on EITHER window, milkdrop jumps in front of the taskbar. + -..and click on a non-MD window, nothing happens. + d-FIXED somehow, magically, while fixing bugs w/true fullscreen mode! + 4. (VJ window + true fullscreen mode:) + d-make sure VJ window gets placed on the right monitor, at startup, + and respects taskbar posn. + d-bug - start in windowed mode, then dbl-clk to go [true] fullscreen + on 2nd monitor, all with VJ mode on, and it excepts somewhere + in m_text.DrawNow() in a call to DrawPrimitive()! + FIXED - had to check m_vjd3d8_device->TestCooperativeLevel + each frame, and destroy/reinit if device needed reset. + d-can't resize VJ window when grfx window is running true fullscreen! + -FIXED, by dropping the Sleep(30)/return when m_lost_focus + was true, and by not consuming WM_NCACTIVATE in true fullscreen + mode when m_hTextWnd was present, since DX8 doesn't do its + auto-minimize thing in that case. + + + +*/ + +#include "plugin.h" +#include "utility.h" +#include "support.h" +//#include "resource.h" +#include "defines.h" +#include "shell_defines.h" +#include +#include +#include // for time() +//#include // for sliders +#include +#include +//#include "../XmlDocument.h" + +#define FRAND ((rand() % 7381)/7380.0f) +#define strnicmp _strnicmp +#define strcmpi _strcmpi + +//extern CSoundData* pg_sound; // declared in main.cpp +extern CPlugin* g_plugin; // declared in MilkDropXBMC.cpp +extern char g_visName[]; // declared in MilkDropXBMC.cpp + +// from support.cpp: +extern bool g_bDebugOutput; +extern bool g_bDumpFileCleared; + +// these callback functions are called by menu.cpp whenever the user finishes editing an eval_ expression. +void OnUserEditedPerFrame(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_PRESET_CODE, 0); +} +void OnUserEditedPerPixel(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_PRESET_CODE, 0); +} +void OnUserEditedPresetInit(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_PRESET_CODE, 1); +} +void OnUserEditedWavecode(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_WAVE_CODE, 0); +} +void OnUserEditedWavecodeInit(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_WAVE_CODE, 1); +} +void OnUserEditedShapecode(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_SHAPE_CODE, 0); +} +void OnUserEditedShapecodeInit(LPARAM param1, LPARAM param2) +{ + g_plugin->m_pState->RecompileExpressions(RECOMPILE_SHAPE_CODE, 1); +} + +// Modify the help screen text here. +// Watch the # of lines, though; if there are too many, they will get cut off; +// and watch the length of the lines, since there is no wordwrap. +// A good guideline: your entire help screen should be visible when fullscreen +// @ 640x480 and using the default help screen font. +char g_szHelp[] = +{ + "ESC: exit help/menus/fullscreen\r" // part of framework + "ALT+D: toggle desktop mode\r" // part of framework + "ALT+ENTER: toggle fullscreen\r" // part of framework + "\r" + "SCROLL LOCK: [un]lock current preset\r" + "L: load specific preset\r" + "R: toggle random/sequential preset order\r" + "H: instant Hard cut (to next preset)\r" + "spacebar: transition to next preset\r" + "+/-: rate current preset\r" + "\r" + "F1: toggle help display\r" // part of framework + "F2: toggle song display\r" // <- specific to this example plugin + "F3: toggle song display\r" // <- specific to this example plugin + "F4: toggle preset name display\r" + "F5: toggle fps display\r" // <- specific to this example plugin + "F6: toggle preset rating display\r" + "F7: reload milk_msg.ini\r" + "F8: change directory/drive\r" + "F9: toggle stereo 3D mode\r" + " + ctrl/shift = inc/dec depth\r" + "\r" + "PLAYBACK:\r" // part of framework + " ZXCVB: prev play pause stop next\r" // part of framework + " P: show/hide playlist\r" // part of framework + " U: toggle shuffle\r" // part of framework + " up/down arrows: adjust vol.\r" // part of framework + " left/right arrows: seek 5 sec.\r" // part of framework + " +SHIFT: seek 30 sec.\r" // part of framework + "\r" + "PRESET EDITING AND SAVING\r" + " M: show/hide preset-editing Menu\r" + " S: save new preset\r" + " N: show per-frame variable moNitor\r" + "\r" + "SPRITES, CUSTOM MESSAGES...\r" + " T: launch song title animation\r" + " Y: enter custom message mode\r" + " K: enter sprite mode\r" + " SHIFT + K: enter sprite kill mode\r" + " ** see milkdrop.html for the rest! **" +}; + +#define IPC_CB_VISRANDOM 628 // param is status of random + +//---------------------------------------------------------------------- + +void CPlugin::OverrideDefaults() +{ + // Here, you have the option of overriding the "default defaults" + // for the stuff on tab 1 of the config panel, replacing them + // with custom defaults for your plugin. + // To override any of the defaults, just uncomment the line + // and change the value. + // DO NOT modify these values from any function but this one! + + // This example plugin only changes the default width/height + // for fullscreen mode; the "default defaults" are just + // 640 x 480. + // If your plugin is very dependent on smooth animation and you + // wanted it plugin to have the 'save cpu' option OFF by default, + // for example, you could set 'm_save_cpu' to 0 here. + + // m_start_fullscreen = 0; // 0 or 1 + // m_start_desktop = 0; // 0 or 1 + // m_fake_fullscreen_mode = 0; // 0 or 1 + m_max_fps_fs = 60; // 1-120, or 0 for 'unlimited' + m_max_fps_dm = 60; // 1-120, or 0 for 'unlimited' + m_max_fps_w = 60; // 1-120, or 0 for 'unlimited' + // m_show_press_f1_msg = 1; // 0 or 1 + m_allow_page_tearing_w = 0; // 0 or 1 + // m_allow_page_tearing_fs = 0; // 0 or 1 + // m_allow_page_tearing_dm = 1; // 0 or 1 + // m_minimize_winamp = 1; // 0 or 1 + // m_desktop_textlabel_boxes = 1; // 0 or 1 + // m_save_cpu = 0; // 0 or 1 + + // strcpy(m_fontinfo[0].szFace, "Trebuchet MS"); // system font + // m_fontinfo[0].nSize = 18; + // m_fontinfo[0].bBold = 0; + // m_fontinfo[0].bItalic = 0; + // strcpy(m_fontinfo[1].szFace, "Times New Roman"); // decorative font + // m_fontinfo[1].nSize = 24; + // m_fontinfo[1].bBold = 0; + // m_fontinfo[1].bItalic = 1; + + m_disp_mode_fs.Width = 1024; // normally 640 + m_disp_mode_fs.Height = 768; // normally 480 + m_disp_mode_fs.Format = D3DFMT_X8R8G8B8; // use either D3DFMT_X8R8G8B8 or D3DFMT_R5G6B5. The former will match to any 32-bit color format available, and the latter will match to any 16-bit color available, if that exact format can't be found. + // m_disp_mode_fs.RefreshRate = 60; +} + +//---------------------------------------------------------------------- + +void CPlugin::MyPreInitialize() +{ + // Initialize EVERY data member you've added to CPlugin here; + // these will be the default values. + // If you want to initialize any of your variables with random values + // (using rand()), be sure to seed the random number generator first! + // (If you want to change the default values for settings that are part of + // the plugin shell (framework), do so from OverrideDefaults() above.) + + // seed the system's random number generator w/the current system time: + srand((unsigned)time(NULL)); + + // CONFIG PANEL SETTINGS THAT WE'VE ADDED (TAB #2) + m_bFirstRun = true; + m_fBlendTimeUser = 1.1f; + m_fBlendTimeAuto = 8.0f; + m_fTimeBetweenPresets = 8.0f; + m_fTimeBetweenPresetsRand = 5.0f; + m_bSequentialPresetOrder = false; + m_bHoldPreset = false; + m_bHardCutsDisabled = false; + m_fHardCutLoudnessThresh = 2.5f; + m_fHardCutHalflife = 60.0f; + //m_nWidth = 1024; + //m_nHeight = 768; + //m_nDispBits = 16; + m_nTexSize = 1024; // -1 means "auto" + m_nGridX = 32; + m_nGridY = 24; + + m_bShowPressF1ForHelp = true; + //strcpy(m_szMonitorName, "[don't use multimon]"); + m_bShowMenuToolTips = true; // NOTE: THIS IS CURRENTLY HARDWIRED TO TRUE - NO OPTION TO CHANGE + m_n16BitGamma = 2; + m_bAutoGamma = true; + //m_nFpsLimit = -1; + m_cLeftEye3DColor[0] = 255; + m_cLeftEye3DColor[1] = 0; + m_cLeftEye3DColor[2] = 0; + m_cRightEye3DColor[0] = 0; + m_cRightEye3DColor[1] = 255; + m_cRightEye3DColor[2] = 255; + m_bEnableRating = false; + m_bInstaScan = false; + m_bSongTitleAnims = true; + m_fSongTitleAnimDuration = 1.7f; + m_fTimeBetweenRandomSongTitles = -1.0f; + m_fTimeBetweenRandomCustomMsgs = -1.0f; + m_nSongTitlesSpawned = 0; + m_nCustMsgsSpawned = 0; + + m_bAlways3D = false; + m_fStereoSep = 1.0f; + //m_bAlwaysOnTop = false; + //m_bFixSlowText = true; + m_bWarningsDisabled = false; + m_bWarningsDisabled2 = false; + m_bAnisotropicFiltering = true; + m_bPresetLockOnAtStartup = false; + +// m_gdi_title_font_doublesize = NULL; +// m_d3dx_title_font_doublesize = NULL; + + // RUNTIME SETTINGS THAT WE'VE ADDED + m_prev_time = GetTime() - 0.0333f; // note: this will be updated each frame, at bottom of MyRenderFn. + m_bTexSizeWasAuto = false; + //m_bPresetLockedByUser = false; NOW SET IN DERIVED SETTINGS + m_bPresetLockedByCode = false; + m_fStartTime = 0.0f; + m_fPresetStartTime = 0.0f; + m_fNextPresetTime = -1.0f; // negative value means no time set (...it will be auto-set on first call to UpdateTime) + m_pState = &m_state_DO_NOT_USE[0]; + m_pOldState = &m_state_DO_NOT_USE[1]; + m_UI_mode = UI_REGULAR; + //m_nTrackPlaying = 0; + //m_nSongPosMS = 0; + //m_nSongLenMS = 0; + m_bUserPagedUp = false; + m_bUserPagedDown = false; + m_fMotionVectorsTempDx = 0.0f; + m_fMotionVectorsTempDy = 0.0f; + + m_waitstring.bActive = false; + m_waitstring.bOvertypeMode = false; + m_waitstring.szClipboard[0] = 0; + + m_nPresets = 0; + m_nDirs = 0; + m_nPresetListCurPos = 0; + m_nCurrentPreset = 0; + m_szCurrentPresetFile[0] = 0; + m_pPresetAddr = NULL; + m_pfPresetRating = NULL; + m_szpresets = new char[16384]; + m_nSizeOfPresetList = 16384; + m_szPresetDir[0] = 0; // will be set @ end of this function + m_nRatingReadProgress = -1; + + myfft.Init(576, MY_FFT_SAMPLES, -1); + memset(&mysound, 0, sizeof(mysound)); + + //m_nTextHeightPixels = -1; + //m_nTextHeightPixels_Fancy = -1; + m_bShowFPS = false; + m_bShowRating = false; + m_bShowPresetInfo = false; + m_bShowDebugInfo = false; + m_bShowSongTitle = false; + m_bShowSongTime = false; + m_bShowSongLen = false; + m_fShowUserMessageUntilThisTime = -1.0f; + m_fShowRatingUntilThisTime = -1.0f; + m_szUserMessage[0] = 0; + m_szDebugMessage[0] = 0; + m_szSongTitle[0] = 0; + m_szSongTitlePrev[0] = 0; + + m_lpVS[0] = NULL; + m_lpVS[1] = NULL; + m_pZBuffer = NULL; +// m_lpDDSTitle = NULL; + m_nTitleTexSizeX = 0; + m_nTitleTexSizeY = 0; + m_verts = NULL; + m_verts_temp = NULL; + m_vertinfo = NULL; + m_indices = NULL; + + m_bMMX = false; + m_bHasFocus = true; + m_bHadFocus = false; + m_bOrigScrollLockState = false;//GetKeyState(VK_SCROLL) & 1; + // m_bMilkdropScrollLockState is derived at end of MyReadConfig() + + m_nNumericInputMode = NUMERIC_INPUT_MODE_CUST_MSG; + m_nNumericInputNum = 0; + m_nNumericInputDigits = 0; + //td_custom_msg_font m_CustomMessageFont[MAX_CUSTOM_MESSAGE_FONTS]; + //td_custom_msg m_CustomMessage[MAX_CUSTOM_MESSAGES]; + + //texmgr m_texmgr; // for user sprites + + m_supertext.bRedrawSuperText = false; + m_supertext.fStartTime = -1.0f; + + // --------------------other init-------------------- + + g_bDebugOutput = false; + g_bDumpFileCleared = false; + + strcpy(m_szWinampPluginsPath, GetConfigIniFile()); + char *p = strrchr(m_szWinampPluginsPath, '/'); + if (p) *(p+1) = 0; + strcpy(m_szPresetDir, m_szWinampPluginsPath); + strcpy(m_szMsgIniFile, m_szWinampPluginsPath); + strcpy(m_szImgIniFile, m_szWinampPluginsPath); + strcat(m_szPresetDir, "milkdrop/"); + strcat(m_szMsgIniFile, MSG_INIFILE); + strcat(m_szImgIniFile, IMG_INIFILE); + + /* + char buf[MAX_PATH]; + sprintf(buf, "Program version is %3.2f%c", INT_VERSION*0.01f, (INT_SUBVERSION==0) ? (' ') : ('a'+INT_SUBVERSION-1)); + dumpmsg(buf); + sprintf(buf, "Config.ini file is %s", GetConfigIniFile()); + dumpmsg(buf); + sprintf(buf, "Preset directory is %s", m_szPresetDir); + dumpmsg(buf); + sprintf(buf, "Winamp window handle is %08x", GetWinampWindow()); + dumpmsg(buf); + sprintf(buf, "MMX %s detected.", m_bMMX ? "successfully " : "was NOT "); + dumpmsg(buf); + //sprintf(buf, "SSE %s detected.", m_bSSE ? "successfully " : "was NOT "); + //dumpmsg(buf); + */ +} + +//---------------------------------------------------------------------- + +extern void LoadSettings(); + +void CPlugin::MyReadConfig() +{ +/* + + + // Read the user's settings from the .INI file. + // If you've added any controls to the config panel, read their value in + // from the .INI file here. + + // use this function declared in to read a value of this type: + // ----------------- ----------- ---------------------------- + // InternalGetPrivateProfileInt Win32 API int + // GetPrivateProfileBool utility.h bool + // GetPrivateProfileBOOL utility.h BOOL + // InternalGetPrivateProfileFloat utility.h float + // InternalGetPrivateProfileString Win32 API string + + //ex: m_fog_enabled = InternalGetPrivateProfileInt("settings","fog_enabled" ,m_fog_enabled ,GetConfigIniFile()); + + int n=0; + char *pIni = GetConfigIniFile(); + + m_bFirstRun = !GetPrivateProfileBool("settings","bConfigured" ,false,pIni); + m_bEnableRating = GetPrivateProfileBool("settings","bEnableRating",m_bEnableRating,pIni); + m_bInstaScan = GetPrivateProfileBool("settings","bInstaScan",m_bInstaScan,pIni); + m_bHardCutsDisabled = GetPrivateProfileBool("settings","bHardCutsDisabled",m_bHardCutsDisabled,pIni); + g_bDebugOutput = GetPrivateProfileBool("settings","bDebugOutput",g_bDebugOutput,pIni); + //m_bShowSongInfo = GetPrivateProfileBool("settings","bShowSongInfo",m_bShowSongInfo,pIni); + //m_bShowPresetInfo=GetPrivateProfileBool("settings","bShowPresetInfo",m_bShowPresetInfo,pIni); + m_bShowPressF1ForHelp = GetPrivateProfileBool("settings","bShowPressF1ForHelp",m_bShowPressF1ForHelp,pIni); + //m_bShowMenuToolTips = GetPrivateProfileBool("settings","bShowMenuToolTips",m_bShowMenuToolTips,pIni); + m_bSongTitleAnims = GetPrivateProfileBool("settings","bSongTitleAnims",m_bSongTitleAnims,pIni); + + m_bShowFPS = GetPrivateProfileBool("settings","bShowFPS", m_bShowFPS ,pIni); + m_bShowRating = GetPrivateProfileBool("settings","bShowRating", m_bShowRating ,pIni); + m_bShowPresetInfo = GetPrivateProfileBool("settings","bShowPresetInfo",m_bShowPresetInfo ,pIni); + //m_bShowDebugInfo = GetPrivateProfileBool("settings","bShowDebugInfo", m_bShowDebugInfo ,pIni); + m_bShowSongTitle = GetPrivateProfileBool("settings","bShowSongTitle", m_bShowSongTitle ,pIni); + m_bShowSongTime = GetPrivateProfileBool("settings","bShowSongTime", m_bShowSongTime ,pIni); + m_bShowSongLen = GetPrivateProfileBool("settings","bShowSongLen", m_bShowSongLen ,pIni); + + //m_bFixPinkBug = GetPrivateProfileBool("settings","bFixPinkBug",m_bFixPinkBug,pIni); + int nTemp = GetPrivateProfileBool("settings","bFixPinkBug",-1,pIni); + if (nTemp == 0) + m_n16BitGamma = 0; + else if (nTemp == 1) + m_n16BitGamma = 2; + m_n16BitGamma = InternalGetPrivateProfileInt("settings","n16BitGamma",m_n16BitGamma,pIni); + m_bAutoGamma = GetPrivateProfileBool("settings","bAutoGamma",m_bAutoGamma,pIni); + m_bAlways3D = GetPrivateProfileBool("settings","bAlways3D",m_bAlways3D,pIni); + m_fStereoSep = InternalGetPrivateProfileFloat("settings","fStereoSep",m_fStereoSep,pIni); + //m_bFixSlowText = GetPrivateProfileBool("settings","bFixSlowText",m_bFixSlowText,pIni); + //m_bAlwaysOnTop = GetPrivateProfileBool("settings","bAlwaysOnTop",m_bAlwaysOnTop,pIni); + m_bWarningsDisabled = GetPrivateProfileBool("settings","bWarningsDisabled",m_bWarningsDisabled,pIni); + m_bWarningsDisabled2 = GetPrivateProfileBool("settings","bWarningsDisabled2",m_bWarningsDisabled2,pIni); + m_bAnisotropicFiltering = GetPrivateProfileBool("settings","bAnisotropicFiltering",m_bAnisotropicFiltering,pIni); + m_bPresetLockOnAtStartup = GetPrivateProfileBool("settings","bPresetLockOnAtStartup",m_bPresetLockOnAtStartup,pIni); + + m_cLeftEye3DColor[0] = InternalGetPrivateProfileInt("settings","nLeftEye3DColorR",m_cLeftEye3DColor[0],pIni); + m_cLeftEye3DColor[1] = InternalGetPrivateProfileInt("settings","nLeftEye3DColorG",m_cLeftEye3DColor[1],pIni); + m_cLeftEye3DColor[2] = InternalGetPrivateProfileInt("settings","nLeftEye3DColorB",m_cLeftEye3DColor[2],pIni); + m_cRightEye3DColor[0] = InternalGetPrivateProfileInt("settings","nRightEye3DColorR",m_cRightEye3DColor[0],pIni); + m_cRightEye3DColor[1] = InternalGetPrivateProfileInt("settings","nRightEye3DColorG",m_cRightEye3DColor[1],pIni); + m_cRightEye3DColor[2] = InternalGetPrivateProfileInt("settings","nRightEye3DColorB",m_cRightEye3DColor[2],pIni); + + m_nTexSize = InternalGetPrivateProfileInt("settings","nTexSize" ,m_nTexSize ,pIni); + m_bTexSizeWasAuto = (m_nTexSize == -1); + m_nGridX = InternalGetPrivateProfileInt("settings","nMeshSize" ,m_nGridX ,pIni); + m_nGridY = m_nGridX*3/4; + + m_fBlendTimeUser = InternalGetPrivateProfileFloat("settings","fBlendTimeUser" ,m_fBlendTimeUser ,pIni); + m_fBlendTimeAuto = InternalGetPrivateProfileFloat("settings","fBlendTimeAuto" ,m_fBlendTimeAuto ,pIni); + m_fTimeBetweenPresets = InternalGetPrivateProfileFloat("settings","fTimeBetweenPresets" ,m_fTimeBetweenPresets ,pIni); + m_fTimeBetweenPresetsRand = InternalGetPrivateProfileFloat("settings","fTimeBetweenPresetsRand",m_fTimeBetweenPresetsRand,pIni); + m_fHardCutLoudnessThresh = InternalGetPrivateProfileFloat("settings","fHardCutLoudnessThresh" ,m_fHardCutLoudnessThresh ,pIni); + m_fHardCutHalflife = InternalGetPrivateProfileFloat("settings","fHardCutHalflife" ,m_fHardCutHalflife ,pIni); + m_fSongTitleAnimDuration = InternalGetPrivateProfileFloat("settings","fSongTitleAnimDuration" ,m_fSongTitleAnimDuration ,pIni); + m_fTimeBetweenRandomSongTitles = InternalGetPrivateProfileFloat("settings","fTimeBetweenRandomSongTitles" ,m_fTimeBetweenRandomSongTitles,pIni); + m_fTimeBetweenRandomCustomMsgs = InternalGetPrivateProfileFloat("settings","fTimeBetweenRandomCustomMsgs" ,m_fTimeBetweenRandomCustomMsgs,pIni); + + // -------- + + InternalGetPrivateProfileString("settings","szPresetDir",m_szPresetDir,m_szPresetDir,sizeof(m_szPresetDir),pIni); + + ReadCustomMessages(); + + // bounds-checking: + if (m_nGridX > MAX_GRID_X) + m_nGridX = MAX_GRID_X; + if (m_nGridY > MAX_GRID_Y) + m_nGridY = MAX_GRID_Y; + if (m_fTimeBetweenPresetsRand < 0) + m_fTimeBetweenPresetsRand = 0; + if (m_fTimeBetweenPresets < 0.1f) + m_fTimeBetweenPresets = 0.1f; + + // DERIVED SETTINGS + m_bPresetLockedByUser = m_bPresetLockOnAtStartup; + m_bMilkdropScrollLockState = m_bPresetLockOnAtStartup; +*/ + + m_bPresetLockedByUser = false; + + //------------------------------------------------------------------------- + // XML version + + LoadSettings(); +} + +//---------------------------------------------------------------------- + +void CPlugin::MyWriteConfig() +{ +/* + + // Write the user's settings to the .INI file. + // This gets called only when the user runs the config panel and hits OK. + // If you've added any controls to the config panel, write their value out + // to the .INI file here. + + // use this function declared in to write a value of this type: + // ----------------- ----------- ---------------------------- + // WritePrivateProfileInt Win32 API int + // WritePrivateProfileInt utility.h bool + // WritePrivateProfileInt utility.h BOOL + // WritePrivateProfileFloat utility.h float + // WritePrivateProfileString Win32 API string + + // ex: WritePrivateProfileInt(m_fog_enabled ,"fog_enabled" ,GetConfigIniFile(),"settings"); + + char *pIni = GetConfigIniFile(); + + // constants: + WritePrivateProfileString("settings","bConfigured","1",pIni); + + //note: m_szPresetDir is not written here; it is written manually, whenever it changes. + + char szSectionName[] = "settings"; + + WritePrivateProfileInt(m_bSongTitleAnims, "bSongTitleAnims", pIni, "settings"); + WritePrivateProfileInt(m_bHardCutsDisabled, "bHardCutsDisabled", pIni, "settings"); + WritePrivateProfileInt(m_bEnableRating, "bEnableRating", pIni, "settings"); + WritePrivateProfileInt(m_bInstaScan, "bInstaScan", pIni, "settings"); + WritePrivateProfileInt(g_bDebugOutput, "bDebugOutput", pIni, "settings"); + + //itePrivateProfileInt(m_bShowPresetInfo, "bShowPresetInfo", pIni, "settings"); + //itePrivateProfileInt(m_bShowSongInfo, "bShowSongInfo", pIni, "settings"); + //itePrivateProfileInt(m_bFixPinkBug, "bFixPinkBug", pIni, "settings"); + + WritePrivateProfileInt(m_bShowPressF1ForHelp, "bShowPressF1ForHelp", pIni, "settings"); + //itePrivateProfileInt(m_bShowMenuToolTips, "bShowMenuToolTips", pIni, "settings"); + WritePrivateProfileInt(m_n16BitGamma, "n16BitGamma", pIni, "settings"); + WritePrivateProfileInt(m_bAutoGamma, "bAutoGamma", pIni, "settings"); + + WritePrivateProfileInt(m_bAlways3D, "bAlways3D", pIni, "settings"); + WritePrivateProfileFloat(m_fStereoSep, "fStereoSep", pIni, "settings"); + //WritePrivateProfileInt(m_bFixSlowText, "bFixSlowText", pIni, "settings"); + //itePrivateProfileInt(m_bAlwaysOnTop, "bAlwaysOnTop", pIni, "settings"); + WritePrivateProfileInt(m_bWarningsDisabled, "bWarningsDisabled", pIni, "settings"); + WritePrivateProfileInt(m_bWarningsDisabled2, "bWarningsDisabled2", pIni, "settings"); + WritePrivateProfileInt(m_bAnisotropicFiltering, "bAnisotropicFiltering",pIni, "settings"); + WritePrivateProfileInt(m_bPresetLockOnAtStartup,"bPresetLockOnAtStartup",pIni,"settings"); + + WritePrivateProfileInt(m_cLeftEye3DColor[0], "nLeftEye3DColorR", pIni, "settings"); + WritePrivateProfileInt(m_cLeftEye3DColor[1], "nLeftEye3DColorG", pIni, "settings"); + WritePrivateProfileInt(m_cLeftEye3DColor[2], "nLeftEye3DColorB", pIni, "settings"); + WritePrivateProfileInt(m_cRightEye3DColor[0], "nRightEye3DColorR", pIni, "settings"); + WritePrivateProfileInt(m_cRightEye3DColor[1], "nRightEye3DColorG", pIni, "settings"); + WritePrivateProfileInt(m_cRightEye3DColor[2], "nRightEye3DColorB", pIni, "settings"); + + WritePrivateProfileInt(m_nTexSize, "nTexSize", pIni, "settings"); + WritePrivateProfileInt(m_nGridX, "nMeshSize", pIni, "settings"); + + WritePrivateProfileFloat(m_fBlendTimeAuto, "fBlendTimeAuto", pIni, "settings"); + WritePrivateProfileFloat(m_fBlendTimeUser, "fBlendTimeUser", pIni, "settings"); + WritePrivateProfileFloat(m_fTimeBetweenPresets, "fTimeBetweenPresets", pIni, "settings"); + WritePrivateProfileFloat(m_fTimeBetweenPresetsRand, "fTimeBetweenPresetsRand", pIni, "settings"); + WritePrivateProfileFloat(m_fHardCutLoudnessThresh, "fHardCutLoudnessThresh", pIni, "settings"); + WritePrivateProfileFloat(m_fHardCutHalflife, "fHardCutHalflife", pIni, "settings"); + WritePrivateProfileFloat(m_fSongTitleAnimDuration, "fSongTitleAnimDuration", pIni, "settings"); + WritePrivateProfileFloat(m_fTimeBetweenRandomSongTitles,"fTimeBetweenRandomSongTitles",pIni, "settings"); + WritePrivateProfileFloat(m_fTimeBetweenRandomCustomMsgs,"fTimeBetweenRandomCustomMsgs",pIni, "settings"); +*/ +} + +//---------------------------------------------------------------------- + +int CPlugin::AllocateMyNonDx8Stuff() +{ + // This gets called only once, when your plugin is actually launched. + // If only the config panel is launched, this does NOT get called. + // (whereas MyPreInitialize() still does). + // If anything fails here, return FALSE to safely exit the plugin, + // but only after displaying a messagebox giving the user some information + // about what went wrong. + + /* + if (!m_hBlackBrush) + m_hBlackBrush = CreateSolidBrush(RGB(0,0,0)); + */ + + BuildMenus(); + + m_bMMX = CheckForMMX(); + //m_bSSE = CheckForSSE(); + + m_pState->Default(); + m_pOldState->Default(); + + // JM + if (m_bHoldPreset && m_nPresets >= 0) + { + printf("Preset is held, loading preset %i", m_nCurrentPreset); + if (m_nCurrentPreset > 0) + { + m_nCurrentPreset--; + LoadNextPreset(0.0f); + } + else + { + m_nCurrentPreset++; + LoadPreviousPreset(0.0f); + } + } + else + { + printf("Preset is not held, loading a random preset. Current is %i", m_nCurrentPreset); + LoadRandomPreset(0.0f); + } + // JM + return true; +} + +//---------------------------------------------------------------------- + +void CPlugin::CleanUpMyNonDx8Stuff() +{ + // This gets called only once, when your plugin exits. + // Be sure to clean up any objects here that were + // created/initialized in AllocateMyNonDx8Stuff. + + //sound.Finish(); + + if (m_pPresetAddr) + { + delete m_pPresetAddr; + m_pPresetAddr = NULL; + } + + if (m_pfPresetRating) + { + delete m_pfPresetRating; + m_pfPresetRating = NULL; + } + + if (m_szpresets) + { + delete m_szpresets; + m_szpresets = NULL; + } + + // NOTE: DO NOT DELETE m_gdi_titlefont_doublesize HERE!!! + +/* + m_menuPreset .Finish(); + m_menuWave .Finish(); + m_menuAugment .Finish(); + m_menuCustomWave.Finish(); + m_menuCustomShape.Finish(); + m_menuMotion .Finish(); + m_menuPost .Finish(); + for (int i=0; i= 11.0f) // ..don't jump to 2048x2048 quite as readily + bias = 0.5f; + int nExp = (int)(fExp + bias); + m_nTexSize = (int)powf(2.0f, (float)nExp); + } +*/ + + // clip texsize by max. from caps + if (m_nTexSize > GetCaps()->MaxTextureWidth && GetCaps()->MaxTextureWidth>0) + m_nTexSize = GetCaps()->MaxTextureWidth; + if (m_nTexSize > GetCaps()->MaxTextureHeight && GetCaps()->MaxTextureHeight>0) + m_nTexSize = GetCaps()->MaxTextureHeight; + + // reallocate + bool bSuccess = false; + int nOrigTexSize = m_nTexSize; + + do + { + SafeRelease(m_lpVS[0]); + SafeRelease(m_lpVS[1]); + SafeRelease(m_pZBuffer); + + LPDIRECT3DSURFACE9 pBackBuffer, tmpSurface; + D3DSURFACE_DESC tmpDesc; + D3DVIEWPORT9 pVP; + + GetDevice()->GetRenderTarget(0, &pBackBuffer ); + GetDevice()->GetDepthStencilSurface(&tmpSurface); + tmpSurface->GetDesc(&tmpDesc); + SafeRelease(tmpSurface); + GetDevice()->GetViewport(&pVP); + + UINT uiwidth=(pVP.Width>m_nTexSize) ? pVP.Width:m_nTexSize; + UINT uiheight=(pVP.Height>m_nTexSize) ? pVP.Height:m_nTexSize; + + printf("CreateDepthStencilSurface with %u x %u", uiwidth, uiheight); + if(GetDevice()->CreateDepthStencilSurface(uiwidth, uiheight, tmpDesc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, &m_pZBuffer, NULL) != D3D_OK) + printf("Can't create DepthStencilSurface"); + + // create VS1 and VS2 + bSuccess = (GetDevice()->CreateTexture(m_nTexSize, m_nTexSize, 1, D3DUSAGE_RENDERTARGET, GetBackBufFormat(), D3DPOOL_DEFAULT, &m_lpVS[0], NULL) == D3D_OK); + if (bSuccess) + { + IDirect3DSurface9* pNewTarget = NULL; + if (m_lpVS[0]->GetSurfaceLevel(0, &pNewTarget) == D3D_OK) + { + GetDevice()->SetRenderTarget(0, pNewTarget); + GetDevice()->Clear(0, 0, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0); + pNewTarget->Release(); + } + + bSuccess = (GetDevice()->CreateTexture(m_nTexSize, m_nTexSize, 1, D3DUSAGE_RENDERTARGET, GetBackBufFormat(), D3DPOOL_DEFAULT, &m_lpVS[1], NULL) == D3D_OK); + if (bSuccess) + { + if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) == D3D_OK) + { + GetDevice()->SetRenderTarget(0, pNewTarget); + GetDevice()->Clear(0, 0, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0); + pNewTarget->Release(); + } + } + else + printf("failed to create texture %d x %d", m_nTexSize, m_nTexSize); + } + else + printf("failed to create texture %d x %d", m_nTexSize, m_nTexSize); + + GetDevice()->SetRenderTarget(0, pBackBuffer); + SafeRelease(pBackBuffer); + + + if (!bSuccess && m_bTexSizeWasAuto) + m_nTexSize /= 2; + } + while (!bSuccess && m_nTexSize >= 256 && m_bTexSizeWasAuto); + + if (!bSuccess) + { + char buf[2048]; + if (m_bTexSizeWasAuto || m_nTexSize==256) + sprintf(buf, "couldn't create offscreen surfaces! (probably not enough video memory left)\rtry selecting a smaller video mode or changing the color depth."); + else + sprintf(buf, "couldn't create offscreen surfaces! (probably not enough video memory left)\r\r\rRECOMMENDATION: SET THE TEXTURE SIZE BACK TO 'AUTO' AND TRY AGAIN"); + dumpmsg(buf); +// MessageBox(GetPluginWindow(), buf, "MILKDROP ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST ); + return false; + } + printf("Textures created!"); + + if (m_nTexSize != nOrigTexSize) + { + char buf[2048]; + sprintf(buf, "Init: -WARNING-: low memory; ideal auto texture size would be %d, but it had to be lowered to %d!", nOrigTexSize, m_nTexSize); + dumpmsg(buf); + if (!m_bWarningsDisabled) + { + sprintf(buf, "WARNING: low video memory; auto texture had to be reduced\rfrom %dx%d to %dx%d.\r\rThe image may look chunky or blocky.\r", nOrigTexSize, nOrigTexSize, m_nTexSize, m_nTexSize); + if (GetScreenMode() != FULLSCREEN) + { + switch(GetBackBufFormat()) + { +// case D3DFMT_R8G8B8 : + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + strcat(buf, "\rRECOMMENDATION: **reduce your Windows color depth to 16 bits**\rto free up some video memory, or lower your screen resolution.\r"); + break; + default: + strcat(buf, "\rRECOMMENDATION: lower your screen resolution, to free up some video memory.\r"); + break; + } + } + dumpmsg(buf); +// MessageBox(GetPluginWindow(), buf, "WARNING", MB_OK|MB_SETFOREGROUND|MB_TOPMOST ); + } + } + } + + // ----------------- + + /*if (m_bFixSlowText && !m_bSeparateTextWindow) + { + if (D3DXCreateTexture(GetDevice(), GetWidth(), GetHeight(), 1, D3DUSAGE_RENDERTARGET, GetBackBufFormat(), D3DPOOL_DEFAULT, &m_lpDDSText) != D3D_OK) + { + char buf[2048]; + dumpmsg("Init: -WARNING-:"); + sprintf(buf, "WARNING: Not enough video memory to make a dedicated text surface; \rtext will still be drawn directly to the back buffer.\r\rTo avoid seeing this error again, uncheck the 'fix slow text' option."); + dumpmsg(buf); + if (!m_bWarningsDisabled) + MessageBox(GetPluginWindow(), buf, "WARNING", MB_OK|MB_SETFOREGROUND|MB_TOPMOST ); + m_lpDDSText = NULL; + } + }*/ + + // ----------------- + +#if 0 + // reallocate the texture for font titles + custom msgs (m_lpDDSTitle) + { + m_nTitleTexSizeX = m_nTexSize; + m_nTitleTexSizeY = m_nTexSize/2; + + //dumpmsg("Init: [re]allocating title surface"); + + // [DEPRECATED as of transition to dx8:] + // We could just create one title surface, but this is a problem because many + // systems can only call DrawText on DDSCAPS_OFFSCREENPLAIN surfaces, and can NOT + // draw text on a DDSCAPS_TEXTURE surface (it comes out garbled). + // So, we create one of each; we draw the text to the DDSCAPS_OFFSCREENPLAIN surface + // (m_lpDDSTitle[1]), then we blit that (once) to the DDSCAPS_TEXTURE surface + // (m_lpDDSTitle[0]), which can then be drawn onto the screen on polys. + + int square = 0; + HRESULT hr; + + do + { + hr = D3DXCreateTexture(GetDevice(), m_nTitleTexSizeX, m_nTitleTexSizeY, 1, D3DUSAGE_RENDERTARGET, GetBackBufFormat(), D3DPOOL_DEFAULT, &m_lpDDSTitle); + if (hr != D3D_OK) + { + if (square==0) + { + square = 1; + m_nTitleTexSizeY *= 2; + } + else + { + m_nTitleTexSizeX /= 2; + m_nTitleTexSizeY /= 2; + } + } + } + while (hr != D3D_OK && m_nTitleTexSizeX > 16); + + if (hr != D3D_OK) + { + //dumpmsg("Init: -WARNING-: Title texture could not be created!"); + m_lpDDSTitle = NULL; + //SafeRelease(m_lpDDSTitle); + //return true; + } + else + { + //sprintf(buf, "Init: title texture size is %dx%d (ideal size was %dx%d)", m_nTitleTexSizeX, m_nTitleTexSizeY, m_nTexSize, m_nTexSize/4); + //dumpmsg(buf); + m_supertext.bRedrawSuperText = true; + } + } +#endif + // ----------------- + +#if 0 + // create 'm_gdi_title_font_doublesize' + int songtitle_font_size = m_fontinfo[SONGTITLE_FONT].nSize * m_nTitleTexSizeX/256; + if (songtitle_font_size<6) songtitle_font_size=6; + if (!(m_gdi_title_font_doublesize = CreateFont(songtitle_font_size, 0, 0, 0, m_fontinfo[SONGTITLE_FONT].bBold ? 900 : 400, m_fontinfo[SONGTITLE_FONT].bItalic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, m_fontinfo[SONGTITLE_FONT].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, DEFAULT_PITCH, m_fontinfo[SONGTITLE_FONT].szFace))) + { + MessageBox(NULL, "Error creating double-sized GDI title font", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } + + if (D3DXCreateFont(GetDevice(), m_gdi_title_font_doublesize, &m_d3dx_title_font_doublesize) != D3D_OK) + { + MessageBox(GetPluginWindow(), "Error creating double-sized d3dx title font", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } +#endif + // ----------------- + +// m_texmgr.Init(GetDevice()); + + //dumpmsg("Init: mesh allocation"); + m_verts = new SPRITEVERTEX[(m_nGridX+1)*(m_nGridY+1)]; + m_verts_temp = new SPRITEVERTEX[(m_nGridX+2)]; + m_vertinfo = new td_vertinfo[(m_nGridX+1)*(m_nGridY+1)]; + m_indices = new WORD[(m_nGridX+2)*(m_nGridY*2)]; + if (!m_verts || !m_vertinfo) + { + sprintf(buf, "couldn't allocate mesh - out of memory"); + dumpmsg(buf); +// MessageBox(GetPluginWindow(), buf, "MILKDROP ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST ); + return false; + } + + int nVert = 0; + for (int y=0; y<=m_nGridY; y++) + { + for (int x=0; x<=m_nGridX; x++) + { + // precompute x,y,z + m_verts[nVert].x = x/(float)m_nGridX*2.0f - 1.0f; + m_verts[nVert].y = y/(float)m_nGridY*2.0f - 1.0f; + m_verts[nVert].z = 0.0f; + + // precompute rad, ang, being conscious of aspect ratio + m_vertinfo[nVert].rad = sqrtf(m_verts[nVert].x*m_verts[nVert].x + m_verts[nVert].y*m_verts[nVert].y*ASPECT*ASPECT); + if (y==m_nGridY/2 && x==m_nGridX/2) + m_vertinfo[nVert].ang = 0.0f; + else + m_vertinfo[nVert].ang = atan2f(m_verts[nVert].y*ASPECT, m_verts[nVert].x); + m_vertinfo[nVert].a = 1; + m_vertinfo[nVert].c = 0; + + nVert++; + } + } + + int xref, yref; + nVert = 0; + for (int quadrant=0; quadrant<4; quadrant++) + { + for (int slice=0; slice < m_nGridY/2; slice++) + { + for (int i=0; i < m_nGridX + 2; i++) + { + // quadrants: 2 3 + // 0 1 + + xref = i/2; + yref = (i%2) + slice; + + if (quadrant & 1) + xref = m_nGridX - xref; + + if (quadrant & 2) + yref = m_nGridY - yref; + + m_indices[nVert++] = xref + (yref)*(m_nGridX+1); + } + } + } + + return true; +} + +//---------------------------------------------------------------------- + +void CPlugin::CleanUpMyDX8Stuff(int final_cleanup) +{ + // Clean up all your DX8 and D3DX textures, fonts, buffers, etc. here. + // EVERYTHING CREATED IN ALLOCATEMYDX8STUFF() SHOULD BE CLEANED UP HERE. + // The input parameter, 'final_cleanup', will be 0 if this is + // a routine cleanup (part of a window resize or switch between + // fullscr/windowed modes), or 1 if this is the final cleanup + // and the plugin is exiting. Note that even if it is a routine + // cleanup, *you still have to release ALL your DirectX stuff, + // because the DirectX device is being destroyed and recreated!* + // Also set all the pointers back to NULL; + // this is important because if we go to reallocate the DX8 + // stuff later, and something fails, then CleanUp will get called, + // but it will then be trying to clean up invalid pointers.) + // The SafeRelease() and SafeDelete() macros make your code prettier; + // they are defined here in utility.h as follows: + // #define SafeRelease(x) if (x) {x->Release(); x=NULL;} + // #define SafeDelete(x) if (x) {delete x; x=NULL;} + // IMPORTANT: + // This function ISN'T only called when the plugin exits! + // It is also called whenever the user toggles between fullscreen and + // windowed modes, or resizes the window. Basically, on these events, + // the base class calls CleanUpMyDX8Stuff before Reset()ing the DirectX + // device, and then calls AllocateMyDX8Stuff afterwards. + + + // NOTE: not necessary; shell does this for us. + /*if (GetDevice()) + { + GetDevice()->SetTexture(0, NULL); + GetDevice()->SetTexture(1, NULL); + }*/ + + // 2. release stuff + SafeRelease(m_lpVS[0]); + SafeRelease(m_lpVS[1]); + SafeRelease(m_pZBuffer); +// SafeRelease(m_lpDDSTitle); +// SafeRelease(m_d3dx_title_font_doublesize); + + // NOTE: THIS CODE IS IN THE RIGHT PLACE. +/* if (m_gdi_title_font_doublesize) + { + DeleteObject(m_gdi_title_font_doublesize); + m_gdi_title_font_doublesize = NULL; + } +*/ +// m_texmgr.Finish(); + + if (m_verts != NULL) + { + delete m_verts; + m_verts = NULL; + } + + if (m_verts_temp != NULL) + { + delete m_verts_temp; + m_verts_temp = NULL; + } + + if (m_vertinfo != NULL) + { + delete m_vertinfo; + m_vertinfo = NULL; + } + + if (m_indices != NULL) + { + delete m_indices; + m_indices = NULL; + } +} + +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- + +void CPlugin::MyRenderFn(int redraw) +{ + LPDIRECT3DSURFACE9 tmpSurface; + GetDevice()->GetDepthStencilSurface(&tmpSurface); + GetDevice()->SetDepthStencilSurface(m_pZBuffer); + + // Render a frame of animation here. + // This function is called each frame just AFTER BeginScene(). + // For timing information, call 'GetTime()' and 'GetFps()'. + // The usual formula is like this (but doesn't have to be): + // 1. take care of timing/other paperwork/etc. for new frame + // 2. clear the background + // 3. get ready for 3D drawing + // 4. draw your 3D stuff + // 5. call PrepareFor2DDrawing() + // 6. draw your 2D stuff (overtop of your 3D scene) + // If the 'redraw' flag is 1, you should try to redraw + // the last frame; GetTime, GetFps, and GetFrame should + // all return the same values as they did on the last + // call to MyRenderFn(). Otherwise, the redraw flag will + // be zero, and you can draw a new frame. The flag is + // used to force the desktop to repaint itself when + // running in desktop mode and Winamp is paused or stopped. + + // 1. take care of timing/other paperwork/etc. for new frame + { + float dt = GetTime() - m_prev_time; + m_prev_time = GetTime(); // note: m_prev_time is not for general use! + if (m_bPresetLockedByUser || m_bPresetLockedByCode) + { + m_fPresetStartTime += dt; + m_fNextPresetTime += dt; + } + + UpdatePresetRatings(); // read in a few each frame, til they're all in + } + + // 2. check for lost or gained kb focus: + // (note: can't use wm_setfocus or wm_killfocus because they don't work w/embedwnd) +/* + if (GetFrame()==0) + { + SetScrollLock(m_bPresetLockOnAtStartup); + } + else + { + m_bHadFocus = m_bHasFocus; + if (GetParent(GetPluginWindow()) == GetWinampWindow()) + m_bHasFocus = (GetFocus() == GetPluginWindow()); + else + m_bHasFocus = (GetFocus() == GetParent(GetPluginWindow())) || + (GetFocus() == GetPluginWindow()); + + if (m_hTextWnd && GetFocus()==m_hTextWnd) + m_bHasFocus = 1; + + if (GetFocus()==NULL) + m_bHasFocus = 0; + ; + //HWND t1 = GetFocus(); + //HWND t2 = GetPluginWindow(); + //HWND t3 = GetParent(t2); + + if (m_bHadFocus==1 && m_bHasFocus==0) + { + m_bMilkdropScrollLockState = GetKeyState(VK_SCROLL) & 1; + SetScrollLock(m_bOrigScrollLockState); + } + else if (m_bHadFocus==0 && m_bHasFocus==1) + { + m_bOrigScrollLockState = GetKeyState(VK_SCROLL) & 1; + SetScrollLock(m_bMilkdropScrollLockState); + } + } + + GetWinampSongTitle(GetWinampWindow(), m_szSongTitle, sizeof(m_szSongTitle)-1); + if (strcmp(m_szSongTitle, m_szSongTitlePrev)) + { + strcpy(m_szSongTitlePrev, m_szSongTitle); + if (m_bSongTitleAnims) + LaunchSongTitleAnim(); + } +*/ + // 2. Clear the background: + //DWORD clear_color = (m_fog_enabled) ? FOG_COLOR : 0xFF000000; + //GetDevice()->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, clear_color, 1.0f, 0); + + // 5. switch to 2D drawing mode. 2D coord system: + // +--------+ Y=-1 + // | | + // | screen | Z=0: front of scene + // | | Z=1: back of scene + // +--------+ Y=1 + // X=-1 X=1 + PrepareFor2DDrawing(GetDevice()); + + DoCustomSoundAnalysis(); // emulates old pre-vms milkdrop sound analysis + + RenderFrame(redraw); // see milkdropfs.cpp + + /* + for (int i=0; i<10; i++) + { + RECT r; + r.top = GetHeight()*i/10; + r.left = 0; + r.right = GetWidth(); + r.bottom = r.top + GetFontHeight(DECORATIVE_FONT); + char buf[256]; + switch(i) + { + case 0: strcpy(buf, "this is a test"); break; + case 1: strcpy(buf, "argh"); break; + case 2: strcpy(buf, "!!"); break; + case 3: strcpy(buf, "TESTING FONTS"); break; + case 4: strcpy(buf, "rancid bear grease"); break; + case 5: strcpy(buf, "whoppers and ding dongs"); break; + case 6: strcpy(buf, "billy & joey"); break; + case 7: strcpy(buf, "."); break; + case 8: strcpy(buf, "---"); break; + case 9: strcpy(buf, "test"); break; + } + int t = (int)( 54 + 18*sin(i/10.0f*53.7f + 1) - 28*sin(i/10.0f*39.4f + 3) ); + if (((GetFrame() + i*107) % t) < t*8/9) + m_text.QueueText(GetFont(DECORATIVE_FONT), buf, r, 0, 0xFFFF00FF); + } + /**/ + GetDevice()->SetDepthStencilSurface(tmpSurface); + SafeRelease(tmpSurface); +} + +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- + +void CPlugin::DrawTooltip(char* str, int xR, int yB) +{ +#if 0 + /* + // draws a string in the lower-right corner of the screen. + // note: ID3DXFont handles DT_RIGHT and DT_BOTTOM *very poorly*. + // it is best to calculate the size of the text first, + // then place it in the right spot. + // note: use DT_WORDBREAK instead of DT_WORD_ELLIPSES, otherwise certain fonts' + // calcrect (for the dark box) will be wrong. + + RECT r, r2; + SetRect(&r, 0, 0, xR-TEXT_MARGIN*2, 2048); + m_text.DrawText(GetFont(TOOLTIP_FONT), str, -1, &r, DT_NOPREFIX | /*DT_SINGLELINE |*/ DT_WORDBREAK | DT_CALCRECT, 0xFFFFFFFF); + r2.bottom = yB - TEXT_MARGIN; + r2.right = xR - TEXT_MARGIN; + r2.left = r2.right - (r.right-r.left); + r2.top = r2.bottom - (r.bottom-r.top); + //m_text.DrawText(GetFont(TOOLTIP_FONT), str, -1, &r2, DT_NOPREFIX | /*DT_SINGLELINE |*/ DT_WORD_ELLIPSIS, 0xFF000000); + RECT r3 = r2; r3.left -= 4; r3.top -= 2; r3.right += 2; r3.bottom += 2; + DrawDarkTranslucentBox(&r3); + m_text.DrawText(GetFont(TOOLTIP_FONT), str, -1, &r2, DT_NOPREFIX | /*DT_SINGLELINE |*/ DT_WORDBREAK , 0xFFFFFFFF); +#endif +} + +#define MTO_UPPER_RIGHT 0 +#define MTO_UPPER_LEFT 1 +#define MTO_LOWER_RIGHT 2 +#define MTO_LOWER_LEFT 3 + +#define SelectFont(n) { \ + pFont = GetFont(n); \ + h = GetFontHeight(n); \ +} +#define MyTextOut(str, corner) { \ + SetRect(&r, 0, 0, xR-xL, 2048); \ + m_text.DrawText(pFont, str, -1, &r, DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_CALCRECT, 0xFFFFFFFF); \ + int w = r.right - r.left; \ + if (corner == MTO_UPPER_LEFT ) SetRect(&r, xL, *upper_left_corner_y, xL+w, *upper_left_corner_y + h); \ + else if (corner == MTO_UPPER_RIGHT) SetRect(&r, xR-w, *upper_right_corner_y, xR, *upper_right_corner_y + h); \ + else if (corner == MTO_LOWER_LEFT ) SetRect(&r, xL, *lower_left_corner_y - h, xL+w, *lower_left_corner_y); \ + else if (corner == MTO_LOWER_RIGHT) SetRect(&r, xR-w, *lower_right_corner_y - h, xR, *lower_right_corner_y); \ + m_text.DrawText(pFont, str, -1, &r, DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS, 0xFFFFFFFF); \ + if (corner == MTO_UPPER_LEFT ) *upper_left_corner_y += h; \ + else if (corner == MTO_UPPER_RIGHT) *upper_right_corner_y += h; \ + else if (corner == MTO_LOWER_LEFT ) *lower_left_corner_y -= h; \ + else if (corner == MTO_LOWER_RIGHT) *lower_right_corner_y -= h; \ +} + +void CPlugin::MyRenderUI( + int *upper_left_corner_y, // increment me! + int *upper_right_corner_y, // increment me! + int *lower_left_corner_y, // decrement me! + int *lower_right_corner_y, // decrement me! + int xL, + int xR + ) +{ + +#if 0 + // draw text messages directly to the back buffer. + // when you draw text into one of the four corners, + // draw the text at the current 'y' value for that corner + // (one of the first 4 params to this function), + // and then adjust that y value so that the next time + // text is drawn in that corner, it gets drawn above/below + // the previous text (instead of overtop of it). + // when drawing into the upper or lower LEFT corners, + // left-align your text to 'xL'. + // when drawing into the upper or lower RIGHT corners, + // right-align your text to 'xR'. + + // note: try to keep the bounding rectangles on the text small; + // the smaller the area that has to be locked (to draw the text), + // the faster it will be. (on some cards, drawing text is + // ferociously slow, so even if it works okay on yours, it might + // not work on another video card.) + // note: if you want some text to be on the screen often, and the text + // won't be changing every frame, please consider the poor folks + // whose video cards hate that; in that case you should probably + // draw the text just once, to a texture, and then display the + // texture each frame. This is how the help screen is done; see + // pluginshell.cpp for example code. + + RECT r; + char buf[512]; + LPD3DXFONT pFont = GetFont(DECORATIVE_FONT); + int h = GetFontHeight(DECORATIVE_FONT); + + if (!pFont) + return; + + if (!GetFont(DECORATIVE_FONT)) + return; + + // 1. render text in upper-right corner + { + // a) preset name + if (m_bShowPresetInfo) + { + SelectFont(DECORATIVE_FONT); + sprintf(buf, "%s ", m_pState->m_szDesc); + MyTextOut(buf, MTO_UPPER_RIGHT); + } + + // b) preset rating + if (m_bShowRating || GetTime() < m_fShowRatingUntilThisTime) + { + // see also: SetCurrentPresetRating() in milkdrop.cpp + SelectFont(DECORATIVE_FONT); + sprintf(buf, " Rating: %d ", (int)m_pState->m_fRating); + if (!m_bEnableRating) + strcat(buf, "[disabled] "); + MyTextOut(buf, MTO_UPPER_RIGHT); + } + + // c) fps display + if (m_bShowFPS) + { + SelectFont(DECORATIVE_FONT); + sprintf(buf, "fps: %4.2f ", GetFps()); // leave extra space @ end, so italicized fonts don't get clipped + MyTextOut(buf, MTO_UPPER_RIGHT); + } + + // d) custom timed message: + if (!m_bWarningsDisabled2 && GetTime() < m_fShowUserMessageUntilThisTime) + { + SelectFont(SIMPLE_FONT); + sprintf(buf, "%s ", m_szUserMessage); + MyTextOut(buf, MTO_UPPER_RIGHT); + } + + // e) debug information + if (m_bShowDebugInfo) + { + SelectFont(SIMPLE_FONT); + sprintf(buf, " pf monitor: %6.4f ", (float)(*m_pState->var_pf_monitor)); + MyTextOut(buf, MTO_UPPER_RIGHT); + } + } + + // 2. render text in lower-right corner + { + // waitstring tooltip: + if (m_waitstring.bActive && m_bShowMenuToolTips && m_waitstring.szToolTip[0]) + { + DrawTooltip(m_waitstring.szToolTip, xR, *lower_right_corner_y); + } + } + + // 3. render text in lower-left corner + { + char buf2[512]; + char buf3[512+1]; // add two extra spaces to end, so italicized fonts don't get clipped + + // render song title in lower-left corner: + if (m_bShowSongTitle) + { + SelectFont(DECORATIVE_FONT); + GetWinampSongTitle(GetWinampWindow(), buf, sizeof(buf)); // defined in utility.h/cpp + sprintf(buf3, "%s ", buf); + MyTextOut(buf3, MTO_LOWER_LEFT); + } + + // render song time & len above that: + if (m_bShowSongTime || m_bShowSongLen) + { + GetWinampSongPosAsText(GetWinampWindow(), buf); // defined in utility.h/cpp + GetWinampSongLenAsText(GetWinampWindow(), buf2); // defined in utility.h/cpp + if (m_bShowSongTime && m_bShowSongLen) + sprintf(buf3, "%s / %s ", buf, buf2); + else if (m_bShowSongTime) + strcpy(buf3, buf); + else + strcpy(buf3, buf2); + + SelectFont(DECORATIVE_FONT); + MyTextOut(buf3, MTO_LOWER_LEFT); + } + } + + // 4. render text in upper-left corner + { + char buf[8192*3]; // leave extra space for &->&&, and [,[,& insertion + + SelectFont(SIMPLE_FONT); + + // stuff for loading presets, menus, etc: + + if (m_waitstring.bActive) + { + // 1. draw the prompt string + MyTextOut(m_waitstring.szPrompt, MTO_UPPER_LEFT); + + // 2. reformat the waitstring text for display + int bBrackets = m_waitstring.nSelAnchorPos != -1 && m_waitstring.nSelAnchorPos != m_waitstring.nCursorPos; + int bCursorBlink = bBrackets ? 0 : ((int)(GetTime()*3.0f) % 2); + strcpy(buf, m_waitstring.szText); + + int temp_cursor_pos = m_waitstring.nCursorPos; + int temp_anchor_pos = m_waitstring.nSelAnchorPos; + + // replace &'s in the code with '&&' so they actually show up + { + char buf2[sizeof(buf)]; + int len = strlen(buf), y=0; + for (int x=0; x<=len; x++) + { + buf2[y++] = buf[x]; + if (buf[x]=='&' && (x != m_waitstring.nCursorPos || !bCursorBlink)) + { + buf2[y++] = '&'; + if (x temp_anchor_pos) ? temp_cursor_pos - 1 : temp_anchor_pos - 1; + int len = strlen(buf); + int i; + + for (i=len; i>end; i--) + buf[i+1] = buf[i]; + buf[end+1] = ']'; + len++; + + for (i=len; i>=start; i--) + buf[i+1] = buf[i]; + buf[start] = '['; + len++; + } + else + { + // underline the current cursor position by inserting an '&' + if (temp_cursor_pos == (int)strlen(buf)) + { + if (bCursorBlink) + strcat(buf, "_"); + else + strcat(buf, " "); + } + else if (bCursorBlink) + { + for (int i=strlen(buf); i>=temp_cursor_pos; i--) + buf[i+1] = buf[i]; + buf[temp_cursor_pos] = '&'; + } + } + + RECT rect; + SetRect(&rect, xL, *upper_left_corner_y, xR, *lower_left_corner_y); + rect.top += PLAYLIST_INNER_MARGIN; + rect.left += PLAYLIST_INNER_MARGIN; + rect.right -= PLAYLIST_INNER_MARGIN; + rect.bottom -= PLAYLIST_INNER_MARGIN; + + // then draw the edit string + if (m_waitstring.bDisplayAsCode) + { + char buf2[8192]; + int top_of_page_pos = 0; + + // compute top_of_page_pos so that the line the cursor is on will show. + // also compute dims of the black rectangle while we're at it. + { + int start = 0; + int pos = 0; + int ypixels = 0; + int page = 1; + int exit_on_next_page = 0; + + RECT box = rect; + box.right = box.left; + box.bottom = box.top; + + while (buf[pos] != 0) // for each line of text... (note that it might wrap) + { + start = pos; + while (buf[pos] != LINEFEED_CONTROL_CHAR && buf[pos] != 0) + pos++; + + char ch = buf[pos]; + buf[pos] = 0; + sprintf(buf2, " %s ", &buf[start]); + RECT r2 = rect; + r2.bottom = 4096; + m_text.DrawText(GetFont(SIMPLE_FONT), buf2, -1, &r2, DT_CALCRECT | DT_WORDBREAK, 0xFFFFFFFF); + int h = r2.bottom-r2.top; + ypixels += h; + buf[pos] = ch; + + if (start > m_waitstring.nCursorPos) // make sure 'box' gets updated for each line on this page + exit_on_next_page = 1; + + if (ypixels > rect.bottom-rect.top) // this line belongs on the next page + { + if (exit_on_next_page) + { + buf[start] = 0; // so text stops where the box stops, when we draw the text + break; + } + + ypixels = h; + top_of_page_pos = start; + page++; + + box = rect; + box.right = box.left; + box.bottom = box.top; + } + box.bottom += h; + box.right = max(box.right, box.left + r2.right-r2.left); + + if (buf[pos]==0) + break; + pos++; + } + + // use r2 to draw a dark box: + box.top -= PLAYLIST_INNER_MARGIN; + box.left -= PLAYLIST_INNER_MARGIN; + box.right += PLAYLIST_INNER_MARGIN; + box.bottom += PLAYLIST_INNER_MARGIN; + DrawDarkTranslucentBox(&box); + *upper_left_corner_y += box.bottom - box.top + PLAYLIST_INNER_MARGIN*3; + + sprintf(m_waitstring.szToolTip, " Page %d ", page); + } + + // display multiline (replace all character 13's with a CR) + { + int start = top_of_page_pos; + int pos = top_of_page_pos; + + while (buf[pos] != 0) + { + while (buf[pos] != LINEFEED_CONTROL_CHAR && buf[pos] != 0) + pos++; + + char ch = buf[pos]; + buf[pos] = 0; + sprintf(buf2, " %s ", &buf[start]); + DWORD color = MENU_COLOR; + if (m_waitstring.nCursorPos >= start && m_waitstring.nCursorPos <= pos) + color = MENU_HILITE_COLOR; + rect.top += m_text.DrawText(GetFont(SIMPLE_FONT), buf2, -1, &rect, DT_WORDBREAK, color); + buf[pos] = ch; + + if (rect.top > rect.bottom) + break; + + if (buf[pos] != 0) pos++; + start = pos; + } + } + // note: *upper_left_corner_y is updated above, when the dark box is drawn. + } + else + { + // display on one line + char buf2[8192]; + sprintf(buf2, " %s ", buf); + RECT box = rect; + box.bottom = 4096; + m_text.DrawText(GetFont(SIMPLE_FONT), buf2, -1, &box, DT_WORDBREAK | DT_CALCRECT, MENU_COLOR ); + + // use r2 to draw a dark box: + box.top -= PLAYLIST_INNER_MARGIN; + box.left -= PLAYLIST_INNER_MARGIN; + box.right += PLAYLIST_INNER_MARGIN; + box.bottom += PLAYLIST_INNER_MARGIN; + DrawDarkTranslucentBox(&box); + *upper_left_corner_y += box.bottom - box.top + PLAYLIST_INNER_MARGIN*3; + + m_text.DrawText(GetFont(SIMPLE_FONT), buf2, -1, &rect, DT_WORDBREAK, MENU_COLOR ); + } + } + else if (m_UI_mode == UI_MENU) + { + assert(m_pCurMenu); + SetRect(&r, xL, *upper_left_corner_y, xR, *lower_left_corner_y); + + RECT darkbox; + m_pCurMenu->DrawMenu(r, xR, *lower_right_corner_y, 1, &darkbox); + *upper_left_corner_y += darkbox.bottom - darkbox.top + PLAYLIST_INNER_MARGIN*3; + + darkbox.right += PLAYLIST_INNER_MARGIN*2; + darkbox.bottom += PLAYLIST_INNER_MARGIN*2; + DrawDarkTranslucentBox(&darkbox); + + r.top += PLAYLIST_INNER_MARGIN; + r.left += PLAYLIST_INNER_MARGIN; + r.right += PLAYLIST_INNER_MARGIN; + r.bottom += PLAYLIST_INNER_MARGIN; + m_pCurMenu->DrawMenu(r, xR, *lower_right_corner_y); + } + else if (m_UI_mode == UI_LOAD_DEL) + { + RECT rect; + SetRect(&rect, xL, *upper_left_corner_y, xR, *lower_left_corner_y); + rect.top += m_text.DrawText(GetFont(SIMPLE_FONT), "Are you SURE you want to delete this preset? [y/N]", -1, &rect, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX, MENU_COLOR); + sprintf(buf, "(preset to delete: %s)", m_pPresetAddr[m_nPresetListCurPos]); + rect.top += m_text.DrawText(GetFont(SIMPLE_FONT), buf, -1, &rect, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX, MENU_COLOR); + *upper_left_corner_y = rect.top; + } + else if (m_UI_mode == UI_SAVE_OVERWRITE) + { + RECT rect; + SetRect(&rect, xL, *upper_left_corner_y, xR, *lower_left_corner_y); + rect.top += m_text.DrawText(GetFont(SIMPLE_FONT), "This file already exists. Overwrite it? [y/N]", -1, &rect, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX, MENU_COLOR); + sprintf(buf, "(file in question: %s.milk)", m_waitstring.szText); + rect.top += m_text.DrawText(GetFont(SIMPLE_FONT), buf, -1, &rect, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX, MENU_COLOR); + *upper_left_corner_y = rect.top; + } + else if (m_UI_mode == UI_LOAD) + { + if (m_nPresets == 0) + { + // note: this error message is repeated in milkdrop.cpp in LoadRandomPreset() + sprintf(m_szUserMessage, "ERROR: No preset files found in %s*.milk", m_szPresetDir); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + m_UI_mode = UI_REGULAR; + } + else + { + MyTextOut("Load which preset? (arrow keys to scroll; Esc/close, Enter/select, INS/rename; DEL/delete)", MTO_UPPER_LEFT); + + RECT rect; + SetRect(&rect, xL, *upper_left_corner_y, xR, *lower_left_corner_y); + rect.top += PLAYLIST_INNER_MARGIN; + rect.left += PLAYLIST_INNER_MARGIN; + rect.right -= PLAYLIST_INNER_MARGIN; + rect.bottom -= PLAYLIST_INNER_MARGIN; + + int lines_available = (rect.bottom - rect.top - PLAYLIST_INNER_MARGIN*2) / GetFontHeight(SIMPLE_FONT); + + if (lines_available < 1) + { + // force it + rect.bottom = rect.top + GetFontHeight(SIMPLE_FONT) + 1; + lines_available = 1; + } + if (lines_available > MAX_PRESETS_PER_PAGE) + lines_available = MAX_PRESETS_PER_PAGE; + + if (m_bUserPagedDown) + { + m_nPresetListCurPos += lines_available; + if (m_nPresetListCurPos >= m_nPresets) + m_nPresetListCurPos = m_nPresets - 1; + + // remember this preset's name so the next time they hit 'L' it jumps straight to it + //strcpy(m_szLastPresetSelected, m_pPresetAddr[m_nPresetListCurPos]); + + m_bUserPagedDown = false; + } + + if (m_bUserPagedUp) + { + m_nPresetListCurPos -= lines_available; + if (m_nPresetListCurPos < 0) + m_nPresetListCurPos = 0; + + // remember this preset's name so the next time they hit 'L' it jumps straight to it + //strcpy(m_szLastPresetSelected, m_pPresetAddr[m_nPresetListCurPos]); + + m_bUserPagedUp = false; + } + + int i; + int first_line = m_nPresetListCurPos - (m_nPresetListCurPos % lines_available); + int last_line = first_line + lines_available; + char str[512], str2[512]; + + if (last_line > m_nPresets) + last_line = m_nPresets; + + // tooltip: + if (m_bShowMenuToolTips) + { + char buf[256]; + sprintf(buf, " (page %d of %d) ", m_nPresetListCurPos/lines_available+1, (m_nPresets+lines_available-1)/lines_available); + DrawTooltip(buf, xR, *lower_right_corner_y); + } + + RECT orig_rect = rect; + + RECT box; + box.top = rect.top; + box.left = rect.left; + box.right = rect.left; + box.bottom = rect.top; + + for (int pass=0; pass<2; pass++) + { + //if (pass==1) + // GetFont(SIMPLE_FONT)->Begin(); + + rect = orig_rect; + for (i=first_line; im_szDesc, str)==0) + bIsRunning = true; + } + + if (bIsRunning && m_bPresetLockedByUser) + strcat(str2, " "); + + DWORD color = bIsDir ? DIR_COLOR : PLAYLIST_COLOR_NORMAL; + if (bIsRunning) + color = bIsSelected ? PLAYLIST_COLOR_BOTH : PLAYLIST_COLOR_PLAYING_TRACK; + else if (bIsSelected) + color = PLAYLIST_COLOR_HILITE_TRACK; + + RECT r2 = rect; + rect.top += m_text.DrawText(GetFont(SIMPLE_FONT), str2, -1, &r2, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX | (pass==0 ? DT_CALCRECT : 0), color); + + if (pass==0) // calculating dark box + { + box.right = max(box.right, box.left + r2.right-r2.left); + box.bottom += r2.bottom-r2.top; + } + } + + //if (pass==1) + // GetFont(SIMPLE_FONT)->End(); + + if (pass==0) // calculating dark box + { + box.top -= PLAYLIST_INNER_MARGIN; + box.left -= PLAYLIST_INNER_MARGIN; + box.right += PLAYLIST_INNER_MARGIN; + box.bottom += PLAYLIST_INNER_MARGIN; + DrawDarkTranslucentBox(&box); + *upper_left_corner_y = box.bottom + PLAYLIST_INNER_MARGIN; + } + } + } + } + } + +#endif +} + +//---------------------------------------------------------------------- + +LRESULT CPlugin::MyWindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + // You can handle Windows messages here while the plugin is running, + // such as mouse events (WM_MOUSEMOVE/WM_LBUTTONDOWN), keypresses + // (WK_KEYDOWN/WM_CHAR), and so on. + // This function is threadsafe (thanks to Winamp's architecture), + // so you don't have to worry about using semaphores or critical + // sections to read/write your class member variables. + // If you don't handle a message, let it continue on the usual path + // (to Winamp) by returning DefWindowProc(hWnd,uMsg,wParam,lParam). + // If you do handle a message, prevent it from being handled again + // (by Winamp) by returning 0. + + // IMPORTANT: For the WM_KEYDOWN, WM_KEYUP, and WM_CHAR messages, + // you must return 0 if you process the message (key), + // and 1 if you do not. DO NOT call DefWindowProc() + // for these particular messages! + + SHORT mask = 1 << (sizeof(SHORT)*8 - 1); + bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0; + bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0; + + switch (uMsg) + { + + case WM_COMMAND: + { + switch (LOWORD(wParam)) { + case ID_VIS_NEXT: + LoadNextPreset(m_fBlendTimeUser); + return 0; + case ID_VIS_PREV: + LoadPreviousPreset(m_fBlendTimeUser); + return 0; + case ID_VIS_RANDOM: { + USHORT v = HIWORD(wParam) ? 1 : 0; + if (wParam >> 16 == 0xFFFF) { + SendMessage(GetWinampWindow(),WM_WA_IPC,!m_bHoldPreset,IPC_CB_VISRANDOM); + break; + } + if (!v) { + m_bHoldPreset = 1; + m_bSequentialPresetOrder = 1; + } else { + m_bHoldPreset = 0; + m_bSequentialPresetOrder = 0; + } + if (v) LoadRandomPreset(m_fBlendTimeUser); + sprintf(m_szUserMessage, "random presets %s", v ? "on" : "off"); + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + return 0; + } + case ID_VIS_FS: + if (GetFrame() > 0) ToggleFullScreen(); + return 0; + case ID_VIS_CFG: + ToggleHelp(); + return 0; + case ID_VIS_MENU: + POINT pt; + GetCursorPos(&pt); + SendMessage(hWnd, WM_CONTEXTMENU, (int)hWnd, (pt.y << 16) | pt.x); + return 0; + } + } + + /* + case WM_SETFOCUS: + m_bOrigScrollLockState = GetKeyState(VK_SCROLL) & 1; + SetScrollLock(m_bMilkdropScrollLockState); + return DefWindowProc(hWnd, uMsg, wParam, lParam); + + case WM_KILLFOCUS: + m_bMilkdropScrollLockState = GetKeyState(VK_SCROLL) & 1; + SetScrollLock(m_bOrigScrollLockState); + return DefWindowProc(hWnd, uMsg, wParam, lParam); + */ + + case WM_CHAR: // plain & simple alphanumeric keys + if (m_waitstring.bActive) // if user is in the middle of editing a string + { + if (wParam >= ' ' && wParam <= 'z') + { + int len = strlen(m_waitstring.szText); + + if (m_waitstring.bFilterBadChars && + (wParam == '\"' || + wParam == '\\' || + wParam == '/' || + wParam == ':' || + wParam == '*' || + wParam == '?' || + wParam == '|' || + wParam == '<' || + wParam == '>' || + wParam == '&')) // NOTE: '&' is legal in filenames, but we try to avoid it since during GDI display it acts as a control code (it will not show up, but instead, underline the character following it). + { + // illegal char + strcpy(m_szUserMessage, "(illegal character)"); + m_fShowUserMessageUntilThisTime = GetTime() + 2.5f; + } + else if (len+1 >= m_waitstring.nMaxLen) + { + // m_waitstring.szText has reached its limit + strcpy(m_szUserMessage, "(string too long)"); + m_fShowUserMessageUntilThisTime = GetTime() + 2.5f; + } + else + { + m_fShowUserMessageUntilThisTime = GetTime(); // if there was an error message already, clear it + + char buf[16]; + sprintf(buf, "%c", wParam); + + if (m_waitstring.nSelAnchorPos != -1) + WaitString_NukeSelection(); + + if (m_waitstring.bOvertypeMode) + { + // overtype mode + if (m_waitstring.nCursorPos == len) + strcat(m_waitstring.szText, buf); + else + m_waitstring.szText[m_waitstring.nCursorPos] = buf[0]; + m_waitstring.nCursorPos++; + } + else + { + // insert mode: + for (int i=len; i>=m_waitstring.nCursorPos; i--) + m_waitstring.szText[i+1] = m_waitstring.szText[i]; + m_waitstring.szText[m_waitstring.nCursorPos] = buf[0]; + m_waitstring.nCursorPos++; + } + } + } + return 0; // we processed (or absorbed) the key + } + else if (m_UI_mode == UI_LOAD_DEL) // waiting to confirm file delete + { + if (wParam == 'y' || wParam == 'Y') + { + // first add pathname to filename + char szDelFile[512]; + sprintf(szDelFile, "%s%s", GetPresetDir(), m_pPresetAddr[m_nPresetListCurPos]); + + DeletePresetFile(szDelFile); + } + + m_UI_mode = UI_LOAD; + + return 0; // we processed (or absorbed) the key + } + else if (m_UI_mode == UI_SAVE_OVERWRITE) // waiting to confirm overwrite file on save + { + if (wParam == 'y' || wParam == 'Y') + { + // first add pathname + extension to filename + char szNewFile[512]; + sprintf(szNewFile, "%s%s.milk", GetPresetDir(), m_waitstring.szText); + + SavePresetAs(szNewFile); + + // exit waitstring mode + m_UI_mode = UI_REGULAR; + m_waitstring.bActive = false; + m_bPresetLockedByCode = false; + } + else if ((wParam >= ' ' && wParam <= 'z') || wParam == 27) // 27 is the ESCAPE key + { + // go back to SAVE AS mode + m_UI_mode = UI_SAVEAS; + m_waitstring.bActive = true; + } + + return 0; // we processed (or absorbed) the key + } + else // normal handling of a simple key (all non-virtual-key hotkeys end up here) + { + if (HandleRegularKey(wParam)==0) + return 0; + } + return 1; // end case WM_CHAR + + case WM_KEYDOWN: // virtual-key codes + // Note that some keys will never reach this point, since they are + // intercepted by the plugin shell (see PluginShellWindowProc(), + // at the end of pluginshell.cpp for which ones). + // For a complete list of virtual-key codes, look up the keyphrase + // "virtual-key codes [win32]" in the msdn help. + switch(wParam) + { + case VK_F2: m_bShowSongTitle = !m_bShowSongTitle; return 0; // we processed (or absorbed) the key + case VK_F3: + if (m_bShowSongTime && m_bShowSongLen) + { + m_bShowSongTime = false; + m_bShowSongLen = false; + } + else if (m_bShowSongTime && !m_bShowSongLen) + { + m_bShowSongLen = true; + } + else + { + m_bShowSongTime = true; + m_bShowSongLen = false; + } + return 0; // we processed (or absorbed) the key + case VK_F4: m_bShowPresetInfo = !m_bShowPresetInfo; return 0; // we processed (or absorbed) the key + case VK_F5: m_bShowFPS = !m_bShowFPS; return 0; // we processed (or absorbed) the key + case VK_F6: m_bShowRating = !m_bShowRating; return 0; // we processed (or absorbed) the key + case VK_F7: + if (m_nNumericInputMode == NUMERIC_INPUT_MODE_CUST_MSG) + ReadCustomMessages(); // re-read custom messages + return 0; // we processed (or absorbed) the key + case VK_F8: + { + m_UI_mode = UI_CHANGEDIR; + + // enter WaitString mode + m_waitstring.bActive = true; + m_waitstring.bFilterBadChars = false; + m_waitstring.bDisplayAsCode = false; + m_waitstring.nSelAnchorPos = -1; + m_waitstring.nMaxLen = min(sizeof(m_waitstring.szText)-1, MAX_PATH - 1); + strcpy(m_waitstring.szText, GetPresetDir()); + { + // for subtle beauty - remove the trailing '\' from the directory name (if it's not just "x:\") + int len = strlen(m_waitstring.szText); + if (len > 3 && m_waitstring.szText[len-1] == '\\') + m_waitstring.szText[len-1] = 0; + } + strcpy(m_waitstring.szPrompt, "Directory to jump to:"); + m_waitstring.szToolTip[0] = 0; + m_waitstring.nCursorPos = strlen(m_waitstring.szText); // set the starting edit position + } + return 0; // we processed (or absorbed) the key + case VK_F9: + if (bShiftHeldDown) + m_fStereoSep /= 1.08f; + else if (bCtrlHeldDown) + m_fStereoSep *= 1.08f; + else + m_pState->m_bRedBlueStereo = !m_pState->m_bRedBlueStereo; + if (m_fStereoSep < 0.1f) m_fStereoSep = 0.1f; + if (m_fStereoSep > 10) m_fStereoSep = 10; + return FALSE; + case VK_SCROLL: + //BYTE keys[256]; + //GetKeyboardState(keys); + //m_bPresetLockedByUser = (keys[VK_SCROLL] & 1) ? true : false; + m_bPresetLockedByUser = GetKeyState(VK_SCROLL) & 1; + return 0; // we processed (or absorbed) the key + //case VK_F6: break; + //case VK_F7: conflict + //case VK_F8: break; + //case VK_F9: conflict + } + + // next handle the waitstring case (for string-editing), + // then the menu navigation case, + // then handle normal case (handle the message normally or pass on to winamp) + + // case 1: waitstring mode + if (m_waitstring.bActive) + { + // handle arrow keys, home, end, etc. + + SHORT mask = 1 << (sizeof(SHORT)*8 - 1); // we want the highest-order bit + bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0; + bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0; + + if (wParam == VK_LEFT || wParam == VK_RIGHT || + wParam == VK_HOME || wParam == VK_END || + wParam == VK_UP || wParam == VK_DOWN) + { + if (bShiftHeldDown) + { + if (m_waitstring.nSelAnchorPos == -1) + m_waitstring.nSelAnchorPos = m_waitstring.nCursorPos; + } + else + { + m_waitstring.nSelAnchorPos = -1; + } + } + + if (bCtrlHeldDown) // copy/cut/paste + { + switch(wParam) + { + case 'c': + case 'C': + case VK_INSERT: + WaitString_Copy(); + return 0; // we processed (or absorbed) the key + case 'x': + case 'X': + WaitString_Cut(); + return 0; // we processed (or absorbed) the key + case 'v': + case 'V': + WaitString_Paste(); + return 0; // we processed (or absorbed) the key + case VK_LEFT: WaitString_SeekLeftWord(); return 0; // we processed (or absorbed) the key + case VK_RIGHT: WaitString_SeekRightWord(); return 0; // we processed (or absorbed) the key + case VK_HOME: m_waitstring.nCursorPos = 0; return 0; // we processed (or absorbed) the key + case VK_END: m_waitstring.nCursorPos = strlen(m_waitstring.szText); return 0; // we processed (or absorbed) the key + case VK_RETURN: + if (m_waitstring.bDisplayAsCode) + { + // CTRL+ENTER accepts the string -> finished editing + //assert(m_pCurMenu); + m_pCurMenu->OnWaitStringAccept(m_waitstring.szText); + // OnWaitStringAccept calls the callback function. See the + // calls to CMenu::AddItem from milkdrop.cpp to find the + // callback functions for different "waitstrings". + m_waitstring.bActive = false; + m_UI_mode = UI_MENU; + } + return 0; // we processed (or absorbed) the key + } + } + else // waitstring mode key pressed, and ctrl NOT held down + { + switch(wParam) + { + case VK_INSERT: + m_waitstring.bOvertypeMode = !m_waitstring.bOvertypeMode; + return 0; // we processed (or absorbed) the key + + case VK_LEFT: + if (m_waitstring.nCursorPos > 0) + m_waitstring.nCursorPos--; + return 0; // we processed (or absorbed) the key + + case VK_RIGHT: + if (m_waitstring.nCursorPos < (int)strlen(m_waitstring.szText)) + m_waitstring.nCursorPos++; + return 0; // we processed (or absorbed) the key + + case VK_HOME: + m_waitstring.nCursorPos -= WaitString_GetCursorColumn(); + return 0; // we processed (or absorbed) the key + + case VK_END: + m_waitstring.nCursorPos += WaitString_GetLineLength() - WaitString_GetCursorColumn(); + return 0; // we processed (or absorbed) the key + + case VK_UP: + WaitString_SeekUpOneLine(); + return 0; // we processed (or absorbed) the key + + case VK_DOWN: + WaitString_SeekDownOneLine(); + return 0; // we processed (or absorbed) the key + + case VK_BACK: + if (m_waitstring.nSelAnchorPos != -1) + { + WaitString_NukeSelection(); + } + else if (m_waitstring.nCursorPos > 0) + { + int len = strlen(m_waitstring.szText); + for (int i=m_waitstring.nCursorPos-1; iGetCurItem()->m_lParam; + int ret; + switch(m_UI_mode) + { + case UI_IMPORT_WAVE : ret = m_pState->m_wave[i].Import("custom wave", m_waitstring.szText, 0); break; + case UI_EXPORT_WAVE : ret = m_pState->m_wave[i].Export("custom wave", m_waitstring.szText, 0); break; + case UI_IMPORT_SHAPE: ret = m_pState->m_shape[i].Import("custom shape", m_waitstring.szText, 0); break; + case UI_EXPORT_SHAPE: ret = m_pState->m_shape[i].Export("custom shape", m_waitstring.szText, 0); break; + } + + if (bImport) + m_pState->RecompileExpressions(1); + + m_fShowUserMessageUntilThisTime = GetTime() - 1.0f; // if there was an error message already, clear it + if (!ret) + { + if (m_UI_mode==UI_IMPORT_WAVE || m_UI_mode==UI_IMPORT_SHAPE) + strcpy(m_szUserMessage, "(error importing - bad filename, or file does not exist)"); + else + strcpy(m_szUserMessage, "(error exporting - bad filename, or file can not be overwritten)"); + m_fShowUserMessageUntilThisTime = GetTime() + 2.5f; + } + + m_waitstring.bActive = false; + m_UI_mode = UI_MENU; + m_bPresetLockedByCode = false; + } + else if (m_UI_mode == UI_SAVEAS) + { + // first add pathname + extension to filename + char szNewFile[512]; + sprintf(szNewFile, "%s%s.milk", GetPresetDir(), m_waitstring.szText); + + if (GetFileAttributes(szNewFile) != -1) // check if file already exists + { + // file already exists -> overwrite it? + m_waitstring.bActive = false; + m_UI_mode = UI_SAVE_OVERWRITE; + } + else + { + SavePresetAs(szNewFile); + + // exit waitstring mode + m_UI_mode = UI_REGULAR; + m_waitstring.bActive = false; + m_bPresetLockedByCode = false; + } + } + else if (m_UI_mode == UI_EDIT_MENU_STRING) + { + if (m_waitstring.bDisplayAsCode) + { + if (m_waitstring.nSelAnchorPos != -1) + WaitString_NukeSelection(); + + int len = strlen(m_waitstring.szText); + if (len + 1 < m_waitstring.nMaxLen) + { + // insert a linefeed. Use CTRL+return to accept changes in this case. + for (int pos=len+1; pos > m_waitstring.nCursorPos; pos--) + m_waitstring.szText[pos] = m_waitstring.szText[pos - 1]; + m_waitstring.szText[m_waitstring.nCursorPos++] = LINEFEED_CONTROL_CHAR; + + m_fShowUserMessageUntilThisTime = GetTime() - 1.0f; // if there was an error message already, clear it + } + else + { + // m_waitstring.szText has reached its limit + strcpy(m_szUserMessage, "(string too long)"); + m_fShowUserMessageUntilThisTime = GetTime() + 2.5f; + } + } + else + { + // finished editing + //assert(m_pCurMenu); + m_pCurMenu->OnWaitStringAccept(m_waitstring.szText); + // OnWaitStringAccept calls the callback function. See the + // calls to CMenu::AddItem from milkdrop.cpp to find the + // callback functions for different "waitstrings". + m_waitstring.bActive = false; + m_UI_mode = UI_MENU; + } + } + else if (m_UI_mode == UI_CHANGEDIR) + { + m_fShowUserMessageUntilThisTime = GetTime(); // if there was an error message already, clear it + + // change dir + char szOldDir[512]; + char szNewDir[512]; + strcpy(szOldDir, GetPresetDir()); + strcpy(szNewDir, m_waitstring.szText); + + int len = strlen(szNewDir); + if (len > 0 && szNewDir[len-1] != '\\') + strcat(szNewDir, "\\"); + + strcpy(GetPresetDir(), szNewDir); + UpdatePresetList(); + if (m_nPresets == 0) + { + // new dir. was invalid -> allow them to try again + strcpy(GetPresetDir(), szOldDir); + UpdatePresetList(); + + // give them a warning + strcpy(m_szUserMessage, "(invalid path)"); + m_fShowUserMessageUntilThisTime = GetTime() + 3.5f; + } + else + { + // success + strcpy(GetPresetDir(), szNewDir); + + // save new path to registry + WritePrivateProfileString("settings","szPresetDir",GetPresetDir(),GetConfigIniFile()); + + // set current preset index to -1 because current preset is no longer in the list + m_nCurrentPreset = -1; + + // go to file load menu + m_waitstring.bActive = false; + m_UI_mode = UI_LOAD; + } + } + return 0; // we processed (or absorbed) the key + + case VK_ESCAPE: + if (m_UI_mode == UI_LOAD_RENAME) + { + m_waitstring.bActive = false; + m_UI_mode = UI_LOAD; + } + else if ( + m_UI_mode == UI_SAVEAS || + m_UI_mode == UI_SAVE_OVERWRITE || + m_UI_mode == UI_EXPORT_SHAPE || + m_UI_mode == UI_IMPORT_SHAPE || + m_UI_mode == UI_EXPORT_WAVE || + m_UI_mode == UI_IMPORT_WAVE) + { + m_bPresetLockedByCode = false; + m_waitstring.bActive = false; + m_UI_mode = UI_REGULAR; + } + else if (m_UI_mode == UI_EDIT_MENU_STRING) + { + m_waitstring.bActive = false; + if (m_waitstring.bDisplayAsCode) // if were editing code... + m_UI_mode = UI_MENU; // return to menu + else + m_UI_mode = UI_REGULAR; // otherwise don't (we might have been editing a filename, for example) + } + else /*if (m_UI_mode == UI_EDIT_MENU_STRING || m_UI_mode == UI_CHANGEDIR || 1)*/ + { + m_waitstring.bActive = false; + m_UI_mode = UI_REGULAR; + } + return 0; // we processed (or absorbed) the key + } + } + + // don't let keys go anywhere else + return 0; // we processed (or absorbed) the key + } + + // case 2: menu is up & gets the keyboard input + if (m_UI_mode == UI_MENU) + { + //assert(m_pCurMenu); + if (m_pCurMenu->HandleKeydown(hWnd, uMsg, wParam, lParam) == 0) + return 0; // we processed (or absorbed) the key + } + + // case 3: handle non-character keys (virtual keys) and return 0. + // if we don't handle them, return 1, and the shell will + // (passing some to the shell's key bindings, some to Winamp, + // and some to DefWindowProc) + // note: regular hotkeys should be handled in HandleRegularKey. + switch(wParam) + { + case VK_LEFT: + case VK_RIGHT: + if (m_UI_mode == UI_LOAD) + { + // it's annoying when the music skips if you hit the left arrow from the Load menu, so instead, we exit the menu + if (wParam == VK_LEFT) m_UI_mode = UI_REGULAR; + return 0; // we processed (or absorbed) the key + } + break; + + case VK_ESCAPE: + if (m_UI_mode == UI_LOAD || + m_UI_mode == UI_MENU) + { + m_UI_mode = UI_REGULAR; + return 0; // we processed (or absorbed) the key + } + else if (m_UI_mode == UI_LOAD_DEL) + { + m_UI_mode = UI_LOAD; + return 0; // we processed (or absorbed) the key + } + else if (m_UI_mode == UI_SAVE_OVERWRITE) + { + m_UI_mode = UI_SAVEAS; + // return to waitstring mode, leaving all the parameters as they were before: + m_waitstring.bActive = true; + return 0; // we processed (or absorbed) the key + } + /*else if (hwnd == GetPluginWindow()) // (don't close on ESC for text window) + { + dumpmsg("User pressed ESCAPE"); + //m_bExiting = true; + PostMessage(hwnd, WM_CLOSE, 0, 0); + return 0; // we processed (or absorbed) the key + }*/ + break; + + case VK_UP: + if (m_UI_mode == UI_LOAD) + { + if (m_nPresetListCurPos > 0) + m_nPresetListCurPos--; + return 0; // we processed (or absorbed) the key + + // remember this preset's name so the next time they hit 'L' it jumps straight to it + //strcpy(m_szLastPresetSelected, m_pPresetAddr[m_nPresetListCurPos]); + } + break; + + case VK_DOWN: + if (m_UI_mode == UI_LOAD) + { + if (m_nPresetListCurPos < m_nPresets - 1) + m_nPresetListCurPos++; + return 0; // we processed (or absorbed) the key + + // remember this preset's name so the next time they hit 'L' it jumps straight to it + //strcpy(m_szLastPresetSelected, m_pPresetAddr[m_nPresetListCurPos]); + } + break; + + case VK_SPACE: + if (!m_bPresetLockedByCode) + { + LoadRandomPreset(m_fBlendTimeUser); + return 0; // we processed (or absorbed) the key + } + break; + + case VK_PRIOR: + if (m_UI_mode == UI_LOAD) + { + m_bUserPagedUp = true; + return 0; // we processed (or absorbed) the key + } + break; + case VK_NEXT: + if (m_UI_mode == UI_LOAD) + { + m_bUserPagedDown = true; + return 0; // we processed (or absorbed) the key + } + break; + case VK_HOME: + if (m_UI_mode == UI_LOAD) + { + m_nPresetListCurPos = 0; + return 0; // we processed (or absorbed) the key + } + break; + case VK_END: + if (m_UI_mode == UI_LOAD) + { + m_nPresetListCurPos = m_nPresets - 1; + return 0; // we processed (or absorbed) the key + } + break; + + case VK_DELETE: + if (m_UI_mode == UI_LOAD) + { + if (m_pPresetAddr[m_nPresetListCurPos][0] != '*') // can't delete directories + m_UI_mode = UI_LOAD_DEL; + return 0; // we processed (or absorbed) the key + } + else //if (m_nNumericInputDigits == 0) + { + if (m_nNumericInputMode == NUMERIC_INPUT_MODE_CUST_MSG) + { + m_nNumericInputDigits = 0; + m_nNumericInputNum = 0; + + // stop display of text message. + m_supertext.fStartTime = -1.0f; + return 0; // we processed (or absorbed) the key + } + else if (m_nNumericInputMode == NUMERIC_INPUT_MODE_SPRITE) + { + // kill newest sprite (regular DELETE key) + // oldest sprite (SHIFT + DELETE), + // or all sprites (CTRL + SHIFT + DELETE). + + m_nNumericInputDigits = 0; + m_nNumericInputNum = 0; + + SHORT mask = 1 << (sizeof(SHORT)*8 - 1); // we want the highest-order bit + bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0; + bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0; + + if (bShiftHeldDown && bCtrlHeldDown) + { + for (int x=0; x frame) || + (bShiftHeldDown && m_texmgr.m_tex[x].nStartFrame < frame)) + { + newest = x; + frame = m_texmgr.m_tex[x].nStartFrame; + } + } + } + + if (newest != -1) + m_texmgr.KillTex(newest); + } + return 0; // we processed (or absorbed) the key + } + } + break; + + case VK_INSERT: // RENAME + if (m_UI_mode == UI_LOAD) + { + if (m_pPresetAddr[m_nPresetListCurPos][0] != '*') // can't rename directories + { + // go into RENAME mode + m_UI_mode = UI_LOAD_RENAME; + m_waitstring.bActive = true; + m_waitstring.bFilterBadChars = true; + m_waitstring.bDisplayAsCode = false; + m_waitstring.nSelAnchorPos = -1; + m_waitstring.nMaxLen = min(sizeof(m_waitstring.szText)-1, MAX_PATH - strlen(GetPresetDir()) - 6); // 6 for the extension + null char. We set this because win32 LoadFile, MoveFile, etc. barf if the path+filename+ext are > MAX_PATH chars. + + // initial string is the filename, minus the extension + strcpy(m_waitstring.szText, m_pPresetAddr[m_nPresetListCurPos]); + RemoveExtension(m_waitstring.szText); + + // set the prompt & 'tooltip' + sprintf(m_waitstring.szPrompt, "Enter the new name for \"%s\":", m_waitstring.szText); + m_waitstring.szToolTip[0] = 0; + + // set the starting edit position + m_waitstring.nCursorPos = strlen(m_waitstring.szText); + } + return 0; // we processed (or absorbed) the key + } + break; + + case VK_RETURN: + + if (m_UI_mode == UI_LOAD) + { + if (m_pPresetAddr[m_nPresetListCurPos][0] == '*') + { + // CHANGE DIRECTORY + char *p = GetPresetDir(); + + if (strcmp(m_pPresetAddr[m_nPresetListCurPos], "*..") == 0) + { + // back up one dir + char *p2 = strrchr(p, '\\'); + if (p2) + { + *p2 = 0; + p2 = strrchr(p, '\\'); + if (p2) *(p2+1) = 0; + } + } + else + { + // open subdir + strcat(p, &m_pPresetAddr[m_nPresetListCurPos][1]); + strcat(p, "\\"); + } + + WritePrivateProfileString("settings","szPresetDir",GetPresetDir(),GetConfigIniFile()); + + UpdatePresetList(); + + // set current preset index to -1 because current preset is no longer in the list + m_nCurrentPreset = -1; + } + else + { + // LOAD NEW PRESET + m_nCurrentPreset = m_nPresetListCurPos; + + // first take the filename and prepend the path. (already has extension) + char s[MAX_PATH]; + strcpy(s, GetPresetDir()); // note: m_szPresetDir always ends with '\' + strcat(s, m_pPresetAddr[m_nCurrentPreset]); + + // now load (and blend to) the new preset + LoadPreset(s, m_fBlendTimeUser); + } + return 0; // we processed (or absorbed) the key + } + break; + + case VK_BACK: + // pass on to parent + //PostMessage(m_hWndParent,message,wParam,lParam); + m_nNumericInputDigits = 0; + m_nNumericInputNum = 0; + return 0; + + case 'T': + if (bCtrlHeldDown) + { + // stop display of custom message or song title. + m_supertext.fStartTime = -1.0f; + return 0; + } + break; + case 'K': + if (bCtrlHeldDown) // kill all sprites + { + for (int x=0; x= 'A' && wParam <= 'Z') || (wParam >= 'a' && wParam <= 'z'))) + { + SeekToPreset((char)wParam); + return 0; // we processed (or absorbed) the key + } + else switch(wParam) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + int digit = wParam - '0'; + m_nNumericInputNum = (m_nNumericInputNum*10) + digit; + m_nNumericInputDigits++; + + if (m_nNumericInputDigits >= 2) + { + if (m_nNumericInputMode == NUMERIC_INPUT_MODE_CUST_MSG) + LaunchCustomMessage(m_nNumericInputNum); + else if (m_nNumericInputMode == NUMERIC_INPUT_MODE_SPRITE) + LaunchSprite(m_nNumericInputNum, -1); + else if (m_nNumericInputMode == NUMERIC_INPUT_MODE_SPRITE_KILL) + { + for (int x=0; xm_fVideoEchoZoom /= 1.05f; + return 0; // we processed (or absorbed) the key + case 'Q': + m_pState->m_fVideoEchoZoom *= 1.05f; + return 0; // we processed (or absorbed) the key + case 'w': + m_pState->m_nWaveMode++; + if (m_pState->m_nWaveMode >= NUM_WAVES) m_pState->m_nWaveMode = 0; + return 0; // we processed (or absorbed) the key + case 'W': + m_pState->m_nWaveMode--; + if (m_pState->m_nWaveMode < 0) m_pState->m_nWaveMode = NUM_WAVES - 1; + return 0; // we processed (or absorbed) the key + case 'e': + m_pState->m_fWaveAlpha -= 0.1f; + if (m_pState->m_fWaveAlpha.eval(-1) < 0.0f) m_pState->m_fWaveAlpha = 0.0f; + return 0; // we processed (or absorbed) the key + case 'E': + m_pState->m_fWaveAlpha += 0.1f; + //if (m_pState->m_fWaveAlpha.eval(-1) > 1.0f) m_pState->m_fWaveAlpha = 1.0f; + return 0; // we processed (or absorbed) the key + + case 'I': m_pState->m_fZoom -= 0.01f; return 0; // we processed (or absorbed) the key + case 'i': m_pState->m_fZoom += 0.01f; return 0; // we processed (or absorbed) the key + + case 'n': + case 'N': + m_bShowDebugInfo = !m_bShowDebugInfo; + return 0; // we processed (or absorbed) the key + + case 'r': + case 'R': + m_bHoldPreset = 0; + m_bSequentialPresetOrder = !m_bSequentialPresetOrder; + sprintf(m_szUserMessage, "preset order is now %s", (m_bSequentialPresetOrder) ? "SEQUENTIAL" : "RANDOM"); + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + SendMessage(GetWinampWindow(),WM_WA_IPC,!m_bHoldPreset,IPC_CB_VISRANDOM); + return 0; // we processed (or absorbed) the key + + case 'x': + case 'X': + m_bHoldPreset = !m_bHoldPreset; + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + if (m_bHoldPreset) + strcpy(m_szUserMessage, "locking preset"); + else + strcpy(m_szUserMessage, "unlocking preset"); + SendMessage(GetWinampWindow(),WM_WA_IPC,!m_bHoldPreset,IPC_CB_VISRANDOM); + return 0; + + case 'u': + case 'U': + if (SendMessage(GetWinampWindow(),WM_USER,0,250)) + sprintf(m_szUserMessage, "shuffle is now OFF"); // shuffle was on + else + sprintf(m_szUserMessage, "shuffle is now ON"); // shuffle was off + + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + + // toggle shuffle + PostMessage(GetWinampWindow(),WM_COMMAND,40023,0); + + return 0; // we processed (or absorbed) the key + + + /* + case 'u': m_pState->m_fWarpScale /= 1.1f; break; + case 'U': m_pState->m_fWarpScale *= 1.1f; break; + case 'i': m_pState->m_fWarpAnimSpeed /= 1.1f; break; + case 'I': m_pState->m_fWarpAnimSpeed *= 1.1f; break; + */ + case 't': + case 'T': + LaunchSongTitleAnim(); + return 0; // we processed (or absorbed) the key + case 'o': m_pState->m_fWarpAmount /= 1.1f; return 0; // we processed (or absorbed) the key + case 'O': m_pState->m_fWarpAmount *= 1.1f; return 0; // we processed (or absorbed) the key + + // row 2 keys + case 'a': + m_pState->m_fVideoEchoAlpha -= 0.1f; + if (m_pState->m_fVideoEchoAlpha.eval(-1) < 0) m_pState->m_fVideoEchoAlpha = 0; + return 0; // we processed (or absorbed) the key + case 'A': + m_pState->m_fVideoEchoAlpha += 0.1f; + if (m_pState->m_fVideoEchoAlpha.eval(-1) > 1.0f) m_pState->m_fVideoEchoAlpha = 1.0f; + return 0; // we processed (or absorbed) the key + case 'd': + m_pState->m_fDecay += 0.01f; + if (m_pState->m_fDecay.eval(-1) > 1.0f) m_pState->m_fDecay = 1.0f; + return 0; // we processed (or absorbed) the key + case 'D': + m_pState->m_fDecay -= 0.01f; + if (m_pState->m_fDecay.eval(-1) < 0.9f) m_pState->m_fDecay = 0.9f; + return 0; // we processed (or absorbed) the key + case 'h': + case 'H': + // instant hard cut + LoadRandomPreset(0.0f); + m_fHardCutThresh *= 2.0f; + return 0; // we processed (or absorbed) the key + case 'f': + case 'F': + m_pState->m_nVideoEchoOrientation = (m_pState->m_nVideoEchoOrientation + 1) % 4; + return 0; // we processed (or absorbed) the key + case 'g': + m_pState->m_fGammaAdj -= 0.1f; + if (m_pState->m_fGammaAdj.eval(-1) < 0.0f) m_pState->m_fGammaAdj = 0.0f; + return 0; // we processed (or absorbed) the key + case 'G': + m_pState->m_fGammaAdj += 0.1f; + //if (m_pState->m_fGammaAdj > 1.0f) m_pState->m_fGammaAdj = 1.0f; + return 0; // we processed (or absorbed) the key + case 'j': + m_pState->m_fWaveScale *= 0.9f; + return 0; // we processed (or absorbed) the key + case 'J': + m_pState->m_fWaveScale /= 0.9f; + return 0; // we processed (or absorbed) the key + + case 'y': + case 'Y': + m_nNumericInputMode = NUMERIC_INPUT_MODE_CUST_MSG; + m_nNumericInputNum = 0; + m_nNumericInputDigits = 0; + return 0; // we processed (or absorbed) the key + case 'k': + case 'K': + { + SHORT mask = 1 << (sizeof(SHORT)*8 - 1); // we want the highest-order bit + bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0; + + if (bShiftHeldDown) + m_nNumericInputMode = NUMERIC_INPUT_MODE_SPRITE_KILL; + else + m_nNumericInputMode = NUMERIC_INPUT_MODE_SPRITE; + m_nNumericInputNum = 0; + m_nNumericInputDigits = 0; + } + return 0; // we processed (or absorbed) the key + + // row 3/misc. keys + + case '[': + m_pState->m_fXPush -= 0.005f; + return 0; // we processed (or absorbed) the key + case ']': + m_pState->m_fXPush += 0.005f; + return 0; // we processed (or absorbed) the key + case '{': + m_pState->m_fYPush -= 0.005f; + return 0; // we processed (or absorbed) the key + case '}': + m_pState->m_fYPush += 0.005f; + return 0; // we processed (or absorbed) the key + case '<': + m_pState->m_fRot += 0.02f; + return 0; // we processed (or absorbed) the key + case '>': + m_pState->m_fRot -= 0.02f; + return 0; // we processed (or absorbed) the key + + case 's': // SAVE PRESET + case 'S': + if (m_UI_mode == UI_REGULAR) + { + m_bPresetLockedByCode = true; + m_UI_mode = UI_SAVEAS; + + // enter WaitString mode + m_waitstring.bActive = true; + m_waitstring.bFilterBadChars = true; + m_waitstring.bDisplayAsCode = false; + m_waitstring.nSelAnchorPos = -1; + m_waitstring.nMaxLen = min(sizeof(m_waitstring.szText)-1, MAX_PATH - strlen(GetPresetDir()) - 6); // 6 for the extension + null char. We set this because win32 LoadFile, MoveFile, etc. barf if the path+filename+ext are > MAX_PATH chars. + strcpy(m_waitstring.szText, m_pState->m_szDesc); // initial string is the filename, minus the extension + strcpy(m_waitstring.szPrompt, "Save as:"); + m_waitstring.szToolTip[0] = 0; + m_waitstring.nCursorPos = strlen(m_waitstring.szText); // set the starting edit position + return 0; + } + break; + + case 'l': // LOAD PRESET + case 'L': + if (m_UI_mode == UI_LOAD) + { + m_UI_mode = UI_REGULAR; + return 0; // we processed (or absorbed) the key + + } + else if ( + m_UI_mode == UI_REGULAR || + m_UI_mode == UI_MENU) + { + m_UI_mode = UI_LOAD; + m_bUserPagedUp = false; + m_bUserPagedDown = false; + return 0; // we processed (or absorbed) the key + + } + break; + + case 'm': + case 'M': + + if (m_UI_mode == UI_MENU) + m_UI_mode = UI_REGULAR; + else if (m_UI_mode == UI_REGULAR || m_UI_mode == UI_LOAD) + m_UI_mode = UI_MENU; + + return 0; // we processed (or absorbed) the key + + case '-': + SetCurrentPresetRating(m_pState->m_fRating - 1.0f); + return 0; // we processed (or absorbed) the key + case '+': + SetCurrentPresetRating(m_pState->m_fRating + 1.0f); + return 0; // we processed (or absorbed) the key + + } +#endif + return 1; +} + +//---------------------------------------------------------------------- + +void CPlugin::RefreshTab2(HWND hwnd) +{ +/* + ShowWindow(GetDlgItem(hwnd, IDC_BRIGHT_SLIDER), !m_bAutoGamma); + ShowWindow(GetDlgItem(hwnd, IDC_T1), !m_bAutoGamma); + ShowWindow(GetDlgItem(hwnd, IDC_T2), !m_bAutoGamma); + ShowWindow(GetDlgItem(hwnd, IDC_T3), !m_bAutoGamma); + ShowWindow(GetDlgItem(hwnd, IDC_T4), !m_bAutoGamma); + ShowWindow(GetDlgItem(hwnd, IDC_T5), !m_bAutoGamma); + + EnableWindow(GetDlgItem(hwnd, IDC_CB_INSTASCAN), m_bEnableRating); +*/ +} +/* +int CALLBACK MyEnumFontsProc( + CONST LOGFONT *lplf, // logical-font data + CONST TEXTMETRIC *lptm, // physical-font data + DWORD dwType, // font type + LPARAM lpData // application-defined data +) +{ + SendMessage( GetDlgItem( (HWND)lpData, IDC_FONT3), CB_ADDSTRING, 0, (LPARAM)(lplf->lfFaceName)); + return 1; +} +*/ + +/* +void DoColors(HWND hwnd, int *r, int *g, int *b) +{ + static COLORREF acrCustClr[16]; + + CHOOSECOLOR cc; + ZeroMemory(&cc, sizeof(CHOOSECOLOR)); + cc.lStructSize = sizeof(CHOOSECOLOR); + cc.hwndOwner = hwnd;//NULL;//hSaverMainWindow; + cc.Flags = CC_RGBINIT | CC_FULLOPEN; + cc.rgbResult = RGB(*r,*g,*b); + cc.lpCustColors = (LPDWORD)acrCustClr; + if (ChooseColor(&cc)) + { + *r = GetRValue(cc.rgbResult); + *g = GetGValue(cc.rgbResult); + *b = GetBValue(cc.rgbResult); + } +} +*/ +//---------------------------------------------------------------------- + +BOOL CPlugin::MyConfigTabProc(int nPage, HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ +#if 0 + + // This is the only function you need to worry about for programming + // tabs 2 through 8 on the config panel. (Tab 1 contains settings + // that are common to all plugins, and the code is located in pluginshell.cpp). + // By default, only tab 2 is enabled; to enable tabes 3+, see + // 'Enabling Additional Tabs (pages) on the Config Panel' in DOCUMENTATION.TXT. + // You should always return 0 for this function. + // Note that you don't generally have to use critical sections or semaphores + // here; Winamp controls the plugin's message queue, and only gives it message + // in between frames. + // + // Incoming parameters: + // 'nPage' indicates which tab (aka 'property page') is currently showing: 2 through 5. + // 'hwnd' is the window handle of the property page (which is a dialog of its own, + // embedded in the config dialog). + // 'msg' is the windows message being sent. The main ones are: + // + // 1) WM_INITDIALOG: This means the page is being initialized, because the + // user clicked on it. When you get this message, you should initialize + // all the controls on the page, and set them to reflect the settings + // that are stored in member variables. + // + // 2) WM_DESTROY: This is sent when a tab disappears, either because another + // tab is about to be displayed, or because the user clicked OK or Cancel. + // In any case, you should read the current settings of all the controls + // on the page, and store them in member variables. (If the user clicked + // CANCEL, these values will not get saved to disk, but for simplicity, + // we always poll the controls here.) + // + // 3) WM_HELP: This is sent when the user clicks the '?' icon (in the + // titlebar of the config panel) and then clicks on a control. When you + // get this message, you should display a MessageBox telling the user + // a little bit about that control/setting. + // + // 4) WM_COMMAND: Advanced. This notifies you when the user clicks on a + // control. Use this if you need to do certain things when the user + // changes a setting. (For example, one control might only be enabled + // when a certain checkbox is enabled; you would use EnableWindow() for + // this.) + // + // For complete details on adding your own controls to one of the pages, please see + // 'Adding Controls to the Config Panel' in DOCUMENTATION.TXT. + + int t; + float val; + + if (nPage == 2) + { + switch(msg) + { + case WM_INITDIALOG: // initialize controls here + { + //-------------- texture size combo box --------------------- + char buf[2048]; + + for (int i=0; i<4; i++) + { + int size = (int)pow(2, i+8); + sprintf(buf, " %4d x %4d ", size, size); + int nPos = SendMessage( GetDlgItem( hwnd, IDC_TEXSIZECOMBO ), CB_ADDSTRING, 0, (LPARAM)buf); + SendMessage( GetDlgItem( hwnd, IDC_TEXSIZECOMBO ), CB_SETITEMDATA, nPos, size); + } + + // throw the "Auto" option in there + int nPos = SendMessage( GetDlgItem( hwnd, IDC_TEXSIZECOMBO ), CB_ADDSTRING, 0, (LPARAM)" Auto "); + SendMessage( GetDlgItem( hwnd, IDC_TEXSIZECOMBO ), CB_SETITEMDATA, nPos, -1); + + for (i=0; i<4+1; i++) + { + int size = SendMessage( GetDlgItem( hwnd, IDC_TEXSIZECOMBO ), CB_GETITEMDATA, i, 0); + if (size == m_nTexSize) + { + SendMessage( GetDlgItem( hwnd, IDC_TEXSIZECOMBO ), CB_SETCURSEL, i, 0); + } + } + + //-------------- mesh size combo box --------------------- + HWND meshcombo = GetDlgItem( hwnd, IDC_MESHSIZECOMBO ); + nPos = SendMessage(meshcombo , CB_ADDSTRING, 0, (LPARAM)" 8 x 6 FAST "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 8); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 16 x 12 fast "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 16); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 24 x 18 "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 24); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 32 x 24 (default)"); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 32); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 40 x 30 "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 40); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 48 x 36 slow "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 48); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 64 x 48 SLOW "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 64); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 80 x 60 SLOW "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 80); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)" 96 x 72 SLOW "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 96); + nPos = SendMessage( meshcombo, CB_ADDSTRING, 0, (LPARAM)"128 x 96 SLOW "); + SendMessage( meshcombo, CB_SETITEMDATA, nPos, 128); + // note: if you expand max. size, be sure to also raise MAX_GRID_X and MAX_GRID_Y + // in md_defines.h! + + int nCount = SendMessage( GetDlgItem( hwnd, IDC_MESHSIZECOMBO ), CB_GETCOUNT, 0, 0); + for (i=0; iiCtrlId), ctrl_name, sizeof(ctrl_name)-1); + RemoveSingleAmpersands(ctrl_name); + buf[0] = 0; + + strcpy(title, ctrl_name); + + switch(ph->iCtrlId) + { + case IDC_TEXSIZECOMBO: + case IDC_TEXSIZECOMBO_CAPTION: + strcpy(title, "Texture Size"); + strcpy(buf, + "This sets the size of the image that milkdrop uses, internally,\r" + "to drive the visuals. The bigger the value here, the crisper\r" + "the image you see. It's highly recommended that you set this\r" + "to 'auto', which will determine the ideal image (texture) size\r" + "automatically. However, if you experience visual problems (such\r" + "as black streaks or missing chunks in the image) due to low\r" + "video memory, you might want to set this to a low value (like\r" + "256x256 or 512x512)." + ); + break; + + case IDC_MESHSIZECOMBO: + case IDC_MESHSIZECOMBO_CAPTION: + strcpy(title, "Mesh Size"); + strcpy(buf, + "MilkDrop uses a mesh of polygons to warp the image each frame.\r" + "This setting determines how finely subdivided that mesh is.\r" + "A larger mesh size will mean finer resolution 'movement' in the\r" + "image; basically, it will look better. Watch out, though - \r" + "only crank this way up if you have a fast CPU." + ); + break; + + case IDC_CB_ALWAYS3D: + strcpy(buf, + "Enable this to force all presets to be displayed in 3D mode.\r" + "(Note that you need glasses with differently-colored lenses\r" + " to see the effect.)" + ); + break; + case IDC_CB_INSTASCAN: + strcpy(title, "Scan presets instantly"); + strcpy(buf, + "Check this to scan all preset ratings instantly, at startup or when\r" + "the directory changes. Normally, they are scanned in the background,\r" + "one per frame, until all of them are read in. If you'd like to read\r" + "them all in instantly, to alleviate those few seconds of disk grinding,\r" + "check this box; but be warned that it will create a short pause at\r" + "startup or when you change directories.\r" + "\r" + "NOTE: this only applies if the preset rating system is enabled." + ); + break; + case IDC_CB_NORATING: + strcpy(title, "Disable preset rating"); + strcpy(buf, + "Check this to turn off the preset rating system. This means that\r" + "at startup, or whenever you change the preset directory, there is\r" + "less likely to be a slowdown (usually a few seconds of disk activity)\r" + "while milkdrop scans all the presets to extract their ratings (if\r" + "instant scanning is off); or a short pause while it does this (if\r" + "instant scanning is on)." + ); + break; + case IDC_CB_NOWARN: + strcpy(buf, + "Check this to disable warning messageboxes at startup." + ); + break; + case IDC_CB_NOWARN2: + strcpy(buf, + "Check this to disable any & all warning messages that appear in the\r" + "upper-right corner of the screen." + ); + break; + case IDC_CB_ANISO: + strcpy(title, "Use anisotropic filtering"); + strcpy(buf, + "Check this to try to use an advanced form \r" + "of interpolation whenwarping the image each frame." + ); + break; + case IDC_CB_SCROLLON: + strcpy(title, "Start with preset lock ON"); + strcpy(buf, + "Check this to make MilkDrop automatically start in 'preset lock' mode,\r" + "meaning that the preset will not change until the user changes it\r" + "manually (either by pressing SPACE, hitting H for a hard cut, or by\r" + "selecting a new preset from the 'L'oad menu).\r" + "\r" + "Use the SCROLL LOCK key while MilkDrop is running to toggle the preset\r" + "lock on or off. When the SCROLL LOCK light is on, that means that the\r" + "preset lock is also on, and vice versa." + ); + break; + + case IDC_BRIGHT_SLIDER: + case IDC_BRIGHT_SLIDER_BOX: + case IDC_T1: + case IDC_T2: + case IDC_T3: + case IDC_T4: + case IDC_T5: + strcpy(buf, + "The brightness slider lets you control the overall brightness\r" + "of the image. If the image is continually washed out to bright\r" + "purple or white, you'll want to crank this down to (probably) zero.\r" + "If the image is chronically dark, crank this up.\r" + "\r" + "Note that the slider is not visible when the nearby 'guess'\r" + "checkbox is checked. Uncheck it to manually set the brightness.\r" + "\r" + "Also note that this brightness adjustment is only a concern in\r" + "16-bit color modes. (32-bit doesn't have this problem.) So,\r" + "if you're running Windows in 16-bit color, this slider will affect\r" + "windowed, desktop, and 'fake' fullscreen modes. And if you've\r" + "selected a 16-bit fullscreen display mode, it will affect that\r" + "too." + ); + break; + + case IDC_CB_AUTOGAMMA: + strcpy(buf, + "Check this option to ask milkdrop to make an educated guess\r" + "for the 'brightness control for 16-bit color' setting, based\r" + "on the vendor of your video card. This usually gets it, but\r" + "not always.\r" + "\r" + "The slider is only visible when this option is unchecked.\r" + "\r" + "See the help for the slider for more information." + ); + break; + + case ID_SPRITE: + strcpy(buf, + "Click this button to edit milk_img.ini, the file that defines\r" + "all of the custom sprites you can invoke for display while\r" + "milkdrop is running. A sprite is an image that you can fade\r" + "in or our, move around, and so on." + ); + break; + case ID_MSG: + strcpy(buf, + "Click this button to edit milk_msg.ini, the file that you can\r" + "configure to set up custom overlaid text messages that you can\r" + "display while milkdrop is running." + ); + break; + } + + if (buf[0]) + MessageBox(hwnd, buf, title, MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL); + } + break; // case WM_HELP + } + } + else if (nPage==3) + { + switch(msg) + { + case WM_INITDIALOG: + { + char buf[2048]; + + sprintf(buf, " %3.2f", m_fStereoSep); + SetWindowText( GetDlgItem( hwnd, IDC_3DSEP ), buf ); + + sprintf(buf, " %2.1f", m_fSongTitleAnimDuration); + SetWindowText( GetDlgItem( hwnd, IDC_SONGTITLEANIM_DURATION ), buf ); + sprintf(buf, " %2.1f", m_fTimeBetweenRandomSongTitles); + SetWindowText( GetDlgItem( hwnd, IDC_RAND_TITLE ), buf ); + sprintf(buf, " %2.1f", m_fTimeBetweenRandomCustomMsgs); + SetWindowText( GetDlgItem( hwnd, IDC_RAND_MSG ), buf ); + + CheckDlgButton(hwnd, IDC_CB_TITLE_ANIMS, m_bSongTitleAnims); + } + break; + case WM_COMMAND: + if (LOWORD(wParam)==IDLEFT) + DoColors(hwnd, &m_cLeftEye3DColor[0], &m_cLeftEye3DColor[1], &m_cLeftEye3DColor[2]); + if (LOWORD(wParam)==IDRIGHT) + DoColors(hwnd, &m_cRightEye3DColor[0], &m_cRightEye3DColor[1], &m_cRightEye3DColor[2]); + break; + case WM_DESTROY: + { + char buf[2048]; + + GetWindowText( GetDlgItem( hwnd, IDC_3DSEP ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fStereoSep = val; + + GetWindowText( GetDlgItem( hwnd, IDC_SONGTITLEANIM_DURATION ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fSongTitleAnimDuration = val; + GetWindowText( GetDlgItem( hwnd, IDC_RAND_TITLE ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fTimeBetweenRandomSongTitles = val; + GetWindowText( GetDlgItem( hwnd, IDC_RAND_MSG ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fTimeBetweenRandomCustomMsgs = val; + + m_bSongTitleAnims = DlgItemIsChecked(hwnd, IDC_CB_TITLE_ANIMS); + } + break; + case WM_HELP: // give help box for controls here + if (lParam) + { + HELPINFO *ph = (HELPINFO*)lParam; + char title[256], buf[2048], ctrl_name[256]; + GetWindowText(GetDlgItem(hwnd, ph->iCtrlId), ctrl_name, sizeof(ctrl_name)-1); + RemoveSingleAmpersands(ctrl_name); + buf[0] = 0; + + strcpy(title, ctrl_name); + + switch(ph->iCtrlId) + { + case IDLEFT: + sprintf(buf, + "Click this button to tell milkdrop the color of the %s-eye lens\r" + "of your colored 3D glasses. If the color selected here doesn't match\r" + "the color of the lens, you won't be able to perceive depth when\r" + "running presets in 3D.", "left" + ); + break; + + case IDRIGHT: + sprintf(buf, + "Click this button to tell milkdrop the color of the %s-eye lens\r" + "of your colored 3D glasses. If the color selected here doesn't match\r" + "the color of the lens, you won't be able to perceive depth when\r" + "running presets in 3D.", "right" + ); + break; + + case IDC_3DSEP: + case IDC_3DSEP_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_3DSEP_LABEL), title, sizeof(title)-1); + strcpy(buf, + "Change this value to adjust the degree of depth perceived when\r" + "running milkdrop presets in 3D mode. 1.0 is the default; higher\r" + "values will exaggerate the perception of depth , but go too far\r" + "and the illusion of depth will be shattered. Values between 0\r" + "and 1 will decrease the depth perception. The ideal value depends\r" + "on the distance between you and your display (be it a monitor or\r" + "a projector screen) and the size of the display.\r" + "\r" + "The value of 1.0 is normalized to work well for most desktop\r" + "displays; if you're projecting milkdrop onto a wall or screen\r" + "for a crowd, you should DEFINITELY experiment with this value.\r" + "\r" + "Note that you can also change this value while milkdrop is running;\r" + "hit F1 (at runtime) for help on which keys will accomplish this." + ); + break; + + case IDC_SONGTITLEANIM_DURATION: + case IDC_SONGTITLEANIM_DURATION_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_SONGTITLEANIM_DURATION_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The duration, in seconds, of song title animations." + ); + break; + + case IDC_RAND_TITLE: + case IDC_RAND_TITLE_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_RAND_TITLE_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The mean (average) time, in seconds, between randomly-launched\r" + "song title animations. Set to a negative value to disable random\r" + "launching." + ); + break; + + case IDC_RAND_MSG: + case IDC_RAND_MSG_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_RAND_MSG_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The mean (average) time, in seconds, between randomly-launched\r" + "custom messages (from milk_msg.ini). Set to a negative value\r" + "to disable random launching." + ); + break; + + case IDC_CB_TITLE_ANIMS: + strcpy(buf, + "Check this to automatically launch song title animations whenever\r" + "the track changes." + ); + break; + } + + if (buf[0]) + MessageBox(hwnd, buf, title, MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL); + } + break; // case WM_HELP + } + } + else if (nPage==4) + { + switch(msg) + { + case WM_INITDIALOG: + { + char buf[2048]; + + // soft cuts + sprintf(buf, " %2.1f", m_fTimeBetweenPresets); + SetWindowText( GetDlgItem( hwnd, IDC_BETWEEN_TIME ), buf ); + sprintf(buf, " %2.1f", m_fTimeBetweenPresetsRand); + SetWindowText( GetDlgItem( hwnd, IDC_BETWEEN_TIME_RANDOM ), buf ); + sprintf(buf, " %2.1f", m_fBlendTimeUser); + SetWindowText( GetDlgItem( hwnd, IDC_BLEND_USER ), buf ); + sprintf(buf, " %2.1f", m_fBlendTimeAuto); + SetWindowText( GetDlgItem( hwnd, IDC_BLEND_AUTO ), buf ); + + // hard cuts + sprintf(buf, " %2.1f", m_fHardCutHalflife); + SetWindowText( GetDlgItem( hwnd, IDC_HARDCUT_BETWEEN_TIME ), buf ); + + int n = (int)((m_fHardCutLoudnessThresh - 1.25f) * 10.0f); + if (n<0) n = 0; + if (n>20) n = 20; + SendMessage( GetDlgItem( hwnd, IDC_HARDCUT_LOUDNESS), TBM_SETRANGEMIN, FALSE, (LPARAM)(0) ); + SendMessage( GetDlgItem( hwnd, IDC_HARDCUT_LOUDNESS), TBM_SETRANGEMAX, FALSE, (LPARAM)(20) ); + SendMessage( GetDlgItem( hwnd, IDC_HARDCUT_LOUDNESS), TBM_SETPOS, TRUE, (LPARAM)(n) ); + + CheckDlgButton(hwnd, IDC_CB_HARDCUTS, m_bHardCutsDisabled); + } + break; + case WM_DESTROY: + { + char buf[2048]; + + // soft cuts + GetWindowText( GetDlgItem( hwnd, IDC_BETWEEN_TIME ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fTimeBetweenPresets = val; + GetWindowText( GetDlgItem( hwnd, IDC_BETWEEN_TIME_RANDOM ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fTimeBetweenPresetsRand = val; + GetWindowText( GetDlgItem( hwnd, IDC_BLEND_AUTO ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fBlendTimeAuto = val; + GetWindowText( GetDlgItem( hwnd, IDC_BLEND_USER ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fBlendTimeUser = val; + + // hard cuts + GetWindowText( GetDlgItem( hwnd, IDC_HARDCUT_BETWEEN_TIME ), buf, sizeof(buf)); + if (sscanf(buf, "%f", &val) == 1) + m_fHardCutHalflife = val; + + t = SendMessage( GetDlgItem( hwnd, IDC_HARDCUT_LOUDNESS ), TBM_GETPOS, 0, 0); + if (t != CB_ERR) m_fHardCutLoudnessThresh = 1.25f + t/10.0f; + + m_bHardCutsDisabled = DlgItemIsChecked(hwnd, IDC_CB_HARDCUTS); + } + break; + case WM_HELP: + if (lParam) + { + HELPINFO *ph = (HELPINFO*)lParam; + char title[256], buf[2048], ctrl_name[256]; + GetWindowText(GetDlgItem(hwnd, ph->iCtrlId), ctrl_name, sizeof(ctrl_name)-1); + RemoveSingleAmpersands(ctrl_name); + buf[0] = 0; + + strcpy(title, ctrl_name); + + switch(ph->iCtrlId) + { + case IDC_BETWEEN_TIME: + case IDC_BETWEEN_TIME_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_BETWEEN_TIME_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The minimum amount of time that elapses between preset changes\r" + "(excluding hard cuts, which take priority). The old preset will\r" + "begin to blend or fade into a new preset after this amount of time,\r" + "plus some random amount of time as specified below in the\r" + "'additional random time' box. Add these two values together to\r" + "get the maximum amount of time that will elapse between preset\r" + "changes." + ); + break; + + case IDC_BETWEEN_TIME_RANDOM: + case IDC_BETWEEN_TIME_RANDOM_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_BETWEEN_TIME_RANDOM_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The additional random maximum # of seconds between preset fades\r" + "(aka preset changes) (aka soft cuts)." + ); + break; + + case IDC_BLEND_AUTO: + case IDC_BLEND_AUTO_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_BLEND_AUTO_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The duration, in seconds, of a soft cut (a normal fade from one preset\r" + "to another) that is initiated because some amount of time has passed.\r" + "A value less than 1 will make for a very quick transition, while a value\r" + "around 3 or 4 will allow you to see some interesting behavior during\r" + "the blend." + ); + break; + + case IDC_BLEND_USER: + case IDC_BLEND_USER_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_BLEND_USER_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The duration, in seconds, of a soft cut (a normal fade from one preset\r" + "to another) that is initiated by you, when you press the 'H' key (for\r" + "a Hard cut). A value less than 1 will make for a very quick transition,\r" + "while a value around 3 or 4 will allow you to see some interesting behavior\r" + "during the blend." + ); + break; + + case IDC_HARDCUT_BETWEEN_TIME: + case IDC_HARDCUT_BETWEEN_TIME_LABEL: + GetWindowText(GetDlgItem(hwnd, IDC_HARDCUT_BETWEEN_TIME_LABEL), title, sizeof(title)-1); + strcpy(buf, + "The amount of time, in seconds, between hard cuts. Hard cuts are\r" + "set off by loud beats in the music, with (ideally) about this much\r" + "time in between them." + ); + break; + + case IDC_HARDCUT_LOUDNESS: + case IDC_HARDCUT_LOUDNESS_LABEL: + case IDC_HARDCUT_LOUDNESS_MIN: + case IDC_HARDCUT_LOUDNESS_MAX: + GetWindowText(GetDlgItem(hwnd, IDC_HARDCUT_LOUDNESS_LABEL), title, sizeof(title)-1); + strcpy(buf, + "Use this slider to adjust the sensitivity of the beat detection\r" + "algorithm used to detect the beats that cause hard cuts. A value\r" + "close to 'min' will cause the algorithm to be very sensitive (so\r" + "even small beats will trigger it); a value close to 'max' will\r" + "cause only the largest beats to trigger it." + ); + break; + + case IDC_CB_HARDCUTS: + strcpy(buf, + "Check this to disable hard cuts; a loud beat\r" + "will never cause the preset to change." + ); + break; + + } + + if (buf[0]) + MessageBox(hwnd, buf, title, MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL); + } + break; + } + } +#endif 0 + + return false; +} + +//---------------------------------------------------------------------- + +void CPlugin::Randomize() +{ + srand((int)(GetTime()*100)); + //m_fAnimTime = (rand() % 51234L)*0.01f; + m_fRandStart[0] = (rand() % 64841L)*0.01f; + m_fRandStart[1] = (rand() % 53751L)*0.01f; + m_fRandStart[2] = (rand() % 42661L)*0.01f; + m_fRandStart[3] = (rand() % 31571L)*0.01f; + + //CState temp; + //temp.Randomize(rand() % NUM_MODES); + //m_pState->StartBlend(&temp, m_fAnimTime, m_fBlendTimeUser); +} + +//---------------------------------------------------------------------- + +void CPlugin::BuildMenus() +{ +#if 0 + char buf[1024]; + + m_pCurMenu = &m_menuPreset;//&m_menuMain; + + m_menuPreset .Init("--edit current preset"); + m_menuMotion .Init("--MOTION"); + m_menuCustomShape.Init("--drawing: custom shapes"); + m_menuCustomWave .Init("--drawing: custom waves"); + m_menuWave .Init("--drawing: simple waveform"); + m_menuAugment .Init("--drawing: borders, motion vectors"); + m_menuPost .Init("--post-processing, misc."); + for (int i=0; im_szPerFrameInit, MENUITEMTYPE_STRING, + "read-only: zoom, rot, warp, cx, cy, dx, dy, sx, sy; decay, gamma;\r" + " echo_zoom, echo_scale, echo_orient;\r" + " ib_{size|r|g|b|a}, ob_{size|r|g|b|a}, mv_{x|y|dx|dy|l|r|g|b|a};\r" + " wave_{r|g|b|a|x|y|mode|mystery|usedots|thick|additive|brighten};\r" + " darken_center, wrap; invert, brighten, darken, solarize\r" + " time, fps, frame, progress; {bass|mid|treb}[_att]\r" + "write: q1-q8, monitor" + , 256, 0, &OnUserEditedPresetInit); + m_menuPreset.AddItem("[ edit per_frame equations ]", &m_pState->m_szPerFrameExpr, MENUITEMTYPE_STRING, + "read-only: time, fps, frame, progress; {bass|mid|treb}[_att]\r" + "read/write: zoom, rot, warp, cx, cy, dx, dy, sx, sy; q1-q8; monitor\r" + " mv_{x|y|dx|dy|l|r|g|b|a}, ib_{size|r|g|b|a}, ob_{size|r|g|b|a};\r" + " wave_{r|g|b|a|x|y|mode|mystery|usedots|thick|additive|brighten};\r" + " darken_center, wrap; invert, brighten, darken, solarize\r" + " decay, gamma, echo_zoom, echo_alpha, echo_orient" + , 256, 0, &OnUserEditedPerFrame); + m_menuPreset.AddItem("[ edit per_pixel equations ]", &m_pState->m_szPerPixelExpr, MENUITEMTYPE_STRING, + "read-only: x, y, rad, ang; time, fps, frame, progress; {bass|mid|treb}[_att]\r" + "read/write: dx, dy, zoom, rot, warp, cx, cy, sx, sy, q1-q8" + , 256, 0, &OnUserEditedPerPixel); + + + //------------------------------------------- + + // menu items + m_menuWave.AddItem("wave type", &m_pState->m_nWaveMode, MENUITEMTYPE_INT, "each value represents a different way of drawing the waveform", 0, NUM_WAVES-1); + m_menuWave.AddItem("size", &m_pState->m_fWaveScale, MENUITEMTYPE_LOGBLENDABLE, "relative size of the waveform"); + m_menuWave.AddItem("smoothing", &m_pState->m_fWaveSmoothing,MENUITEMTYPE_BLENDABLE, "controls the smoothness of the waveform; 0=natural sound data (no smoothing), 0.9=max. smoothing", 0.0f, 0.9f); + m_menuWave.AddItem("mystery parameter", &m_pState->m_fWaveParam, MENUITEMTYPE_BLENDABLE, "what this one does is a secret (actually, its effect depends on the 'wave type'", -1.0f, 1.0f); + m_menuWave.AddItem("position (X)", &m_pState->m_fWaveX, MENUITEMTYPE_BLENDABLE, "position of the waveform: 0 = far left edge of screen, 0.5 = center, 1 = far right", 0, 1); + m_menuWave.AddItem("position (Y)", &m_pState->m_fWaveY, MENUITEMTYPE_BLENDABLE, "position of the waveform: 0 = very bottom of screen, 0.5 = center, 1 = top", 0, 1); + m_menuWave.AddItem("color (red)", &m_pState->m_fWaveR, MENUITEMTYPE_BLENDABLE, "amount of red color in the wave (0..1)", 0, 1); + m_menuWave.AddItem("color (green)", &m_pState->m_fWaveG, MENUITEMTYPE_BLENDABLE, "amount of green color in the wave (0..1)", 0, 1); + m_menuWave.AddItem("color (blue)", &m_pState->m_fWaveB, MENUITEMTYPE_BLENDABLE, "amount of blue color in the wave (0..1)", 0, 1); + m_menuWave.AddItem("opacity", &m_pState->m_fWaveAlpha, MENUITEMTYPE_LOGBLENDABLE, "opacity of the waveform; lower numbers = more transparent", 0.001f, 100.0f); + m_menuWave.AddItem("use dots", &m_pState->m_bWaveDots, MENUITEMTYPE_BOOL, "if true, the waveform is drawn as dots (instead of lines)"); + m_menuWave.AddItem("draw thick", &m_pState->m_bWaveThick, MENUITEMTYPE_BOOL, "if true, the waveform's lines (or dots) are drawn with double thickness"); + m_menuWave.AddItem("modulate opacity by volume", &m_pState->m_bModWaveAlphaByVolume, MENUITEMTYPE_BOOL, "if true, the waveform opacity is affected by the music's volume"); + m_menuWave.AddItem("modulation: transparent volume", &m_pState->m_fModWaveAlphaStart, MENUITEMTYPE_BLENDABLE, "when the relative volume hits this level, the wave becomes transparent. 1 = normal loudness, 0.5 = extremely quiet, 1.5 = extremely loud", 0.0f, 2.0f); + m_menuWave.AddItem("modulation: opaque volume", &m_pState->m_fModWaveAlphaEnd, MENUITEMTYPE_BLENDABLE, "when the relative volume hits this level, the wave becomes opaque. 1 = normal loudness, 0.5 = extremely quiet, 1.5 = extremely loud", 0.0f, 2.0f); + m_menuWave.AddItem("additive drawing", &m_pState->m_bAdditiveWaves, MENUITEMTYPE_BOOL, "if true, the wave is drawn additively, saturating the image at white"); + m_menuWave.AddItem("color brightening", &m_pState->m_bMaximizeWaveColor, MENUITEMTYPE_BOOL, "if true, the red, green, and blue color components will be scaled up until at least one of them reaches 1.0"); + + m_menuAugment.AddItem("outer border thickness" ,&m_pState->m_fOuterBorderSize, MENUITEMTYPE_BLENDABLE, "thickness of the outer border drawn at the edges of the screen", 0, 0.5f); + m_menuAugment.AddItem(" color (red)" ,&m_pState->m_fOuterBorderR , MENUITEMTYPE_BLENDABLE, "amount of red color in the outer border", 0, 1); + m_menuAugment.AddItem(" color (green)" ,&m_pState->m_fOuterBorderG , MENUITEMTYPE_BLENDABLE, "amount of green color in the outer border", 0, 1); + m_menuAugment.AddItem(" color (blue)" ,&m_pState->m_fOuterBorderB , MENUITEMTYPE_BLENDABLE, "amount of blue color in the outer border", 0, 1); + m_menuAugment.AddItem(" opacity" ,&m_pState->m_fOuterBorderA , MENUITEMTYPE_BLENDABLE, "opacity of the outer border (0=transparent, 1=opaque)", 0, 1); + m_menuAugment.AddItem("inner border thickness" ,&m_pState->m_fInnerBorderSize, MENUITEMTYPE_BLENDABLE, "thickness of the inner border drawn at the edges of the screen", 0, 0.5f); + m_menuAugment.AddItem(" color (red)" ,&m_pState->m_fInnerBorderR , MENUITEMTYPE_BLENDABLE, "amount of red color in the inner border", 0, 1); + m_menuAugment.AddItem(" color (green)" ,&m_pState->m_fInnerBorderG , MENUITEMTYPE_BLENDABLE, "amount of green color in the inner border", 0, 1); + m_menuAugment.AddItem(" color (blue)" ,&m_pState->m_fInnerBorderB , MENUITEMTYPE_BLENDABLE, "amount of blue color in the inner border", 0, 1); + m_menuAugment.AddItem(" opacity" ,&m_pState->m_fInnerBorderA , MENUITEMTYPE_BLENDABLE, "opacity of the inner border (0=transparent, 1=opaque)", 0, 1); + m_menuAugment.AddItem("motion vector opacity" ,&m_pState->m_fMvA , MENUITEMTYPE_BLENDABLE, "opacity of the motion vectors (0=transparent, 1=opaque)", 0, 1); + m_menuAugment.AddItem(" num. mot. vectors (X)" ,&m_pState->m_fMvX , MENUITEMTYPE_BLENDABLE, "the number of motion vectors on the x-axis", 0, 64); + m_menuAugment.AddItem(" num. mot. vectors (Y)" ,&m_pState->m_fMvY , MENUITEMTYPE_BLENDABLE, "the number of motion vectors on the y-axis", 0, 48); + m_menuAugment.AddItem(" offset (X)" ,&m_pState->m_fMvDX , MENUITEMTYPE_BLENDABLE, "horizontal placement offset of the motion vectors", -1, 1); + m_menuAugment.AddItem(" offset (Y)" ,&m_pState->m_fMvDY , MENUITEMTYPE_BLENDABLE, "vertical placement offset of the motion vectors", -1, 1); + m_menuAugment.AddItem(" trail length" ,&m_pState->m_fMvL , MENUITEMTYPE_BLENDABLE, "the length of the motion vectors (1=normal)", 0, 5); + m_menuAugment.AddItem(" color (red)" ,&m_pState->m_fMvR , MENUITEMTYPE_BLENDABLE, "amount of red color in the motion vectors", 0, 1); + m_menuAugment.AddItem(" color (green)" ,&m_pState->m_fMvG , MENUITEMTYPE_BLENDABLE, "amount of green color in the motion vectors", 0, 1); + m_menuAugment.AddItem(" color (blue)" ,&m_pState->m_fMvB , MENUITEMTYPE_BLENDABLE, "amount of blue color in the motion vectors", 0, 1); + + m_menuMotion.AddItem("zoom amount", &m_pState->m_fZoom, MENUITEMTYPE_LOGBLENDABLE, "controls inward/outward motion. 0.9=zoom out, 1.0=no zoom, 1.1=zoom in"); + m_menuMotion.AddItem(" zoom exponent", &m_pState->m_fZoomExponent, MENUITEMTYPE_LOGBLENDABLE, "controls the curvature of the zoom; 1=normal"); + m_menuMotion.AddItem("warp amount", &m_pState->m_fWarpAmount, MENUITEMTYPE_LOGBLENDABLE, "controls the magnitude of the warping; 0=none, 1=normal, 2=major warping..."); + m_menuMotion.AddItem(" warp scale", &m_pState->m_fWarpScale, MENUITEMTYPE_LOGBLENDABLE, "controls the wavelength of the warp; 1=normal, less=turbulent, more=smoother"); + m_menuMotion.AddItem(" warp speed", &m_pState->m_fWarpAnimSpeed,MENUITEMTYPE_LOGFLOAT, "controls the speed of the warp; 1=normal, less=slower, more=faster"); + m_menuMotion.AddItem("rotation amount", &m_pState->m_fRot, MENUITEMTYPE_BLENDABLE, "controls the amount of rotation. 0=none, 0.1=slightly right, -0.1=slightly clockwise, 0.1=CCW", -1.00f, 1.00f); + m_menuMotion.AddItem(" rot., center of (X)",&m_pState->m_fRotCX, MENUITEMTYPE_BLENDABLE, "controls where the center of rotation is, horizontally. 0=left, 0.5=center, 1=right", -1.0f, 2.0f); + m_menuMotion.AddItem(" rot., center of (Y)",&m_pState->m_fRotCY, MENUITEMTYPE_BLENDABLE, "controls where the center of rotation is, vertically. 0=top, 0.5=center, 1=bottom", -1.0f, 2.0f); + m_menuMotion.AddItem("translation (X)", &m_pState->m_fXPush, MENUITEMTYPE_BLENDABLE, "controls amount of constant horizontal motion; -0.01 = slight shift right, 0=none, 0.01 = to left", -1.0f, 1.0f); + m_menuMotion.AddItem("translation (Y)", &m_pState->m_fYPush, MENUITEMTYPE_BLENDABLE, "controls amount of constant vertical motion; -0.01 = slight shift downward, 0=none, 0.01 = upward", -1.0f, 1.0f); + m_menuMotion.AddItem("scaling (X)", &m_pState->m_fStretchX, MENUITEMTYPE_LOGBLENDABLE, "controls amount of constant horizontal stretching; 0.99=shrink, 1=normal, 1.01=stretch"); + m_menuMotion.AddItem("scaling (Y)", &m_pState->m_fStretchY, MENUITEMTYPE_LOGBLENDABLE, "controls amount of constant vertical stretching; 0.99=shrink, 1=normal, 1.01=stretch"); + + m_menuPost.AddItem("sustain level", &m_pState->m_fDecay, MENUITEMTYPE_BLENDABLE, "controls the eventual fade to black; 1=no fade, 0.9=strong fade; 0.98=recommended.", 0.50f, 1.0f); + m_menuPost.AddItem("darken center", &m_pState->m_bDarkenCenter, MENUITEMTYPE_BOOL, "when ON, help keeps the image from getting too bright by continually dimming the center point"); + m_menuPost.AddItem("gamma adjustment", &m_pState->m_fGammaAdj, MENUITEMTYPE_BLENDABLE, "controls brightness; 1=normal, 2=double, 3=triple, etc.", 1.0f, 8.0f); + m_menuPost.AddItem("hue shader", &m_pState->m_fShader, MENUITEMTYPE_BLENDABLE, "adds subtle color variations to the image. 0=off, 1=fully on", 0.0f, 1.0f); + m_menuPost.AddItem("video echo: alpha", &m_pState->m_fVideoEchoAlpha, MENUITEMTYPE_BLENDABLE, "controls the opacity of the second graphics layer; 0=transparent (off), 0.5=half-mix, 1=opaque", 0.0f, 1.0f); + m_menuPost.AddItem(" video echo: zoom", &m_pState->m_fVideoEchoZoom, MENUITEMTYPE_LOGBLENDABLE, "controls the size of the second graphics layer"); + m_menuPost.AddItem(" video echo: orientation",&m_pState->m_nVideoEchoOrientation, MENUITEMTYPE_INT, "selects an orientation for the second graphics layer. 0=normal, 1=flip on x, 2=flip on y, 3=flip on both", 0.0f, 3.0f); + m_menuPost.AddItem("texture wrap", &m_pState->m_bTexWrap, MENUITEMTYPE_BOOL, "sets whether or not screen elements can drift off of one side and onto the other"); + m_menuPost.AddItem("stereo 3D", &m_pState->m_bRedBlueStereo, MENUITEMTYPE_BOOL, "displays the image in stereo 3D; you need 3D glasses (with red and blue lenses) for this."); + m_menuPost.AddItem("filter: invert", &m_pState->m_bInvert, MENUITEMTYPE_BOOL, "inverts the colors in the image"); + m_menuPost.AddItem("filter: brighten", &m_pState->m_bBrighten, MENUITEMTYPE_BOOL, "brightens the darker parts of the image (nonlinear; square root filter)"); + m_menuPost.AddItem("filter: darken", &m_pState->m_bDarken, MENUITEMTYPE_BOOL, "darkens the brighter parts of the image (nonlinear; squaring filter)"); + m_menuPost.AddItem("filter: solarize", &m_pState->m_bSolarize, MENUITEMTYPE_BOOL, "emphasizes mid-range colors"); + + for (i=0; im_wave[i].enabled, MENUITEMTYPE_BOOL, "enables or disables this custom waveform/spectrum"); // bool + m_menuWavecode[i].AddItem("number of samples" ,&m_pState->m_wave[i].samples, MENUITEMTYPE_INT, "the number of samples (points) that makes up the waveform", 2, 512); // 0-512 + m_menuWavecode[i].AddItem("L/R separation" ,&m_pState->m_wave[i].sep, MENUITEMTYPE_INT, "the offset between the left & right channels; useful for doing phase plots. Keep low (<32) when using w/spectrum.", 0, 256); // 0-512 + m_menuWavecode[i].AddItem("scaling" ,&m_pState->m_wave[i].scaling, MENUITEMTYPE_LOGFLOAT, "the size of the wave (1=normal)"); + m_menuWavecode[i].AddItem("smoothing" ,&m_pState->m_wave[i].smoothing, MENUITEMTYPE_FLOAT, "0=the raw wave; 1=a highly damped (smoothed) wave", 0, 1); + m_menuWavecode[i].AddItem("color (red)" ,&m_pState->m_wave[i].r, MENUITEMTYPE_FLOAT, "amount of red color in the wave (0..1)", 0, 1); + m_menuWavecode[i].AddItem("color (green)" ,&m_pState->m_wave[i].g, MENUITEMTYPE_FLOAT, "amount of green color in the wave (0..1)", 0, 1); + m_menuWavecode[i].AddItem("color (blue)" ,&m_pState->m_wave[i].b, MENUITEMTYPE_FLOAT, "amount of blue color in the wave (0..1)", 0, 1); + m_menuWavecode[i].AddItem("opacity" ,&m_pState->m_wave[i].a, MENUITEMTYPE_FLOAT, "opacity of the waveform; 0=transparent, 1=opaque", 0, 1); + m_menuWavecode[i].AddItem("use spectrum" ,&m_pState->m_wave[i].bSpectrum, MENUITEMTYPE_BOOL, "if ON, the data in value1 and value2 will constitute a frequency spectrum (instead of waveform values)"); // 0-5 [0=wave left, 1=wave center, 2=wave right; 3=spectrum left, 4=spec center, 5=spec right] + m_menuWavecode[i].AddItem("use dots" ,&m_pState->m_wave[i].bUseDots, MENUITEMTYPE_BOOL, "if ON, the samples will be drawn with dots, instead of connected lines"); // bool + m_menuWavecode[i].AddItem("draw thick" ,&m_pState->m_wave[i].bDrawThick, MENUITEMTYPE_BOOL, "if ON, the samples will be overdrawn 4X to make them thicker, bolder, and more visible"); // bool + m_menuWavecode[i].AddItem("additive drawing" ,&m_pState->m_wave[i].bAdditive, MENUITEMTYPE_BOOL, "if ON, the samples will add color to sature the image toward white; otherwise, they replace what's there."); // bool + m_menuWavecode[i].AddItem("--export to file" ,(void*)UI_EXPORT_WAVE, MENUITEMTYPE_UIMODE, "export the settings for this custom waveform to a file on disk", 0, 0, NULL, UI_EXPORT_WAVE, i); + m_menuWavecode[i].AddItem("--import from file" ,(void*)UI_IMPORT_WAVE, MENUITEMTYPE_UIMODE, "import settings for a custom waveform from a file on disk" , 0, 0, NULL, UI_IMPORT_WAVE, i); + m_menuWavecode[i].AddItem("[ edit initialization code ]",&m_pState->m_wave[i].m_szInit, MENUITEMTYPE_STRING, "IN: time, frame, fps, progress; q1-q8 (from preset init) / OUT: t1-t8", 256, 0, &OnUserEditedWavecodeInit); + m_menuWavecode[i].AddItem("[ edit per-frame code ]",&m_pState->m_wave[i].m_szPerFrame, MENUITEMTYPE_STRING, "IN: time, frame, fps, progress; q1-q8, t1-t8; r,g,b,a; {bass|mid|treb}[_att] / OUT: r,g,b,a; t1-t8", 256, 0, &OnUserEditedWavecode); + m_menuWavecode[i].AddItem("[ edit per-point code ]",&m_pState->m_wave[i].m_szPerPoint, MENUITEMTYPE_STRING, "IN: sample [0..1]; value1 [left ch], value2 [right ch], plus all vars for per-frame code / OUT: x,y; r,g,b,a; t1-t8", 256, 0, &OnUserEditedWavecode); + } + + for (i=0; im_shape[i].enabled, MENUITEMTYPE_BOOL, "enables or disables this shape"); // bool + m_menuShapecode[i].AddItem("number of sides" ,&m_pState->m_shape[i].sides, MENUITEMTYPE_INT, "the default number of sides that make up the polygonal shape", 3, 100); + m_menuShapecode[i].AddItem("draw thick" ,&m_pState->m_shape[i].thickOutline,MENUITEMTYPE_BOOL, "if ON, the border will be overdrawn 4X to make it thicker, bolder, and more visible"); // bool + m_menuShapecode[i].AddItem("additive drawing" ,&m_pState->m_shape[i].additive, MENUITEMTYPE_BOOL, "if ON, the shape will add color to sature the image toward white; otherwise, it will replace what's there."); // bool + m_menuShapecode[i].AddItem("x position" ,&m_pState->m_shape[i].x, MENUITEMTYPE_FLOAT, "default x position of the shape (0..1; 0=left side, 1=right side)", 0, 1); + m_menuShapecode[i].AddItem("y position" ,&m_pState->m_shape[i].y, MENUITEMTYPE_FLOAT, "default y position of the shape (0..1; 0=bottom, 1=top of screen)", 0, 1); + m_menuShapecode[i].AddItem("radius" ,&m_pState->m_shape[i].rad, MENUITEMTYPE_LOGFLOAT, "default radius of the shape (0+)"); + m_menuShapecode[i].AddItem("angle" ,&m_pState->m_shape[i].ang, MENUITEMTYPE_FLOAT, "default rotation angle of the shape (0...3.14*2)", 0, 3.1415927f*2.0f); + m_menuShapecode[i].AddItem("textured" ,&m_pState->m_shape[i].textured, MENUITEMTYPE_BOOL, "if ON, the shape will be textured with the image from the previous frame"); // bool + m_menuShapecode[i].AddItem("texture zoom" ,&m_pState->m_shape[i].tex_zoom, MENUITEMTYPE_LOGFLOAT, "the portion of the previous frame's image to use with the shape"); // bool + m_menuShapecode[i].AddItem("texture angle" ,&m_pState->m_shape[i].tex_ang, MENUITEMTYPE_FLOAT , "the angle at which to rotate the previous frame's image before applying it to the shape", 0, 3.1415927f*2.0f); // bool + m_menuShapecode[i].AddItem("inner color (red)" ,&m_pState->m_shape[i].r, MENUITEMTYPE_FLOAT, "default amount of red color toward the center of the shape (0..1)", 0, 1); + m_menuShapecode[i].AddItem("inner color (green)" ,&m_pState->m_shape[i].g, MENUITEMTYPE_FLOAT, "default amount of green color toward the center of the shape (0..1)", 0, 1); + m_menuShapecode[i].AddItem("inner color (blue)" ,&m_pState->m_shape[i].b, MENUITEMTYPE_FLOAT, "default amount of blue color toward the center of the shape (0..1)", 0, 1); + m_menuShapecode[i].AddItem("inner opacity" ,&m_pState->m_shape[i].a, MENUITEMTYPE_FLOAT, "default opacity of the center of the shape; 0=transparent, 1=opaque", 0, 1); + m_menuShapecode[i].AddItem("outer color (red)" ,&m_pState->m_shape[i].r2, MENUITEMTYPE_FLOAT, "default amount of red color toward the outer edge of the shape (0..1)", 0, 1); + m_menuShapecode[i].AddItem("outer color (green)" ,&m_pState->m_shape[i].g2, MENUITEMTYPE_FLOAT, "default amount of green color toward the outer edge of the shape (0..1)", 0, 1); + m_menuShapecode[i].AddItem("outer color (blue)" ,&m_pState->m_shape[i].b2, MENUITEMTYPE_FLOAT, "default amount of blue color toward the outer edge of the shape (0..1)", 0, 1); + m_menuShapecode[i].AddItem("outer opacity" ,&m_pState->m_shape[i].a2, MENUITEMTYPE_FLOAT, "default opacity of the outer edge of the shape; 0=transparent, 1=opaque", 0, 1); + m_menuShapecode[i].AddItem("border color (red)" ,&m_pState->m_shape[i].border_r, MENUITEMTYPE_FLOAT, "default amount of red color in the shape's border (0..1)", 0, 1); + m_menuShapecode[i].AddItem("border color (green)",&m_pState->m_shape[i].border_g, MENUITEMTYPE_FLOAT, "default amount of green color in the shape's border (0..1)", 0, 1); + m_menuShapecode[i].AddItem("border color (blue)" ,&m_pState->m_shape[i].border_b, MENUITEMTYPE_FLOAT, "default amount of blue color in the shape's border (0..1)", 0, 1); + m_menuShapecode[i].AddItem("border opacity" ,&m_pState->m_shape[i].border_a, MENUITEMTYPE_FLOAT, "default opacity of the shape's border; 0=transparent, 1=opaque", 0, 1); + m_menuShapecode[i].AddItem("--export to file" ,NULL, MENUITEMTYPE_UIMODE, "export the settings for this custom shape to a file on disk", 0, 0, NULL, UI_EXPORT_SHAPE, i); + m_menuShapecode[i].AddItem("--import from file" ,NULL, MENUITEMTYPE_UIMODE, "import settings for a custom shape from a file on disk" , 0, 0, NULL, UI_IMPORT_SHAPE, i); + m_menuShapecode[i].AddItem("[ edit initialization code ]",&m_pState->m_shape[i].m_szInit, MENUITEMTYPE_STRING, "IN: time, frame, fps, progress; q1-q8 (from preset init); x,y,rad,ang; r,g,b,a; r2,g2,b2,a2; border_{r|g|b|a}; sides, thick, additive, textured\rOUT: t1-t8; x,y,rad,ang; r,g,b,a; r2,g2,b2,a2; border_{r|g|b|a}; sides, thick, additive, textured", 256, 0, &OnUserEditedShapecodeInit); + m_menuShapecode[i].AddItem("[ edit per-frame code ]",&m_pState->m_shape[i].m_szPerFrame, MENUITEMTYPE_STRING, "IN: time, frame, fps, progress; q1-q8 (from preset init); x,y,rad,ang; r,g,b,a; r2,g2,b2,a2; border_{r|g|b|a}; sides, thick, additive, textured\rOUT: t1-t8; x,y,rad,ang; r,g,b,a; r2,g2,b2,a2; border_{r|g|b|a}; sides, thick, additive, textured", 256, 0, &OnUserEditedShapecode); + //m_menuShapecode[i].AddItem("[ edit per-point code ]",&m_pState->m_shape[i].m_szPerPoint, MENUITEMTYPE_STRING, "IN: sample [0..1]; value1 [left ch], value2 [right ch], plus all vars for per-frame code / OUT: x,y; r,g,b,a; t1-t8", 256, 0, &OnUserEditedWavecode); + } +#endif 0 +} + +void CPlugin::WriteRealtimeConfig() +{ +#if 0 + /*if (m_bSeparateTextWindow && m_hTextWnd) + { + RECT rect; + if (GetWindowRect(m_hTextWnd, &rect)) + { + WritePrivateProfileInt(rect.left, "nTextWndLeft", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(rect.top, "nTextWndTop", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(rect.right, "nTextWndRight", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(rect.bottom, "nTextWndBottom", GetConfigIniFile(), "settings"); + } + }*/ + + WritePrivateProfileInt(m_bShowFPS , "bShowFPS", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(m_bShowRating , "bShowRating", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(m_bShowPresetInfo , "bShowPresetInfo", GetConfigIniFile(), "settings"); + //WritePrivateProfileInt(m_bShowDebugInfo , "bShowDebugInfo", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(m_bShowSongTitle , "bShowSongTitle", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(m_bShowSongTime , "bShowSongTime", GetConfigIniFile(), "settings"); + WritePrivateProfileInt(m_bShowSongLen , "bShowSongLen", GetConfigIniFile(), "settings"); +#endif +} + +void CPlugin::dumpmsg(char *s) +{ + printf(s); +} + +void CPlugin::LoadPreviousPreset(float fBlendTime) +{ + // make sure file list is ok + if (m_nPresets - m_nDirs == 0) + { + UpdatePresetList(); + if (m_nPresets - m_nDirs == 0) + { + // note: this error message is repeated in milkdropfs.cpp in DrawText() + sprintf(m_szUserMessage, "ERROR: No preset files found in %s*.milk", m_szPresetDir); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + return; + } + } + + m_nCurrentPreset--; + if (m_nCurrentPreset < m_nDirs || m_nCurrentPreset >= m_nPresets) + m_nCurrentPreset = m_nPresets-1; + + strcpy(m_szCurrentPresetFile, m_szPresetDir); // note: m_szPresetDir always ends with '\' + strcat(m_szCurrentPresetFile, m_pPresetAddr[m_nCurrentPreset]); + + LoadPreset(m_szCurrentPresetFile, fBlendTime); +} + +void CPlugin::LoadNextPreset(float fBlendTime) +{ + // make sure file list is ok + if (m_nPresets - m_nDirs == 0) + { + UpdatePresetList(); + if (m_nPresets - m_nDirs == 0) + { + // note: this error message is repeated in milkdropfs.cpp in DrawText() + sprintf(m_szUserMessage, "ERROR: No preset files found in %s*.milk", m_szPresetDir); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + return; + } + } + + m_nCurrentPreset++; + if (m_nCurrentPreset < m_nDirs || m_nCurrentPreset >= m_nPresets) + m_nCurrentPreset = m_nDirs; + + strcpy(m_szCurrentPresetFile, m_szPresetDir); // note: m_szPresetDir always ends with '\' + strcat(m_szCurrentPresetFile, m_pPresetAddr[m_nCurrentPreset]); + + LoadPreset(m_szCurrentPresetFile, fBlendTime); +} + +void CPlugin::LoadRandomPreset(float fBlendTime) +{ + if (m_bHoldPreset) return; + // make sure file list is ok + if (m_nPresets - m_nDirs == 0) + { + UpdatePresetList(); + if (m_nPresets - m_nDirs == 0) + { + // note: this error message is repeated in milkdropfs.cpp in DrawText() + sprintf(m_szUserMessage, "ERROR: No preset files found in %s*.milk", m_szPresetDir); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + return; + } + } + + // --TEMPORARY-- + // this comes in handy if you want to mass-modify a batch of presets; + // just automatically tweak values in Import, then they immediately get exported to a .MILK in a new dir. + /* + for (int i=0; i= m_nPresets) + m_nCurrentPreset = m_nDirs; + } + else + { + // pick a random file + if (!m_bEnableRating || (m_pfPresetRating[m_nPresets - 1] < 0.1f) || (m_nRatingReadProgress < m_nPresets)) + { + m_nCurrentPreset = m_nDirs + (rand() % (m_nPresets - m_nDirs)); + } + else + { + float cdf_pos = (rand() % 14345)/14345.0f*m_pfPresetRating[m_nPresets - 1]; + + /* + char buf[512]; + sprintf(buf, "max = %f, rand = %f, \tvalues: ", m_pfPresetRating[m_nPresets - 1], cdf_pos); + for (int i=m_nDirs; i cdf_pos) + hi = mid; + else + lo = mid; + } + m_nCurrentPreset = hi; + } + } + } + + // m_pPresetAddr[m_nCurrentPreset] points to the preset file to load (w/o the path); + // first prepend the path, then load section [preset00] within that file + strcpy(m_szCurrentPresetFile, m_szPresetDir); // note: m_szPresetDir always ends with '\' + strcat(m_szCurrentPresetFile, m_pPresetAddr[m_nCurrentPreset]); + + LoadPreset(m_szCurrentPresetFile, fBlendTime); +} + +void CPlugin::RandomizeBlendPattern() +{ + if (!m_vertinfo) + return; + + int mixtype = rand()%4; + + if (mixtype==0) + { + // constant, uniform blend + int nVert = 0; + for (int y=0; y<=m_nGridY; y++) + { + for (int x=0; x<=m_nGridX; x++) + { + m_vertinfo[nVert].a = 1; + m_vertinfo[nVert].c = 0; + nVert++; + } + } + } + else if (mixtype==1) + { + // directional wipe + float ang = FRAND*6.28f; + float vx = cosf(ang); + float vy = sinf(ang); + float band = 0.1f + 0.2f*FRAND; // 0.2 is good + float inv_band = 1.0f/band; + + int nVert = 0; + for (int y=0; y<=m_nGridY; y++) + { + float fy = y/(float)m_nGridY; + for (int x=0; x<=m_nGridX; x++) + { + float fx = x/(float)m_nGridX; + + // at t==0, mix rangse from -10..0 + // at t==1, mix ranges from 1..11 + + float t = (fx-0.5f)*vx + (fy-0.5f)*vy + 0.5f; + t = (t-0.5f)/sqrtf(2.0f) + 0.5f; + + m_vertinfo[nVert].a = inv_band * (1 + band); + m_vertinfo[nVert].c = -inv_band + inv_band*t;//(x/(float)m_nGridX - 0.5f)/band; + nVert++; + } + } + } + else if (mixtype==2) + { + // plasma transition + float band = 0.02f + 0.18f*FRAND; + float inv_band = 1.0f/band; + + // first generate plasma array of height values + m_vertinfo[ 0].c = FRAND; + m_vertinfo[ m_nGridX].c = FRAND; + m_vertinfo[m_nGridY*(m_nGridX+1) ].c = FRAND; + m_vertinfo[m_nGridY*(m_nGridX+1) + m_nGridX].c = FRAND; + GenPlasma(0, m_nGridX, 0, m_nGridY, 0.25f); + + // then find min,max so we can normalize to [0..1] range and then to the proper 'constant offset' range. + float minc = m_vertinfo[0].c; + float maxc = m_vertinfo[0].c; + int x,y,nVert; + + nVert = 0; + for (y=0; y<=m_nGridY; y++) + { + for (x=0; x<=m_nGridX; x++) + { + if (minc > m_vertinfo[nVert].c) + minc = m_vertinfo[nVert].c; + if (maxc < m_vertinfo[nVert].c) + maxc = m_vertinfo[nVert].c; + nVert++; + } + } + + float mult = 1.0f/(maxc-minc); + nVert = 0; + for (y=0; y<=m_nGridY; y++) + { + for (x=0; x<=m_nGridX; x++) + { + float t = (m_vertinfo[nVert].c - minc)*mult; + m_vertinfo[nVert].a = inv_band * (1 + band); + m_vertinfo[nVert].c = -inv_band + inv_band*t; + nVert++; + } + } + } + else if (mixtype==3) + { + // radial blend + float band = 0.02f + 0.14f*FRAND + 0.34f*FRAND; + float inv_band = 1.0f/band; + float dir = (rand()%2)*2 - 1; + + int nVert = 0; + for (int y=0; y<=m_nGridY; y++) + { + float dy = y/(float)m_nGridY - 0.5f; + for (int x=0; x<=m_nGridX; x++) + { + float dx = x/(float)m_nGridX - 0.5f; + float t = sqrtf(dx*dx + dy*dy)*1.41421f; + if (dir==-1) + t = 1-t; + + m_vertinfo[nVert].a = inv_band * (1 + band); + m_vertinfo[nVert].c = -inv_band + inv_band*t; + nVert++; + } + } + } +} + +void CPlugin::GenPlasma(int x0, int x1, int y0, int y1, float dt) +{ + int midx = (x0+x1)/2; + int midy = (y0+y1)/2; + float t00 = m_vertinfo[y0*(m_nGridX+1) + x0].c; + float t01 = m_vertinfo[y0*(m_nGridX+1) + x1].c; + float t10 = m_vertinfo[y1*(m_nGridX+1) + x0].c; + float t11 = m_vertinfo[y1*(m_nGridX+1) + x1].c; + + if (y1-y0 >= 2) + { + if (x0==0) + m_vertinfo[midy*(m_nGridX+1) + x0].c = 0.5f*(t00 + t10) + (FRAND*2-1)*dt; + m_vertinfo[midy*(m_nGridX+1) + x1].c = 0.5f*(t01 + t11) + (FRAND*2-1)*dt; + } + if (x1-x0 >= 2) + { + if (y0==0) + m_vertinfo[y0*(m_nGridX+1) + midx].c = 0.5f*(t00 + t01) + (FRAND*2-1)*dt; + m_vertinfo[y1*(m_nGridX+1) + midx].c = 0.5f*(t10 + t11) + (FRAND*2-1)*dt; + } + + if (y1-y0 >= 2 && x1-x0 >= 2) + { + // do midpoint & recurse: + t00 = m_vertinfo[midy*(m_nGridX+1) + x0].c; + t01 = m_vertinfo[midy*(m_nGridX+1) + x1].c; + t10 = m_vertinfo[y0*(m_nGridX+1) + midx].c; + t11 = m_vertinfo[y1*(m_nGridX+1) + midx].c; + m_vertinfo[midy*(m_nGridX+1) + midx].c = 0.25f*(t10 + t11 + t00 + t01) + (FRAND*2-1)*dt; + + GenPlasma(x0, midx, y0, midy, dt*0.5f); + GenPlasma(midx, x1, y0, midy, dt*0.5f); + GenPlasma(x0, midx, midy, y1, dt*0.5f); + GenPlasma(midx, x1, midy, y1, dt*0.5f); + } +} + +void CPlugin::LoadPreset(char *szPresetFilename, float fBlendTime) +{ + OutputDebugString("Milkdrop: Loading preset "); + OutputDebugString(szPresetFilename); + OutputDebugString("\n"); + + + if (szPresetFilename != m_szCurrentPresetFile) + strcpy(m_szCurrentPresetFile, szPresetFilename); + + CState *temp = m_pState; + m_pState = m_pOldState; + m_pOldState = temp; + + m_pState->Import("preset00", m_szCurrentPresetFile); + + RandomizeBlendPattern(); + + if (fBlendTime >= 0.001f) + m_pState->StartBlendFrom(m_pOldState, GetTime(), fBlendTime); + + m_fPresetStartTime = GetTime(); + m_fNextPresetTime = -1.0f; // flags UpdateTime() to recompute this + +} + +void CPlugin::SeekToPreset(char cStartChar) +{ + if (cStartChar >= 'a' && cStartChar <= 'z') + cStartChar -= 'a' - 'A'; + + for (int i = m_nDirs; i < m_nPresets; i++) + { + char ch = m_pPresetAddr[i][0]; + if (ch >= 'a' && ch <= 'z') + ch -= 'a' - 'A'; + if (ch == cStartChar) + { + m_nPresetListCurPos = i; + return; + } + } +} + + +void CPlugin::UpdatePresetList() +{ + struct _finddata_t c_file; + long hFile; + //HANDLE hFindFile; + + char szMask[512]; + char szPath[512]; + char szLastPresetSelected[512]; + + if (m_nPresetListCurPos >= m_nDirs && m_nPresetListCurPos < m_nPresets) + strcpy(szLastPresetSelected, m_pPresetAddr[m_nPresetListCurPos]); + else + strcpy(szLastPresetSelected, ""); + + // make sure the path exists; if not, go to winamp plugins dir +/* + if (GetFileAttributes(m_szPresetDir) == -1) + { + strcpy(m_szPresetDir, m_szWinampPluginsPath); + if (GetFileAttributes(m_szPresetDir) == -1) + { + strcpy(m_szPresetDir, "c:\\"); + } + } +*/ + strcpy(szPath, m_szPresetDir); + int len = strlen(szPath); + if (len>0 && szPath[len-1] != '/') + { + strcat(szPath, "/"); + } + strcpy(szMask, szPath); + strcat(szMask, "*.*"); + + + WIN32_FIND_DATA ffd; + ZeroMemory(&ffd, sizeof(ffd)); + + m_nRatingReadProgress = 0; + + for (int i=0; i<2; i++) // usually RETURNs at end of first loop + { + m_nPresets = 0; + m_nDirs = 0; + + // find first .MILK file + if( (hFile = _findfirst(szMask, &c_file )) != -1L ) // note: returns filename -without- path + //if( (hFindFile = FindFirstFile(szMask, &ffd )) != INVALID_HANDLE_VALUE ) // note: returns filename -without- path + { + char *p = m_szpresets; + int bytes_left = m_nSizeOfPresetList - 1; // save space for extra null-termination of last string + + /* + len = strlen(ffd.cFileName); + bytes_left -= len+1; + strcpy(p, ffd.cFileName); + p += len+1; + m_nPresets++; + */ + //dumpmsg(ffd.cFileName); + + // find the rest + //while (_findnext( hFile, &c_file ) == 0) + + do + { + bool bSkip = false; + + char szFilename[512]; + strcpy(szFilename, c_file.name); + + /*if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + // skip "." directory + if (strcmp(ffd.cFileName, ".")==0)// || strlen(ffd.cFileName) < 1) + bSkip = true; + else + sprintf(szFilename, "*%s", ffd.cFileName); + } + else*/ + { + // skip normal files not ending in ".milk" + int len = strlen(c_file.name); + if (len < 5 || strcmpi(c_file.name + len - 5, ".milk") != 0) + bSkip = true; + } + + if (!bSkip) + { + //dumpmsg(szFilename); + len = strlen(szFilename); + bytes_left -= len+1; + + m_nPresets++; + /*if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + m_nDirs++;*/ + + if (bytes_left >= 0) + { + strcpy(p, szFilename); + p += len+1; + } + } + } + while(_findnext(hFile,&c_file) == 0); + + _findclose( hFile ); + + if (bytes_left >= 0) + { + // success! double-null-terminate the last string. + *p = 0; + + // also fill each slot of m_pPresetAddr with the address of each string + // but do it in ALPHABETICAL ORDER + if (m_pPresetAddr) delete m_pPresetAddr; + m_pPresetAddr = new CHARPTR[m_nPresets]; + + //the unsorted version: + p = m_szpresets; + for (int k=0; k reallocating list..."); + int new_size = (-bytes_left + m_nSizeOfPresetList)*11/10; // overallocate a bit + delete m_szpresets; + m_szpresets = new char[new_size]; + m_nSizeOfPresetList = new_size; + } + } + } + + // should never get here + sprintf(m_szUserMessage, "Unfathomable error getting preset file list!"); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + + m_nPresets = 0; + m_nDirs = 0; +} + + +void CPlugin::MergeSortPresets(int left, int right) +{ + // note: left..right range is inclusive + int nItems = right-left+1; + + if (nItems > 2) + { + // recurse to sort 2 halves (but don't actually recurse on a half if it only has 1 element) + int mid = (left+right)/2; + /*if (mid != left) */ MergeSortPresets(left, mid); + /*if (mid+1 != right)*/ MergeSortPresets(mid+1, right); + + // then merge results + int a = left; + int b = mid + 1; + while (a <= mid && b <= right) + { + bool bSwap; + + // merge the sorted arrays; give preference to strings that start with a '*' character + int nSpecial = 0; + if (m_pPresetAddr[a][0] == '*') nSpecial++; + if (m_pPresetAddr[b][0] == '*') nSpecial++; + + if (nSpecial == 1) + { + bSwap = (m_pPresetAddr[b][0] == '*'); + } + else + { + bSwap = (mystrcmpi(m_pPresetAddr[a], m_pPresetAddr[b]) > 0); + } + + if (bSwap) + { + CHARPTR temp = m_pPresetAddr[b]; + for (int k=b; k>a; k--) + m_pPresetAddr[k] = m_pPresetAddr[k-1]; + m_pPresetAddr[a] = temp; + mid++; + b++; + } + a++; + } + } + else if (nItems == 2) + { + // sort 2 items; give preference to 'special' strings that start with a '*' character + int nSpecial = 0; + if (m_pPresetAddr[left][0] == '*') nSpecial++; + if (m_pPresetAddr[right][0] == '*') nSpecial++; + + if (nSpecial == 1) + { + if (m_pPresetAddr[right][0] == '*') + { + CHARPTR temp = m_pPresetAddr[left]; + m_pPresetAddr[left] = m_pPresetAddr[right]; + m_pPresetAddr[right] = temp; + } + } + else if (mystrcmpi(m_pPresetAddr[left], m_pPresetAddr[right]) > 0) + { + CHARPTR temp = m_pPresetAddr[left]; + m_pPresetAddr[left] = m_pPresetAddr[right]; + m_pPresetAddr[right] = temp; + } + } +} + + +void CPlugin::WaitString_NukeSelection() +{ + if (m_waitstring.bActive && + m_waitstring.nSelAnchorPos != -1) + { + // nuke selection. note: start & end are INCLUSIVE. + int start = (m_waitstring.nCursorPos < m_waitstring.nSelAnchorPos) ? m_waitstring.nCursorPos : m_waitstring.nSelAnchorPos; + int end = (m_waitstring.nCursorPos > m_waitstring.nSelAnchorPos) ? m_waitstring.nCursorPos - 1 : m_waitstring.nSelAnchorPos - 1; + int len = strlen(m_waitstring.szText); + int how_far_to_shift = end - start + 1; + int num_chars_to_shift = len - end; // includes NULL char + + for (int i=0; i m_waitstring.nSelAnchorPos) ? m_waitstring.nCursorPos - 1 : m_waitstring.nSelAnchorPos - 1; + int chars_to_copy = end - start + 1; + + for (int i=0; i= m_waitstring.nMaxLen) + { + chars_to_insert = m_waitstring.nMaxLen - len - 1; + + // inform user + strcpy(m_szUserMessage, "(string too long)"); + m_fShowUserMessageUntilThisTime = GetTime() + 2.5f; + } + else + { + m_fShowUserMessageUntilThisTime = GetTime(); // if there was an error message already, clear it + } + + for (i=len; i >= m_waitstring.nCursorPos; i--) + m_waitstring.szText[i + chars_to_insert] = m_waitstring.szText[i]; + for (i=0; i < chars_to_insert; i++) + m_waitstring.szText[i + m_waitstring.nCursorPos] = m_waitstring.szClipboard[i]; + m_waitstring.nCursorPos += chars_to_insert; + } +} + +void CPlugin::WaitString_SeekLeftWord() +{ + // move to beginning of prior word + + while (m_waitstring.nCursorPos > 0 && + !IsAlphanumericChar(m_waitstring.szText[m_waitstring.nCursorPos-1])) + { + m_waitstring.nCursorPos--; + } + + while (m_waitstring.nCursorPos > 0 && + IsAlphanumericChar(m_waitstring.szText[m_waitstring.nCursorPos-1])) + { + m_waitstring.nCursorPos--; + } +} + +void CPlugin::WaitString_SeekRightWord() +{ + // move to beginning of next word + + //testing lotsa stuff + + int len = strlen(m_waitstring.szText); + + while (m_waitstring.nCursorPos < len && + IsAlphanumericChar(m_waitstring.szText[m_waitstring.nCursorPos])) + { + m_waitstring.nCursorPos++; + } + + while (m_waitstring.nCursorPos < len && + !IsAlphanumericChar(m_waitstring.szText[m_waitstring.nCursorPos])) + { + m_waitstring.nCursorPos++; + } +} + +int CPlugin::WaitString_GetCursorColumn() +{ + if (m_waitstring.bDisplayAsCode) + { + int column = 0; + while (m_waitstring.nCursorPos - column - 1 >= 0 && + m_waitstring.szText[m_waitstring.nCursorPos - column - 1] != LINEFEED_CONTROL_CHAR) + { + column++; + } + return column; + } + else + { + return m_waitstring.nCursorPos; + } +} + +int CPlugin::WaitString_GetLineLength() +{ + int line_start = m_waitstring.nCursorPos - WaitString_GetCursorColumn(); + int line_length = 0; + + while (m_waitstring.szText[line_start + line_length] != 0 && + m_waitstring.szText[line_start + line_length] != LINEFEED_CONTROL_CHAR) + { + line_length++; + } + + return line_length; +} + +void CPlugin::WaitString_SeekUpOneLine() +{ + int column = g_plugin->WaitString_GetCursorColumn(); + + if (column != m_waitstring.nCursorPos) + { + // seek to very end of previous line (cursor will be at the semicolon) + m_waitstring.nCursorPos -= column + 1; + + int new_column = g_plugin->WaitString_GetCursorColumn(); + + if (new_column > column) + m_waitstring.nCursorPos -= (new_column - column); + } +} + +void CPlugin::WaitString_SeekDownOneLine() +{ + int column = g_plugin->WaitString_GetCursorColumn(); + int newpos = m_waitstring.nCursorPos; + + while (m_waitstring.szText[newpos] != 0 && m_waitstring.szText[newpos] != LINEFEED_CONTROL_CHAR) + newpos++; + + if (m_waitstring.szText[newpos] != 0) + { + m_waitstring.nCursorPos = newpos + 1; + + while ( column > 0 && + m_waitstring.szText[m_waitstring.nCursorPos] != LINEFEED_CONTROL_CHAR && + m_waitstring.szText[m_waitstring.nCursorPos] != 0) + { + m_waitstring.nCursorPos++; + column--; + } + } +} + + +void CPlugin::SavePresetAs(char *szNewFile) +{ + // overwrites the file if it was already there, + // so you should check if the file exists first & prompt user to overwrite, + // before calling this function + + if (!m_pState->Export("preset00", szNewFile)) + { + // error + strcpy(m_szUserMessage, "ERROR: unable to save the file"); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + } + else + { + // pop up confirmation + strcpy(m_szUserMessage, "[save successful]"); + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + + // update m_pState->m_szDesc with the new name + strcpy(m_pState->m_szDesc, m_waitstring.szText); + + // refresh file listing + UpdatePresetList(); + } +} + +void CPlugin::DeletePresetFile(char *szDelFile) +{ + // NOTE: this function additionally assumes that m_nPresetListCurPos indicates + // the slot that the to-be-deleted preset occupies! + + // delete file + if (!DeleteFile(szDelFile)) + { + // error + strcpy(m_szUserMessage, "ERROR: unable to delete delete the file"); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + } + else + { + // pop up confirmation + sprintf(m_szUserMessage, "[preset \"%s\" deleted]", m_pPresetAddr[m_nPresetListCurPos]); + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + + // refresh file listing & re-select the next file after the one deleted + + if (m_nPresetListCurPos < m_nPresets - 1) + m_nPresetListCurPos++; + else if (m_nPresetListCurPos > 0) + m_nPresetListCurPos--; + else + m_nPresetListCurPos = 0; + + UpdatePresetList(); + } +} + +void CPlugin::RenamePresetFile(char *szOldFile, char *szNewFile) +{ + // NOTE: this function additionally assumes that m_nPresetListCurPos indicates + // the slot that the to-be-renamed preset occupies! + + if (GetFileAttributes(szNewFile) != -1) // check if file already exists + { + // error + strcpy(m_szUserMessage, "ERROR: a file already exists with that filename"); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + + // (user remains in UI_LOAD_RENAME mode to try another filename) + } + else + { + // rename + if (!MoveFile(szOldFile, szNewFile)) + { + // error + strcpy(m_szUserMessage, "ERROR: unable to rename the file"); + m_fShowUserMessageUntilThisTime = GetTime() + 6.0f; + } + else + { + // pop up confirmation + strcpy(m_szUserMessage, "[rename successful]"); + m_fShowUserMessageUntilThisTime = GetTime() + 4.0f; + + // if this preset was the active one, update m_pState->m_szDesc with the new name + char buf[512]; + sprintf(buf, "%s.milk", m_pState->m_szDesc); + if (strcmp(m_pPresetAddr[m_nPresetListCurPos], buf) == 0) + { + strcpy(m_pState->m_szDesc, m_waitstring.szText); + } + + // refresh file listing & do a trick to make it re-select the renamed file + strcpy(m_pPresetAddr[m_nPresetListCurPos], m_waitstring.szText); + strcat(m_pPresetAddr[m_nPresetListCurPos], ".milk"); + UpdatePresetList(); + } + + // exit waitstring mode (return to load menu) + m_UI_mode = UI_LOAD; + m_waitstring.bActive = false; + } +} + + +void CPlugin::UpdatePresetRatings() +{ + if (!m_bEnableRating) + return; + + if (m_nRatingReadProgress==-1 || m_nRatingReadProgress==m_nPresets) + return; + + int k; + + // read in ratings for each preset: + //if (m_pfPresetRating) delete m_pfPresetRating; + //m_pfPresetRating = new float[m_nPresets]; + if (m_pfPresetRating == NULL) + m_pfPresetRating = new float[m_nPresets]; + + if (m_nRatingReadProgress==0 && m_nDirs>0) + { + for (k=0; k 5) f = 5; + + if (k==0) + m_pfPresetRating[k] = f; + else + m_pfPresetRating[k] = m_pfPresetRating[k-1] + f; + + m_nRatingReadProgress++; + } +} + + +void CPlugin::SetCurrentPresetRating(float fNewRating) +{ + if (!m_bEnableRating) + return; + + if (fNewRating < 0) fNewRating = 0; + if (fNewRating > 5) fNewRating = 5; + float change = (fNewRating - m_pState->m_fRating); + + // update the file on disk: + //char szPresetFileNoPath[512]; + //char szPresetFileWithPath[512]; + //sprintf(szPresetFileNoPath, "%s.milk", m_pState->m_szDesc); + //sprintf(szPresetFileWithPath, "%s%s.milk", GetPresetDir(), m_pState->m_szDesc); + WritePrivateProfileFloat(fNewRating, "fRating", m_szCurrentPresetFile, "preset00"); + + // update the copy of the preset in memory + m_pState->m_fRating = fNewRating; + + // update the cumulative internal listing: + if (m_nCurrentPreset != -1 && m_nRatingReadProgress >= m_nCurrentPreset) // (can be -1 if dir. changed but no new preset was loaded yet) + for (int i=m_nCurrentPreset; im_nCurrentPreset is out of range! + -soln: when adjusting rating: + 1. file to modify is m_szCurrentPresetFile + 2. only update CDF if m_nCurrentPreset is not -1 + -> set m_nCurrentPreset to -1 whenever dir. changes + -> set m_szCurrentPresetFile whenever you load a preset + */ + + // show a message + if (!m_bShowRating) + { + // see also: DrawText() in milkdropfs.cpp + m_fShowRatingUntilThisTime = GetTime() + 2.0f; + } +} + + + +void CPlugin::ReadCustomMessages() +{ +#if 0 + + int n; + + // First, clear all old data + for (n=0; n 99) + nMsgNum = 99; + + if (nMsgNum < 0) + { + int count=0; + // choose randomly + for (nMsgNum=0; nMsgNum<100; nMsgNum++) + if (m_CustomMessage[nMsgNum].szText[0]) + count++; + + int sel = (rand()%count)+1; + count = 0; + for (nMsgNum=0; nMsgNum<100; nMsgNum++) + { + if (m_CustomMessage[nMsgNum].szText[0]) + count++; + if (count==sel) + break; + } + } + + + if (nMsgNum < 0 || + nMsgNum >= MAX_CUSTOM_MESSAGES || + m_CustomMessage[nMsgNum].szText[0]==0) + { + return; + } + + int fontID = m_CustomMessage[nMsgNum].nFont; + + m_supertext.bRedrawSuperText = true; + m_supertext.bIsSongTitle = false; + strcpy(m_supertext.szText, m_CustomMessage[nMsgNum].szText); + + // regular properties: + m_supertext.fFontSize = m_CustomMessage[nMsgNum].fSize; + m_supertext.fX = m_CustomMessage[nMsgNum].x + m_CustomMessage[nMsgNum].randx * ((rand()%1037)/1037.0f*2.0f - 1.0f); + m_supertext.fY = m_CustomMessage[nMsgNum].y + m_CustomMessage[nMsgNum].randy * ((rand()%1037)/1037.0f*2.0f - 1.0f); + m_supertext.fGrowth = m_CustomMessage[nMsgNum].growth; + m_supertext.fDuration = m_CustomMessage[nMsgNum].fTime; + m_supertext.fFadeTime = m_CustomMessage[nMsgNum].fFade; + + // overrideables: + if (m_CustomMessage[nMsgNum].bOverrideFace) + strcpy(m_supertext.nFontFace, m_CustomMessage[nMsgNum].szFace); + else + strcpy(m_supertext.nFontFace, m_CustomMessageFont[fontID].szFace); + m_supertext.bItal = (m_CustomMessage[nMsgNum].bOverrideItal) ? (m_CustomMessage[nMsgNum].bItal != 0) : (m_CustomMessageFont[fontID].bItal != 0); + m_supertext.bBold = (m_CustomMessage[nMsgNum].bOverrideBold) ? (m_CustomMessage[nMsgNum].bBold != 0) : (m_CustomMessageFont[fontID].bBold != 0); + m_supertext.nColorR = (m_CustomMessage[nMsgNum].bOverrideColorR) ? m_CustomMessage[nMsgNum].nColorR : m_CustomMessageFont[fontID].nColorR; + m_supertext.nColorG = (m_CustomMessage[nMsgNum].bOverrideColorG) ? m_CustomMessage[nMsgNum].nColorG : m_CustomMessageFont[fontID].nColorG; + m_supertext.nColorB = (m_CustomMessage[nMsgNum].bOverrideColorB) ? m_CustomMessage[nMsgNum].nColorB : m_CustomMessageFont[fontID].nColorB; + + // randomize color + m_supertext.nColorR += (int)(m_CustomMessage[nMsgNum].nRandR * ((rand()%1037)/1037.0f*2.0f - 1.0f)); + m_supertext.nColorG += (int)(m_CustomMessage[nMsgNum].nRandG * ((rand()%1037)/1037.0f*2.0f - 1.0f)); + m_supertext.nColorB += (int)(m_CustomMessage[nMsgNum].nRandB * ((rand()%1037)/1037.0f*2.0f - 1.0f)); + if (m_supertext.nColorR < 0) m_supertext.nColorR = 0; + if (m_supertext.nColorG < 0) m_supertext.nColorG = 0; + if (m_supertext.nColorB < 0) m_supertext.nColorB = 0; + if (m_supertext.nColorR > 255) m_supertext.nColorR = 255; + if (m_supertext.nColorG > 255) m_supertext.nColorG = 255; + if (m_supertext.nColorB > 255) m_supertext.nColorB = 255; + + // fix &'s for display: + /* + { + int pos = 0; + int len = strlen(m_supertext.szText); + while (m_supertext.szText[pos] && pos<255) + { + if (m_supertext.szText[pos] == '&') + { + for (int x=len; x>=pos; x--) + m_supertext.szText[x+1] = m_supertext.szText[x]; + len++; + pos++; + } + pos++; + } + }*/ + + m_supertext.fStartTime = GetTime(); +} + +void CPlugin::LaunchSongTitleAnim() +{ + m_supertext.bRedrawSuperText = true; + m_supertext.bIsSongTitle = true; + strcpy(m_supertext.szText, m_szSongTitle); + strcpy(m_supertext.nFontFace, m_fontinfo[SONGTITLE_FONT].szFace); + m_supertext.fFontSize = (float)m_fontinfo[SONGTITLE_FONT].nSize; + m_supertext.bBold = m_fontinfo[SONGTITLE_FONT].bBold; + m_supertext.bItal = m_fontinfo[SONGTITLE_FONT].bItalic; + m_supertext.fX = 0.5f; + m_supertext.fY = 0.5f; + m_supertext.fGrowth = 1.0f; + m_supertext.fDuration = m_fSongTitleAnimDuration; + m_supertext.nColorR = 255; + m_supertext.nColorG = 255; + m_supertext.nColorB = 255; + + m_supertext.fStartTime = GetTime(); +} + +bool CPlugin::LaunchSprite(int nSpriteNum, int nSlot) +{ +#if 0 + char initcode[8192], code[8192], img[512], section[64]; + char szTemp[8192]; + + initcode[0] = 0; + code[0] = 0; + img[0] = 0; + sprintf(section, "img%02d", nSpriteNum); + + // 1. read in image filename + InternalGetPrivateProfileString(section, "img", "", img, sizeof(img)-1, m_szImgIniFile); + if (img[0] == 0) + { + sprintf(m_szUserMessage, "sprite #%d error: couldn't find 'img=' setting, or sprite is not defined", nSpriteNum); + m_fShowUserMessageUntilThisTime = GetTime() + 7.0f; + return false; + } + + if (img[1] != ':' || img[2] != '\\') + { + // it's not in the form "x:\blah\billy.jpg" so prepend plugin dir path. + char temp[512]; + strcpy(temp, img); + sprintf(img, "%s%s", m_szWinampPluginsPath, temp); + } + + // 2. get color key + //unsigned int ck_lo = (unsigned int)InternalGetPrivateProfileInt(section, "colorkey_lo", 0x00000000, m_szImgIniFile); + //unsigned int ck_hi = (unsigned int)InternalGetPrivateProfileInt(section, "colorkey_hi", 0x00202020, m_szImgIniFile); + // FIRST try 'colorkey_lo' (for backwards compatibility) and then try 'colorkey' + unsigned int ck = (unsigned int)InternalGetPrivateProfileInt(section, "colorkey_lo", 0x00000000, m_szImgIniFile); + ck = (unsigned int)InternalGetPrivateProfileInt(section, "colorkey", ck, m_szImgIniFile); + + // 3. read in init code & per-frame code + for (int n=0; n<2; n++) + { + char *pStr = (n==0) ? initcode : code; + char szLineName[32]; + int len; + + int line = 1; + int char_pos = 0; + bool bDone = false; + + while (!bDone) + { + if (n==0) + sprintf(szLineName, "init_%d", line); + else + sprintf(szLineName, "code_%d", line); + + + InternalGetPrivateProfileString(section, szLineName, "~!@#$", szTemp, 8192, m_szImgIniFile); // fixme + len = strlen(szTemp); + + if ((strcmp(szTemp, "~!@#$")==0) || // if the key was missing, + (len >= 8191-char_pos-1)) // or if we're out of space + { + bDone = true; + } + else + { + sprintf(&pStr[char_pos], "%s%c", szTemp, LINEFEED_CONTROL_CHAR); + } + + char_pos += len + 1; + line++; + } + pStr[char_pos++] = 0; // null-terminate + } + + if (nSlot == -1) + { + // find first empty slot; if none, chuck the oldest sprite & take its slot. + int oldest_index = 0; + int oldest_frame = m_texmgr.m_tex[0].nStartFrame; + for (int x=0; x mysound.avg[i]) + rate = 0.2f; + else + rate = 0.5f; + rate = AdjustRateToFPS(rate, 30.0f, GetFps()); + mysound.avg[i] = mysound.avg[i]*rate + mysound.imm[i]*(1-rate); + + if (GetFrame() < 50) + rate = 0.9f; + else + rate = 0.992f; + rate = AdjustRateToFPS(rate, 30.0f, GetFps()); + mysound.long_avg[i] = mysound.long_avg[i]*rate + mysound.imm[i]*(1-rate); + + + // also get bass/mid/treble levels *relative to the past* + if (fabsf(mysound.long_avg[i]) < 0.001f) + mysound.imm_rel[i] = 1.0f; + else + mysound.imm_rel[i] = mysound.imm[i] / mysound.long_avg[i]; + + if (fabsf(mysound.long_avg[i]) < 0.001f) + mysound.avg_rel[i] = 1.0f; + else + mysound.avg_rel[i] = mysound.avg[i] / mysound.long_avg[i]; + } +} diff --git a/lib/vis_milkdrop/plugin.h b/lib/vis_milkdrop/plugin.h new file mode 100644 index 0000000..c0676a1 --- /dev/null +++ b/lib/vis_milkdrop/plugin.h @@ -0,0 +1,451 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __NULLSOFT_DX8_EXAMPLE_PLUGIN_H__ +#define __NULLSOFT_DX8_EXAMPLE_PLUGIN_H__ 1 + +#include "pluginshell.h" +#include "md_defines.h" +//#include "menu.h" +#include "support.h" +//#include "texmgr.h" +#include "state.h" + +typedef enum { UI_REGULAR, UI_MENU, UI_LOAD, UI_LOAD_DEL, UI_LOAD_RENAME, UI_SAVEAS, UI_SAVE_OVERWRITE, UI_EDIT_MENU_STRING, UI_CHANGEDIR, UI_IMPORT_WAVE, UI_EXPORT_WAVE, UI_IMPORT_SHAPE, UI_EXPORT_SHAPE } ui_mode; +typedef struct { float rad; float ang; float a; float c; } td_vertinfo; // blending: mix = max(0,min(1,a*t + c)); +typedef char* CHARPTR; +LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +#define MY_FFT_SAMPLES 512 // for old [pre-vms] milkdrop sound analysis +typedef struct +{ + float imm[3]; // bass, mids, treble (absolute) + float imm_rel[3]; // bass, mids, treble (relative to song; 1=avg, 0.9~below, 1.1~above) + float avg[3]; // bass, mids, treble (absolute) + float avg_rel[3]; // bass, mids, treble (relative to song; 1=avg, 0.9~below, 1.1~above) + float long_avg[3]; // bass, mids, treble (absolute) + float fWave[2][576]; + float fSpecLeft[MY_FFT_SAMPLES]; +} td_mysounddata; + +typedef struct +{ + int bActive; + int bFilterBadChars; // if true, it will filter out any characters that don't belong in a filename, plus the & symbol (because it doesn't display properly with DrawText) + int bDisplayAsCode; // if true, semicolons will be followed by a newline, for display + int nMaxLen; // can't be more than 511 + int nCursorPos; + int nSelAnchorPos; // -1 if no selection made + int bOvertypeMode; + char szText[8192]; + char szPrompt[512]; + char szToolTip[512]; + char szClipboard[8192]; +} td_waitstr; + +typedef struct +{ + int bBold; + int bItal; + char szFace[128]; + int nColorR; // 0..255 + int nColorG; // 0..255 + int nColorB; // 0..255 +} +td_custom_msg_font; + +typedef struct +{ + char szFace[256]; + int nSize; + int bBold; + int bItalic; +} td_titlefontinfo; + +typedef struct +{ + int nFont; + float fSize; // 0..100 + float x; + float y; + float randx; + float randy; + float growth; + float fTime; // total time to display the message, in seconds + float fFade; // % (0..1) of the time that is spent fading in + + // overrides + int bOverrideBold; + int bOverrideItal; + int bOverrideFace; + int bOverrideColorR; + int bOverrideColorG; + int bOverrideColorB; + int nColorR; // 0..255 + int nColorG; // 0..255 + int nColorB; // 0..255 + int nRandR; + int nRandG; + int nRandB; + int bBold; + int bItal; + char szFace[128]; + + char szText[256]; +} +td_custom_msg; + +typedef struct +{ + int bRedrawSuperText; // true if it needs redraw + int bIsSongTitle; // false for custom message, true for song title + char szText[256]; + char nFontFace[128]; + int bBold; + int bItal; + float fX; + float fY; + float fFontSize; // [0..100] for custom messages, [0..4] for song titles + float fGrowth; // applies to custom messages only + int nFontSizeUsed; // height IN PIXELS + float fStartTime; + float fDuration; + float fFadeTime; // applies to custom messages only; song title fade times are handled specially + int nColorR; + int nColorG; + int nColorB; +} +td_supertext; + +class CPlugin : public CPluginShell +{ +public: + + //====[ 1. members added to create this specific example plugin: ]================================================ + + /// CONFIG PANEL SETTINGS THAT WE'VE ADDED (TAB #2) + bool m_bFirstRun; + float m_fBlendTimeAuto; // blend time when preset auto-switches + float m_fBlendTimeUser; // blend time when user loads a new preset + float m_fTimeBetweenPresets; // <- this is in addition to m_fBlendTimeAuto + float m_fTimeBetweenPresetsRand; // <- this is in addition to m_fTimeBetweenPresets + bool m_bSequentialPresetOrder; + bool m_bHoldPreset; + bool m_bHardCutsDisabled; + float m_fHardCutLoudnessThresh; + float m_fHardCutHalflife; + float m_fHardCutThresh; + //int m_nWidth; + //int m_nHeight; + //int m_nDispBits; + int m_nTexSize; + int m_nGridX; + int m_nGridY; + + bool m_bShowPressF1ForHelp; + //char m_szMonitorName[256]; + bool m_bShowMenuToolTips; + int m_n16BitGamma; + bool m_bAutoGamma; + //int m_nFpsLimit; + int m_cLeftEye3DColor[3]; + int m_cRightEye3DColor[3]; + bool m_bEnableRating; + bool m_bInstaScan; + bool m_bSongTitleAnims; + float m_fSongTitleAnimDuration; + float m_fTimeBetweenRandomSongTitles; + float m_fTimeBetweenRandomCustomMsgs; + int m_nSongTitlesSpawned; + int m_nCustMsgsSpawned; + + bool m_bAlways3D; + float m_fStereoSep; + //bool m_bAlwaysOnTop; + //bool m_bFixSlowText; + bool m_bWarningsDisabled; // messageboxes + bool m_bWarningsDisabled2; // warnings/errors in upper-right corner (m_szUserMessage) + bool m_bAnisotropicFiltering; + bool m_bPresetLockOnAtStartup; + + /* + char m_szFontFace[NUM_FONTS][128]; + int m_nFontSize[NUM_FONTS]; + bool m_bFontBold[NUM_FONTS]; + bool m_bFontItalic[NUM_FONTS]; + char m_szTitleFontFace[128]; + int m_nTitleFontSize; // percentage of screen width (0..100) + bool m_bTitleFontBold; + bool m_bTitleFontItalic; + */ +// HFONT m_gdi_title_font_doublesize; +// LPD3DXFONT m_d3dx_title_font_doublesize; + + // RUNTIME SETTINGS THAT WE'VE ADDED + float m_prev_time; + bool m_bTexSizeWasAuto; + bool m_bPresetLockedByUser; + bool m_bPresetLockedByCode; + float m_fAnimTime; + float m_fStartTime; + float m_fPresetStartTime; + float m_fNextPresetTime; + CState *m_pState; // points to current CState + CState *m_pOldState; // points to previous CState + CState m_state_DO_NOT_USE[2]; // do not use; use pState and pOldState instead. + ui_mode m_UI_mode; // can be UI_REGULAR, UI_LOAD, UI_SAVEHOW, or UI_SAVEAS + //td_playlist_entry *m_szPlaylist; // array of 128-char strings + //int m_nPlaylistCurPos; + //int m_nPlaylistLength; + //int m_nTrackPlaying; + //int m_nSongPosMS; + //int m_nSongLenMS; + bool m_bUserPagedUp; + bool m_bUserPagedDown; + float m_fMotionVectorsTempDx; + float m_fMotionVectorsTempDy; + + td_waitstr m_waitstring; + void WaitString_NukeSelection(); + void WaitString_Cut(); + void WaitString_Copy(); + void WaitString_Paste(); + void WaitString_SeekLeftWord(); + void WaitString_SeekRightWord(); + int WaitString_GetCursorColumn(); + int WaitString_GetLineLength(); + void WaitString_SeekUpOneLine(); + void WaitString_SeekDownOneLine(); + + int m_nPresets; // the # of entries in the file listing. Includes directories and then files, sorted alphabetically. + int m_nDirs; // the # of presets that are actually directories. Always between 0 and m_nPresets. + int m_nPresetListCurPos;// Index (in m_pPresetAddr[]) of the currently-HIGHLIGHTED preset (the user must press Enter on it to select it). + int m_nCurrentPreset; // Index (in m_pPresetAddr[]) of the currently-RUNNING preset. + // Note that this is NOT the same as the currently-highlighted preset! (that's m_nPresetListCurPos) + // Be careful - this can be -1 if the user changed dir. & a new preset hasn't been loaded yet. + char m_szCurrentPresetFile[512]; // this is always valid (unless no presets were found) + CHARPTR *m_pPresetAddr; // slot n of this array is a pointer to the nth string in m_szpresets. (optimization; allows for constant-time access.) Each entry is just a filename + extension (with no path - the path is m_szPresetDir for all of them). + float *m_pfPresetRating; // not-cumulative version + char *m_szpresets; // 1 giant dynamically-allocated string; actually a string-of-strings, containing 'm_nPresets' null-terminated strings one after another; and the last string is followed with two NULL characters instead of just one. + int m_nSizeOfPresetList; // the # of bytes currently allocated for 'm_szpresets' + int m_nRatingReadProgress; // equals 'm_nPresets' if all ratings are read in & ready to go; -1 if uninitialized; otherwise, it's still reading them in, and range is: [0 .. m_nPresets-1] + + FFT myfft; + td_mysounddata mysound; + + // stuff for displaying text to user: + //int m_nTextHeightPixels; // this is for the menu/detail font; NOT the "fancy font" + //int m_nTextHeightPixels_Fancy; + bool m_bShowFPS; + bool m_bShowRating; + bool m_bShowPresetInfo; + bool m_bShowDebugInfo; + bool m_bShowSongTitle; + bool m_bShowSongTime; + bool m_bShowSongLen; + float m_fShowUserMessageUntilThisTime; + float m_fShowRatingUntilThisTime; + char m_szUserMessage[512]; + char m_szDebugMessage[512]; + char m_szSongTitle [512]; + char m_szSongTitlePrev[512]; + //HFONT m_hfont[3]; // 0=fancy font (for song titles, preset name) + // 1=legible font (the main font) + // 2=tooltip font (for tooltips in the menu system) + //HFONT m_htitlefont[NUM_TITLE_FONTS]; // ~25 different sizes + // stuff for menu system: +/* CMilkMenu *m_pCurMenu; // should always be valid! + CMilkMenu m_menuPreset; + CMilkMenu m_menuWave; + CMilkMenu m_menuAugment; + CMilkMenu m_menuCustomWave; + CMilkMenu m_menuCustomShape; + CMilkMenu m_menuMotion; + CMilkMenu m_menuPost; + CMilkMenu m_menuWavecode[MAX_CUSTOM_WAVES]; + CMilkMenu m_menuShapecode[MAX_CUSTOM_SHAPES]; +*/ + char m_szWinampPluginsPath[MAX_PATH]; // ends in a backslash + char m_szMsgIniFile[MAX_PATH]; + char m_szImgIniFile[MAX_PATH]; + char m_szPresetDir[MAX_PATH]; + float m_fRandStart[4]; + + // DIRECTX 8: + IDirect3DTexture9 *m_lpVS[2]; + IDirect3DSurface9 *m_pZBuffer; +// IDirect3DTexture8 *m_lpDDSTitle; // CAREFUL: MIGHT BE NULL (if not enough mem)! + int m_nTitleTexSizeX, m_nTitleTexSizeY; + SPRITEVERTEX *m_verts; + SPRITEVERTEX *m_verts_temp; + td_vertinfo *m_vertinfo; + WORD *m_indices; + + bool m_bMMX; + //bool m_bSSE; + bool m_bHasFocus; + bool m_bHadFocus; + bool m_bOrigScrollLockState; + bool m_bMilkdropScrollLockState; // saved when focus is lost; restored when focus is regained + + int m_nNumericInputMode; // NUMERIC_INPUT_MODE_CUST_MSG, NUMERIC_INPUT_MODE_SPRITE + int m_nNumericInputNum; + int m_nNumericInputDigits; + td_custom_msg_font m_CustomMessageFont[MAX_CUSTOM_MESSAGE_FONTS]; + td_custom_msg m_CustomMessage[MAX_CUSTOM_MESSAGES]; + +// texmgr m_texmgr; // for user sprites + + td_supertext m_supertext; // **contains info about current Song Title or Custom Message.** + + IDirect3DTexture9 *m_tracer_tex; + + //====[ 2. methods added: ]===================================================================================== + + void RefreshTab2(HWND hwnd); + void RenderFrame(int bRedraw); + void AlignWave(int nSamples); + + void DrawTooltip(char* str, int xR, int yB); + void RandomizeBlendPattern(); + void GenPlasma(int x0, int x1, int y0, int y1, float dt); + void LoadPerFrameEvallibVars(CState* pState); + void LoadCustomWavePerFrameEvallibVars(CState* pState, int i); + void LoadCustomShapePerFrameEvallibVars(CState* pState, int i); + void WriteRealtimeConfig(); // called on Finish() + void dumpmsg(char *s); + void Randomize(); + void LoadRandomPreset(float fBlendTime); + void LoadNextPreset(float fBlendTime); + void LoadPreviousPreset(float fBlendTime); + void LoadPreset(char *szPresetFilename, float fBlendTime); + void UpdatePresetList(); + void UpdatePresetRatings(); + //char* GetConfigIniFile() { return m_szConfigIniFile; }; + char* GetMsgIniFile() { return m_szMsgIniFile; }; + char* GetPresetDir() { return m_szPresetDir; }; + void SavePresetAs(char *szNewFile); // overwrites the file if it was already there. + void DeletePresetFile(char *szDelFile); + void RenamePresetFile(char *szOldFile, char *szNewFile); + void SetCurrentPresetRating(float fNewRating); + void SeekToPreset(char cStartChar); + bool ReversePropagatePoint(float fx, float fy, float *fx2, float *fy2); + int HandleRegularKey(WPARAM wParam); + bool OnResizeGraphicsWindow(); + bool OnResizeTextWindow(); + //bool InitFont(); + //void ToggleControlWindow(); // for Desktop Mode only + //void DrawUI(); + void ClearGraphicsWindow(); // for windowed mode only + //bool Update_Overlay(); + //void UpdatePlaylist(); + void LaunchCustomMessage(int nMsgNum); + void ReadCustomMessages(); + void LaunchSongTitleAnim(); + + bool RenderStringToTitleTexture(); + void ShowSongTitleAnim(/*IDirect3DTexture8* lpRenderTarget,*/ int w, int h, float fProgress); + void DrawWave(float *fL, float *fR); + void DrawCustomWaves(); + void DrawCustomShapes(); + void DrawSprites(); + void WarpedBlitFromVS0ToVS1(); + void RunPerFrameEquations(); + void ShowToUser(int bRedraw); + void DrawUserSprites(); + void MergeSortPresets(int left, int right); + void BuildMenus(); + //void ResetWindowSizeOnDisk(); + bool LaunchSprite(int nSpriteNum, int nSlot); + void KillSprite(int iSlot); + void DoCustomSoundAnalysis(); + void DrawMotionVectors(); + + //====[ 3. virtual functions: ]=========================================================================== + + virtual void OverrideDefaults(); + virtual void MyPreInitialize(); + virtual void MyReadConfig(); + virtual void MyWriteConfig(); + virtual int AllocateMyNonDx8Stuff(); + virtual void CleanUpMyNonDx8Stuff(); + virtual int AllocateMyDX8Stuff(); + virtual void CleanUpMyDX8Stuff(int final_cleanup); + virtual void MyRenderFn(int redraw); + virtual void MyRenderUI(int *upper_left_corner_y, int *upper_right_corner_y, int *lower_left_corner_y, int *lower_right_corner_y, int xL, int xR); + virtual LRESULT MyWindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); + virtual BOOL MyConfigTabProc(int nPage, HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + + //====[ 4. methods from base class: ]=========================================================================== + /* + // 'GET' METHODS + // ------------------------------------------------------------ + int GetFrame(); // returns current frame # (starts at zero) + float GetTime(); // returns current animation time (in seconds) (starts at zero) (updated once per frame) + float GetFps(); // returns current estimate of framerate (frames per second) + eScrMode GetScreenMode(); // returns WINDOWED, FULLSCREEN, FAKE_FULLSCREEN, or NOT_YET_KNOWN (if called before or during OverrideDefaults()). + HWND GetWinampWindow(); // returns handle to Winamp main window + HINSTANCE GetInstance(); // returns handle to the plugin DLL module; used for things like loading resources (dialogs, bitmaps, icons...) that are built into the plugin. + char* GetPluginsDirPath(); // usually returns 'c:\\program files\\winamp\\plugins\\' + char* GetConfigIniFile(); // usually returns 'c:\\program files\\winamp\\plugins\\something.ini' - filename is determined from identifiers in 'defines.h' + + // GET METHODS THAT ONLY WORK ONCE DIRECTX IS READY + // ------------------------------------------------------------ + // The following 'Get' methods are only available after DirectX has been initialized. + // If you call these from OverrideDefaults, MyPreInitialize, or MyReadConfig, + // they will fail and return NULL (zero). + // ------------------------------------------------------------ + HWND GetPluginWindow(); // returns handle to the plugin window. NOT persistent; can change. + int GetWidth(); // returns width of plugin window interior, in pixels. + int GetHeight(); // returns height of plugin window interior, in pixels. + D3DFORMAT GetBackBufFormat(); // returns the pixelformat of the back buffer (probably D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, D3DFMT_A4R4G4B4, D3DFMT_R3G3B2, D3DFMT_A8R3G3B2, D3DFMT_X4R4G4B4, or D3DFMT_UNKNOWN) + D3DFORMAT GetBackBufZFormat(); // returns the pixelformat of the back buffer's Z buffer (probably D3DFMT_D16_LOCKABLE, D3DFMT_D32, D3DFMT_D15S1, D3DFMT_D24S8, D3DFMT_D16, D3DFMT_D24X8, D3DFMT_D24X4S4, or D3DFMT_UNKNOWN) + D3DCAPS8* GetCaps(); // returns a pointer to the D3DCAPS8 structer for the device. NOT persistent; can change. + LPDIRECT3DDEVICE8 GetDevice(); // returns a pointer to the DirectX 8 Device. NOT persistent; can change. + + // FONTS & TEXT + // ------------------------------------------------------------ + LPD3DXFONT GetFont(eFontIndex idx); // returns a handle to a D3DX font you can use to draw text on the screen + int GetFontHeight(eFontIndex idx); // returns the height of the font, in pixels + + // MISC + // ------------------------------------------------------------ + td_soundinfo m_sound; // a structure always containing the most recent sound analysis information; defined in pluginshell.h. + void SuggestHowToFreeSomeMem(); // gives the user a 'smart' messagebox that suggests how they can free up some video memory. + */ + //===================================================================================================================== + +}; + + + + + +#endif \ No newline at end of file diff --git a/lib/vis_milkdrop/pluginshell.cpp b/lib/vis_milkdrop/pluginshell.cpp new file mode 100644 index 0000000..a9184a7 --- /dev/null +++ b/lib/vis_milkdrop/pluginshell.cpp @@ -0,0 +1,3543 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* + TO DO + ----- + + -to do/v1.06: + -FFT: high freq. data kinda sucks because of the 8-bit samples we get in; + look for justin to put 16-bit vis data into wa5. + -make an 'advanced view' button on config panel; hide complicated stuff + til they click that. + -put an asterisk(*) next to the 'max framerate' values that + are ideal (given the current windows display mode or selected FS dispmode). + -or add checkbox: "smart sync" + -> matches FPS limit to nearest integer divisor of refresh rate. + -debug.txt/logging support! + -audio: make it a DSP plugin? then we could get the complete, continuous waveform + and overlap our waveform windows, so we'd never miss a brief high note. + -bugs: + -vms plugins sometimes freeze after a several-minute pause; I've seen it + with most of them. hard to repro, though. + -running FS on monitor 2, hit ALT-TAB -> minimizes!!! + -but only if you let go of TAB first. Let go of ALT first and it's fine! + -> means it's related to the keyup... + -fix delayloadhelper leak; one for each launch to config panel/plugin. + -also, delayload(d3d8.dll) still leaks, if plugin has error initializing and + quits by returning false from PluginInitialize(). + -add config panel option to ignore fake-fullscreen tips + -"tip" boxes in dxcontext.cpp + -"notice" box on WM_ACTIVATEAPP? + -desktop mode: + -icon context menus: 'send to', 'cut', and 'copy' links do nothing. + -http://netez.com/2xExplorer/shellFAQ/bas_context.html + -create a 2nd texture to render all icon text labels into + (they're the sole reason that desktop mode is slow) + -in UpdateIconBitmaps, don't read the whole bitmap and THEN + realize it's a dupe; try to compare icon filename+index or somethign? + -DRAG AND DROP. COMPLICATED; MANY DETAILS. + -http://netez.com/2xExplorer/shellFAQ/adv_drag.html + -http://www.codeproject.com/shell/explorerdragdrop.asp + -hmm... you can't drag icons between the 2 desktops (ugh) + -multiple delete/open/props/etc + -delete + enter + arrow keys. + -try to solve mysteries w/ShellExecuteEx() and desktop *shortcuts* (*.lnk). + -(notice that when icons are selected, they get modulated by the + highlight color, when they should be blended 50% with that color.) + + --------------------------- + final touches: + -Tests: + -make sure desktop still functions/responds properly when winamp paused + -desktop mode + multimon: + -try desktop mode on all monitors + -try moving taskbar around; make sure icons are in the + right place, that context menus (general & for + specific icons) pop up in the right place, and that + text-off-left-edge is ok. + -try setting the 2 monitors to different/same resolutions + -check tab order of config panel controls! + -Clean All + -build in release mode to include in the ZIP + -leave only one file open in workspace: README.TXT. + -TEMPORARILY "ATTRIB -R" ALL FILES BEFORE ZIPPING THEM! + + --------------------------- + KEEP IN VIEW: + -EMBEDWND: + -kiv: on resize of embedwnd, it's out of our control; winamp + resizes the child every time the mouse position changes, + and we have to cleanup & reallocate everything, b/c we + can't tell when the resize begins & ends. + [justin said he'd fix in wa5, though] + -kiv: with embedded windows of any type (plugin, playlist, etc.) + you can't place the winamp main wnd over them. + -kiv: tiny bug (IGNORE): when switching between embedwnd & + no-embedding, the window gets scooted a tiny tiny bit. + -kiv: fake fullscreen mode w/multiple monitors: there is no way + to keep the taskbar from popping up [potentially overtop of + the plugin] when you click on something besides the plugin. + To get around this, use true fullscreen mode. + -kiv: max_fps implementation assumptions: + -that most computers support high-precision timer + -that no computers [regularly] sleep for more than 1-2 ms + when you call Sleep(1) after timeBeginPeriod(1). + -reminder: if vms_desktop.dll's interface needs changed, + it will have to be renamed! (version # upgrades are ok + as long as it won't break on an old version; if the + new functionality is essential, rename the DLL.) + + --------------------------- + REMEMBER: + -GF2MX + GF4 have icon scooting probs in desktop mode + (when taskbar is on upper or left edge of screen) + -Radeon is the one w/super slow text probs @ 1280x1024. + (it goes unstable after you show playlist AND helpscr; -> ~1 fps) + -Mark's win98 machine has hidden cursor (in all modes), + but no one else seems to have this problem. + -links: + -win2k-only-style desktop mode: (uses VirtualAllocEx, vs. DLL Injection) + http://www.digiwar.com/scripts/renderpage.php?section=2&subsection=2 + -http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_20096218.html +*/ + +//#include +#include +#include "pluginshell.h" +#include "utility.h" +#include "defines.h" +#include "shell_defines.h" +//#include "resource.h" +//#include "vis.h" +#include +#include +#include +//#include +//#pragma comment(lib,"winmm.lib") // for timeGetTime + +// STATE VALUES & VERTEX FORMATS FOR HELP SCREEN TEXTURE: +#define TEXT_SURFACE_NOT_READY 0 +#define TEXT_SURFACE_REQUESTED 1 +#define TEXT_SURFACE_READY 2 +#define TEXT_SURFACE_ERROR 3 +typedef struct _HELPVERTEX +{ + float x, y; // screen position + float z; // Z-buffer depth + DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims) + float tu, tv; // texture coordinates for texture #0 +} HELPVERTEX, *LPHELPVERTEX; +#define HELP_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1) +typedef struct _SIMPLEVERTEX +{ + float x, y; // screen position + float z; // Z-buffer depth + DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims) +} SIMPLEVERTEX, *LPSIMPLEVERTEX; +#define SIMPLE_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE) + +extern char g_szHelp[]; +//extern winampVisModule mod1; + +// resides in vms_desktop.dll/lib: +void getItemData(int x); + + +CPluginShell::CPluginShell() +{ + // this should remain empty! +} + +CPluginShell::~CPluginShell() +{ + // this should remain empty! +} + +eScrMode CPluginShell::GetScreenMode() { return m_screenmode; }; +int CPluginShell::GetFrame() { return m_frame; }; +float CPluginShell::GetTime() { return m_time; }; +float CPluginShell::GetFps() { return m_fps; }; +HWND CPluginShell::GetPluginWindow() { if (m_lpDX) return m_lpDX->GetHwnd(); else return NULL; }; +int CPluginShell::GetWidth() { if (m_lpDX) return m_lpDX->m_client_width; else return 0; }; +int CPluginShell::GetHeight() { if (m_lpDX) return m_lpDX->m_client_height; else return 0; }; +HWND CPluginShell::GetWinampWindow() { return m_hWndWinamp; }; +HINSTANCE CPluginShell::GetInstance() { return m_hInstance; }; +char* CPluginShell::GetPluginsDirPath() { return m_szPluginsDirPath; }; +char* CPluginShell::GetConfigIniFile() { return m_szConfigIniFile; }; +//int CPluginShell::GetFontHeight(eFontIndex idx) { if (idx >= 0 && idx < NUM_BASIC_FONTS + NUM_EXTRA_FONTS) return m_fontinfo[idx].nSize; else return 0; }; +int CPluginShell::GetBitDepth() { return m_lpDX->GetBitDepth(); }; +LPDIRECT3DDEVICE9 CPluginShell::GetDevice() { if (m_lpDX) return m_lpDX->m_lpDevice; else return NULL; }; +D3DCAPS9* CPluginShell::GetCaps() { if (m_lpDX) return &(m_lpDX->m_caps); else return NULL; }; +D3DFORMAT CPluginShell::GetBackBufFormat() { if (m_lpDX) return m_lpDX->m_current_mode.display_mode.Format; else return D3DFMT_UNKNOWN; }; +D3DFORMAT CPluginShell::GetBackBufZFormat() { if (m_lpDX) return m_lpDX->GetZFormat(); else return D3DFMT_UNKNOWN; }; +//LPD3DXFONT CPluginShell::GetFont(eFontIndex idx) { if (idx >= 0 && idx < NUM_BASIC_FONTS + NUM_EXTRA_FONTS) return m_d3dx_font[idx]; else return NULL; }; +char* CPluginShell::GetDriverFilename() { if (m_lpDX) return m_lpDX->GetDriver(); else return NULL; }; +char* CPluginShell::GetDriverDescription() { if (m_lpDX) return m_lpDX->GetDesc(); else return NULL; }; + + +int CPluginShell::InitNonDx8Stuff() +{ +// timeBeginPeriod(1); + m_fftobj.Init(512, NUM_FREQUENCIES); + if (!InitGDIStuff()) return false; + return AllocateMyNonDx8Stuff(); +} + +void CPluginShell::CleanUpNonDx8Stuff() +{ +// timeEndPeriod(1); + CleanUpMyNonDx8Stuff(); + CleanUpGDIStuff(); + m_fftobj.CleanUp(); +} + +int CPluginShell::InitGDIStuff() +{ +#if 0 + // note: messagebox parent window should be NULL here, because lpDX is still NULL! + + for (int i=0; iGetAdapterCount(); + for (int i=0; iGetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &temp) == D3D_OK) && + (memcmp(&temp.DeviceIdentifier, &m_adapter_guid_windowed, sizeof(GUID))==0)) + { + ordinal_adapter = i; + break; + } + } + + // Get current display mode for windowed-mode adapter: + D3DDISPLAYMODE dm; + if (D3D_OK != m_vjd3d8->GetAdapterDisplayMode(ordinal_adapter, &dm)) + { + MessageBox(NULL,"VJ mode init error: error determining color format\rfor currently-selected Windowed Mode display adapter.","MILKDROP ERROR",MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } + + // And get the upper-left corner of the monitor for it: + HMONITOR hMon = m_vjd3d8->GetAdapterMonitor(ordinal_adapter); + if (hMon) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMon, &mi)) + { + upper_left_corner.x = mi.rcWork.left; + upper_left_corner.y = mi.rcWork.top; + } + } + + // CREATE THE WINDOW + + RECT rect; + if (pClientRect) + { + rect = *pClientRect; + AdjustWindowRect(&rect, dwStyle, 0); // convert client->wnd + } + else + { + SetRect(&rect, 0, 0, 384, 384); + AdjustWindowRect(&rect, dwStyle, 0); // convert client->wnd + + rect.right -= rect.left; + rect.left = 0; + rect.bottom -= rect.top; + rect.top = 0; + + rect.top += upper_left_corner.y+32; + rect.left += upper_left_corner.x+32; + rect.right += upper_left_corner.x+32; + rect.bottom += upper_left_corner.y+32; + } + + WNDCLASS wc; + memset(&wc,0,sizeof(wc)); + wc.lpfnWndProc = VJModeWndProc; // our window procedure + wc.hInstance = GetInstance(); // hInstance of DLL + wc.hIcon = LoadIcon( GetInstance(), MAKEINTRESOURCE(IDI_PLUGIN_ICON) ); + wc.lpszClassName = TEXT_WINDOW_CLASSNAME; // our window class name + wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // CS_DBLCLKS lets the window receive WM_LBUTTONDBLCLK, for toggling fullscreen mode... + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(DWORD); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = NULL; + + if (!RegisterClass(&wc)) + { + MessageBox(NULL,"Error registering window class for text window","MILKDROP ERROR",MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } + m_bTextWindowClassRegistered = true; + + //DWORD nThreadID; + //CreateThread(NULL, 0, TextWindowThread, &rect, 0, &nThreadID); + + // Create the text window + m_hTextWnd = CreateWindowEx( + 0, + TEXT_WINDOW_CLASSNAME, // our window class name + TEXT_WINDOW_CLASSNAME, // use description for a window title + dwStyle, + rect.left, rect.top, // screen position (read from config) + rect.right - rect.left, rect.bottom - rect.top, // width & height of window (need to adjust client area later) + NULL, // parent window (winamp main window) + NULL, // no menu + GetInstance(), // hInstance of DLL + NULL + ); // no window creation data + + if (!m_hTextWnd) + { + MessageBox(NULL,"Error creating VJ window","MILKDROP ERROR",MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } + + SetWindowLong(m_hTextWnd, GWL_USERDATA, (LONG)this); + + GetClientRect(m_hTextWnd, &rect); + m_nTextWndWidth = rect.right-rect.left; + m_nTextWndHeight = rect.bottom-rect.top; + + + // Create the device + D3DPRESENT_PARAMETERS pres_param; + pres_param.BackBufferCount = 1; + pres_param.BackBufferFormat = dm.Format; + pres_param.BackBufferWidth = rect.right - rect.left; + pres_param.BackBufferHeight = rect.bottom - rect.top; + pres_param.hDeviceWindow = m_hTextWnd; + pres_param.AutoDepthStencilFormat = D3DFMT_D16; + pres_param.EnableAutoDepthStencil = FALSE; + pres_param.SwapEffect = D3DSWAPEFFECT_DISCARD; + pres_param.MultiSampleType = D3DMULTISAMPLE_NONE; + pres_param.Flags = 0; + pres_param.FullScreen_RefreshRateInHz = 0; + pres_param.FullScreen_PresentationInterval = 0; + pres_param.Windowed = TRUE; + + HRESULT hr; + if (D3D_OK != (hr = m_vjd3d8->CreateDevice(ordinal_adapter,//D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + m_hTextWnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, + &pres_param, + &m_vjd3d8_device))) + { + m_vjd3d8_device = NULL; + MessageBox(m_lpDX->GetHwnd(),"Error creating D3D device for VJ mode","MILKDROP ERROR",MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } + + if (!AllocateFonts(m_vjd3d8_device)) + return false; + + if (m_fix_slow_text) // note that when not doing vj mode, m_lpDDSText is allocated in AllocateDX8Stuff + AllocateTextSurface(); + + m_text.Finish(); + m_text.Init(m_vjd3d8_device, m_lpDDSText, 0); + } +#endif + return true; +} + +void CPluginShell::CleanUpVJStuff() +{ +#if 0 + // ALWAYS set the textures to NULL before releasing textures, + // otherwise they might still have a hanging reference! + if (m_lpDX && m_lpDX->m_lpDevice) + { + m_lpDX->m_lpDevice->SetTexture(0, NULL); + m_lpDX->m_lpDevice->SetTexture(1, NULL); + } + + if (m_vjd3d8_device) + { + m_vjd3d8_device->SetTexture(0, NULL); + m_vjd3d8_device->SetTexture(1, NULL); + } + + // clean up VJ mode + { + if (m_vjd3d8_device) + { + CleanUpFonts(); + SafeRelease(m_lpDDSText); + } + + SafeRelease(m_vjd3d8_device); + SafeRelease(m_vjd3d8); + + if (m_hTextWnd) + { + //dumpmsg("Finish: destroying text window"); + DestroyWindow(m_hTextWnd); + m_hTextWnd = NULL; + //dumpmsg("Finish: text window destroyed"); + } + + if (m_bTextWindowClassRegistered) + { + //dumpmsg("Finish: unregistering text window class"); + UnregisterClass(TEXT_WINDOW_CLASSNAME,GetInstance()); // unregister window class + m_bTextWindowClassRegistered = false; + //dumpmsg("Finish: text window class unregistered"); + } + } +#endif +} + +int CPluginShell::AllocateFonts(IDirect3DDevice9* pDevice) +{ +#if 0 + // Create D3DX system font: + for (int i=0; iGetHwnd() : NULL, "Error creating D3DX fonts", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return false; + } + + // get actual font heights + for (i=0; iDrawText("M", -1, &r, DT_CALCRECT, 0xFFFFFFFF); + if (h>0) m_fontinfo[i].nSize = h; + } +#endif + return true; +} + +void CPluginShell::CleanUpFonts() +{ +#if 0 + for (int i=0; iGetLevelDesc(0, &desc)) + { + if ((desc.Width < 256 && w >= 256) || + (desc.Height < 256 && h >= 256) || + (desc.Width /(float)w < 0.74f) || + (desc.Height/(float)h < 0.74f) + ) + { + m_lpDDSText->Release(); + m_lpDDSText = NULL; + } + } + } +#endif +} + +int CPluginShell::AllocateDX8Stuff() +{ +// if (m_screenmode == DESKTOP) +// if (!InitDesktopMode()) +// return false; + + if (!m_vjd3d8_device) // otherwise it's done in InitVJStuff, and tied to the vj text wnd device + if (!AllocateFonts(GetDevice())) + return false; + + if (!AllocateMyDX8Stuff()) + return false; + + // OFFSCREEN TEXT SETUP: + if (m_fix_slow_text && !m_vjd3d8_device) // otherwise it's allocated in InitVJStuff + AllocateTextSurface(); + + if (!m_vjd3d8_device) // otherwise it's initialized in InitVJStuff + { +// m_text.Finish(); +// m_text.Init(GetDevice(), m_lpDDSText, 1); + } + + // invalidate various 'caches' here: + m_playlist_top_idx = -1; // invalidating playlist cache forces recompute of playlist width + //m_icon_list.clear(); // clear desktop mode icon list, so it has to read the bitmaps back in + + return true; +} + +void CPluginShell::CleanUpDX8Stuff(int final_cleanup) +{ + // ALWAYS set the textures to NULL before releasing textures, + // otherwise they might still have a hanging reference! + if (m_lpDX && m_lpDX->m_lpDevice) + { + m_lpDX->m_lpDevice->SetTexture(0, NULL); + m_lpDX->m_lpDevice->SetTexture(1, NULL); + } + + if (m_vjd3d8_device) + { + m_vjd3d8_device->SetTexture(0, NULL); + m_vjd3d8_device->SetTexture(1, NULL); + } + + //----------------------// + +// m_text.Finish(); + +// if (!m_vjd3d8_device) // otherwise it happens in CleanUpVJStuff() +// SafeRelease(m_lpDDSText); + + CleanUpMyDX8Stuff(final_cleanup); + + if (!m_vjd3d8_device) // otherwise it happens in CleanUpVJStuff() + CleanUpFonts(); + +// if (m_screenmode == DESKTOP) +// CleanUpDesktopMode(); +} + +void CPluginShell::OnUserResizeTextWindow() +{ +#if 0 + // Update window properties + RECT w, c; + GetWindowRect( m_hTextWnd, &w ); + GetClientRect( m_hTextWnd, &c ); + + WINDOWPLACEMENT wp; + ZeroMemory(&wp, sizeof(wp)); + wp.length = sizeof(wp); + GetWindowPlacement(m_hTextWnd, &wp); + + // convert client rect from client coords to screen coords: + // (window rect is already in screen coords...) + POINT p; + p.x = c.left; + p.y = c.top; + if (ClientToScreen(m_hTextWnd, &p)) + { + c.left += p.x; + c.right += p.x; + c.top += p.y; + c.bottom += p.y; + } + + if(wp.showCmd != SW_SHOWMINIMIZED) + { + if (m_nTextWndWidth != c.right-c.left || + m_nTextWndHeight != c.bottom-c.top) + { + CleanUpVJStuff(); + if (!InitVJStuff(&c)) + { + SuggestHowToFreeSomeMem(); + m_lpDX->m_ready = false; // flag to exit + return; + } + } + + // save the new window position: + //if (wp.showCmd==SW_SHOWNORMAL) + // SaveTextWindowPos(); + } +#endif +} + +void CPluginShell::OnUserResizeWindow() +{ +#if 0 + // Update window properties + RECT w, c; + GetWindowRect( m_lpDX->GetHwnd(), &w ); + GetClientRect( m_lpDX->GetHwnd(), &c ); + + WINDOWPLACEMENT wp; + ZeroMemory(&wp, sizeof(wp)); + wp.length = sizeof(wp); + GetWindowPlacement(m_lpDX->GetHwnd(), &wp); + + // convert client rect from client coords to screen coords: + // (window rect is already in screen coords...) + POINT p; + p.x = c.left; + p.y = c.top; + if (ClientToScreen(m_lpDX->GetHwnd(), &p)) + { + c.left += p.x; + c.right += p.x; + c.top += p.y; + c.bottom += p.y; + } + + if(wp.showCmd != SW_SHOWMINIMIZED) + { + if (m_lpDX->m_client_width != c.right-c.left || + m_lpDX->m_client_height != c.bottom-c.top) + { + CleanUpDX8Stuff(0); + if (!m_lpDX->OnUserResizeWindow(&w, &c)) + { + // note: a basic warning messagebox will have already been given. + // now suggest specific advice on how to regain more video memory: + SuggestHowToFreeSomeMem(); + return; + } + if (!AllocateDX8Stuff()) + { + m_lpDX->m_ready = false; // flag to exit + return; + } + } + + // save the new window position: + if (wp.showCmd==SW_SHOWNORMAL) + m_lpDX->SaveWindow(); + } +#endif +} + +void CPluginShell::StuffParams(DXCONTEXT_PARAMS *pParams) +{ + pParams->screenmode = m_screenmode; + pParams->display_mode = m_disp_mode_fs; + pParams->nbackbuf = 1; + pParams->m_dualhead_horz = m_dualhead_horz; + pParams->m_dualhead_vert = m_dualhead_vert; + pParams->m_skin = (m_screenmode==WINDOWED) ? m_skin : 0; + switch(m_screenmode) + { + case WINDOWED: + pParams->allow_page_tearing = m_allow_page_tearing_w; + pParams->adapter_guid = m_adapter_guid_windowed; + pParams->multisamp = m_multisample_windowed; + break; + case FULLSCREEN: + case FAKE_FULLSCREEN: + pParams->allow_page_tearing = m_allow_page_tearing_fs; + pParams->adapter_guid = m_adapter_guid_fullscreen; + pParams->multisamp = m_multisample_fullscreen; + break; + case DESKTOP: + pParams->allow_page_tearing = m_allow_page_tearing_dm; + pParams->adapter_guid = m_adapter_guid_desktop; + pParams->multisamp = m_multisample_desktop; + break; + } + pParams->parent_window = (m_screenmode==DESKTOP) ? m_hWndDesktopListView : NULL; +} + +void CPluginShell::ToggleDesktop() +{ + CleanUpDX8Stuff(0); + + switch(m_screenmode) + { + case WINDOWED: + case FULLSCREEN: + case FAKE_FULLSCREEN: + m_screenmode = DESKTOP; + break; + case DESKTOP: + m_screenmode = WINDOWED; + break; + } + + DXCONTEXT_PARAMS params; + StuffParams(¶ms); + + if (!m_lpDX->StartOrRestartDevice(¶ms)) + { + // note: a basic warning messagebox will have already been given. + if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY) + SuggestHowToFreeSomeMem(); + return; + } + + if (!AllocateDX8Stuff()) + { + m_lpDX->m_ready = false; // flag to exit + return; + } + +// SetForegroundWindow(m_lpDX->GetHwnd()); +// SetActiveWindow(m_lpDX->GetHwnd()); +// SetFocus(m_lpDX->GetHwnd()); +} + +#define IPC_IS_PLAYING_VIDEO 501 // from wa_ipc.h +#define IPC_SET_VIS_FS_FLAG 631 // a vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode + +void CPluginShell::ToggleFullScreen() +{ +#if 0 + CleanUpDX8Stuff(0); + + switch(m_screenmode) + { + case DESKTOP: + case WINDOWED: + m_screenmode = m_fake_fullscreen_mode ? FAKE_FULLSCREEN : FULLSCREEN; + if (m_screenmode == FULLSCREEN && SendMessage(GetWinampWindow(),WM_WA_IPC,0,IPC_IS_PLAYING_VIDEO)>1) + { + m_screenmode=FAKE_FULLSCREEN; + } + SendMessage(GetWinampWindow(),WM_WA_IPC,1,IPC_SET_VIS_FS_FLAG); + break; + case FULLSCREEN: + case FAKE_FULLSCREEN: + m_screenmode = WINDOWED; + SendMessage(GetWinampWindow(),WM_WA_IPC,0,IPC_SET_VIS_FS_FLAG); + break; + } + + DXCONTEXT_PARAMS params; + StuffParams(¶ms); + + if (!m_lpDX->StartOrRestartDevice(¶ms)) + { + // note: a basic warning messagebox will have already been given. + if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY) + SuggestHowToFreeSomeMem(); + return; + } + + if (!AllocateDX8Stuff()) + { + m_lpDX->m_ready = false; // flag to exit + return; + } + + SetForegroundWindow(m_lpDX->GetHwnd()); + SetActiveWindow(m_lpDX->GetHwnd()); + SetFocus(m_lpDX->GetHwnd()); +#endif +} + +void CPluginShell::ToggleHelp() +{ + m_show_help = 1-m_show_help; +// int ret = CheckMenuItem( m_context_menu, ID_SHOWHELP, MF_BYCOMMAND | (m_show_help ? MF_CHECKED : MF_UNCHECKED) ); +} + +void CPluginShell::TogglePlaylist() +{ + m_show_playlist = 1-m_show_playlist; + m_playlist_top_idx = -1; // <- invalidates playlist cache +// int ret = CheckMenuItem( m_context_menu, ID_SHOWPLAYLIST, MF_BYCOMMAND | (m_show_playlist ? MF_CHECKED : MF_UNCHECKED) ); +} + +int CPluginShell::InitDirectX() +{ + +// m_lpDX = new DXContext(m_hWndWinamp,m_hInstance,CLASSNAME,WINDOWCAPTION,CPluginShell::WindowProc,(LONG)this, m_minimize_winamp, m_szConfigIniFile); + m_lpDX = new DXContext(m_device, m_szConfigIniFile); + if (!m_lpDX) + { +// MessageBox(NULL, "Unable to initialize DXContext;\rprobably out of memory.", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); + return FALSE; + } + + if (m_lpDX->m_lastErr != S_OK) + { + // warning messagebox will have already been given + delete m_lpDX; + return FALSE; + } + + // initialize graphics + DXCONTEXT_PARAMS params; + StuffParams(¶ms); + + if (!m_lpDX->StartOrRestartDevice(¶ms)) + { + // note: a basic warning messagebox will have already been given. + + if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY) + { + // suggest specific advice on how to regain more video memory: + SuggestHowToFreeSomeMem(); + } + + delete m_lpDX; + m_lpDX = NULL; + return FALSE; + } + + return TRUE; +} + +void CPluginShell::CleanUpDirectX() +{ + SafeDelete(m_lpDX); +} + +int CPluginShell::PluginPreInitialize(HWND hWinampWnd, HINSTANCE hWinampInstance) +{ + + // PROTECTED CONFIG PANEL SETTINGS (also see 'private' settings, below) + m_start_fullscreen = 0; + m_start_desktop = 0; + m_fake_fullscreen_mode = 0; + m_max_fps_fs = 30; + m_max_fps_dm = 30; + m_max_fps_w = 30; + m_show_press_f1_msg = 1; + m_allow_page_tearing_w = 1; + m_allow_page_tearing_fs = 0; + m_allow_page_tearing_dm = 0; + m_minimize_winamp = 1; + m_desktop_show_icons = 1; + m_desktop_textlabel_boxes = 1; + m_desktop_manual_icon_scoot = 0; + m_desktop_555_fix = 2; + m_dualhead_horz = 2; + m_dualhead_vert = 1; + m_save_cpu = 1; + m_skin = 1; + m_fix_slow_text = 1; + + // initialize font settings: + strcpy(m_fontinfo[SIMPLE_FONT ].szFace, SIMPLE_FONT_DEFAULT_FACE ); + m_fontinfo[SIMPLE_FONT ].nSize = SIMPLE_FONT_DEFAULT_SIZE ; + m_fontinfo[SIMPLE_FONT ].bBold = SIMPLE_FONT_DEFAULT_BOLD ; + m_fontinfo[SIMPLE_FONT ].bItalic = SIMPLE_FONT_DEFAULT_ITAL ; + m_fontinfo[SIMPLE_FONT ].bAntiAliased = SIMPLE_FONT_DEFAULT_AA ; + strcpy(m_fontinfo[DECORATIVE_FONT].szFace, DECORATIVE_FONT_DEFAULT_FACE); + m_fontinfo[DECORATIVE_FONT].nSize = DECORATIVE_FONT_DEFAULT_SIZE; + m_fontinfo[DECORATIVE_FONT].bBold = DECORATIVE_FONT_DEFAULT_BOLD; + m_fontinfo[DECORATIVE_FONT].bItalic = DECORATIVE_FONT_DEFAULT_ITAL; + m_fontinfo[DECORATIVE_FONT].bAntiAliased = DECORATIVE_FONT_DEFAULT_AA ; + strcpy(m_fontinfo[HELPSCREEN_FONT].szFace, HELPSCREEN_FONT_DEFAULT_FACE); + m_fontinfo[HELPSCREEN_FONT].nSize = HELPSCREEN_FONT_DEFAULT_SIZE; + m_fontinfo[HELPSCREEN_FONT].bBold = HELPSCREEN_FONT_DEFAULT_BOLD; + m_fontinfo[HELPSCREEN_FONT].bItalic = HELPSCREEN_FONT_DEFAULT_ITAL; + m_fontinfo[HELPSCREEN_FONT].bAntiAliased = HELPSCREEN_FONT_DEFAULT_AA ; + strcpy(m_fontinfo[PLAYLIST_FONT ].szFace, PLAYLIST_FONT_DEFAULT_FACE); + m_fontinfo[PLAYLIST_FONT ].nSize = PLAYLIST_FONT_DEFAULT_SIZE; + m_fontinfo[PLAYLIST_FONT ].bBold = PLAYLIST_FONT_DEFAULT_BOLD; + m_fontinfo[PLAYLIST_FONT ].bItalic = PLAYLIST_FONT_DEFAULT_ITAL; + m_fontinfo[PLAYLIST_FONT ].bAntiAliased = PLAYLIST_FONT_DEFAULT_AA ; + + #if (NUM_EXTRA_FONTS >= 1) + strcpy(m_fontinfo[NUM_BASIC_FONTS + 0].szFace, EXTRA_FONT_1_DEFAULT_FACE); + m_fontinfo[NUM_BASIC_FONTS + 0].nSize = EXTRA_FONT_1_DEFAULT_SIZE; + m_fontinfo[NUM_BASIC_FONTS + 0].bBold = EXTRA_FONT_1_DEFAULT_BOLD; + m_fontinfo[NUM_BASIC_FONTS + 0].bItalic = EXTRA_FONT_1_DEFAULT_ITAL; + m_fontinfo[NUM_BASIC_FONTS + 0].bAntiAliased = EXTRA_FONT_1_DEFAULT_AA; + #endif + #if (NUM_EXTRA_FONTS >= 2) + strcpy(m_fontinfo[NUM_BASIC_FONTS + 1].szFace, EXTRA_FONT_2_DEFAULT_FACE); + m_fontinfo[NUM_BASIC_FONTS + 1].nSize = EXTRA_FONT_2_DEFAULT_SIZE; + m_fontinfo[NUM_BASIC_FONTS + 1].bBold = EXTRA_FONT_2_DEFAULT_BOLD; + m_fontinfo[NUM_BASIC_FONTS + 1].bItalic = EXTRA_FONT_2_DEFAULT_ITAL; + m_fontinfo[NUM_BASIC_FONTS + 1].bAntiAliased = EXTRA_FONT_2_DEFAULT_AA; + #endif + #if (NUM_EXTRA_FONTS >= 3) + strcpy(m_fontinfo[NUM_BASIC_FONTS + 2].szFace, EXTRA_FONT_3_DEFAULT_FACE); + m_fontinfo[NUM_BASIC_FONTS + 2].nSize = EXTRA_FONT_3_DEFAULT_SIZE; + m_fontinfo[NUM_BASIC_FONTS + 2].bBold = EXTRA_FONT_3_DEFAULT_BOLD; + m_fontinfo[NUM_BASIC_FONTS + 2].bItalic = EXTRA_FONT_3_DEFAULT_ITAL; + m_fontinfo[NUM_BASIC_FONTS + 2].bAntiAliased = EXTRA_FONT_3_DEFAULT_AA; + #endif + #if (NUM_EXTRA_FONTS >= 4) + strcpy(m_fontinfo[NUM_BASIC_FONTS + 3].szFace, EXTRA_FONT_4_DEFAULT_FACE); + m_fontinfo[NUM_BASIC_FONTS + 3].nSize = EXTRA_FONT_4_DEFAULT_SIZE; + m_fontinfo[NUM_BASIC_FONTS + 3].bBold = EXTRA_FONT_4_DEFAULT_BOLD; + m_fontinfo[NUM_BASIC_FONTS + 3].bItalic = EXTRA_FONT_4_DEFAULT_ITAL; + m_fontinfo[NUM_BASIC_FONTS + 3].bAntiAliased = EXTRA_FONT_4_DEFAULT_AA; + #endif + #if (NUM_EXTRA_FONTS >= 5) + strcpy(m_fontinfo[NUM_BASIC_FONTS + 4].szFace, EXTRA_FONT_5_DEFAULT_FACE); + m_fontinfo[NUM_BASIC_FONTS + 4].nSize = EXTRA_FONT_5_DEFAULT_SIZE; + m_fontinfo[NUM_BASIC_FONTS + 4].bBold = EXTRA_FONT_5_DEFAULT_BOLD; + m_fontinfo[NUM_BASIC_FONTS + 4].bItalic = EXTRA_FONT_5_DEFAULT_ITAL; + m_fontinfo[NUM_BASIC_FONTS + 4].bAntiAliased = EXTRA_FONT_5_DEFAULT_AA; + #endif + + m_disp_mode_fs.Width = DEFAULT_FULLSCREEN_WIDTH; + m_disp_mode_fs.Height = DEFAULT_FULLSCREEN_HEIGHT; + m_disp_mode_fs.Format = D3DFMT_UNKNOWN; + m_disp_mode_fs.RefreshRate = 60; + + // PROTECTED STRUCTURES/POINTERS +// for (int i=0; i= m_szPluginsDirPath && *p != '\\') p--; +// if (++p >= m_szPluginsDirPath) *p = 0; + sprintf(m_szPluginsDirPath, "special://xbmc/addons/"); +// sprintf(m_szPluginsDirPath, "d:\\"); + } + sprintf(m_szConfigIniFile, "%s%s", m_szPluginsDirPath, INIFILE); + + // PRIVATE CONFIG PANEL SETTINGS + m_multisample_fullscreen = D3DMULTISAMPLE_NONE; + m_multisample_desktop = D3DMULTISAMPLE_NONE; + m_multisample_windowed = D3DMULTISAMPLE_NONE; + ZeroMemory(&m_adapter_guid_fullscreen, sizeof(GUID)); + ZeroMemory(&m_adapter_guid_desktop , sizeof(GUID)); + ZeroMemory(&m_adapter_guid_windowed , sizeof(GUID)); + + // PRIVATE RUNTIME SETTINGS + m_lost_focus = 0; + m_hidden = 0; + m_resizing = 0; + m_show_help = 0; + m_show_playlist = 0; + m_playlist_pos = 0; + m_playlist_pageups = 0; + m_playlist_top_idx = -1; + m_playlist_btm_idx = -1; + // m_playlist_width_pixels will be considered invalid whenever 'm_playlist_top_idx' is -1. + // m_playlist[256][256] will be considered invalid whenever 'm_playlist_top_idx' is -1. + m_exiting = 0; + m_upper_left_corner_y = 0; + m_lower_left_corner_y = 0; + m_upper_right_corner_y = 0; + m_lower_right_corner_y = 0; + m_left_edge = 0; + m_right_edge = 0; + m_force_accept_WM_WINDOWPOSCHANGING = 0; + + // PRIVATE - GDI STUFF + m_main_menu = NULL; + m_context_menu = NULL; +// for (i=0; i1) +// { + // m_screenmode=FAKE_FULLSCREEN; + // } + } + // else if (m_start_desktop) + // m_screenmode = DESKTOP; + // else + // m_screenmode = WINDOWED; + + MyPreInitialize(); + MyReadConfig(); + + //----- + + return TRUE; +} + +int CPluginShell::PluginInitialize(LPDIRECT3DDEVICE9 device, int iPosX, int iPosY, int iWidth, int iHeight, float pixelRatio) +{ + // note: initialize GDI before DirectX. Also separate them because + // when we change windowed<->fullscreen, or lose the device and restore it, + // we don't want to mess with any (persistent) GDI stuff. + m_device = device; + if (!InitDirectX()) return FALSE; // gives its own error messages + m_lpDX->m_client_width = iWidth; + m_lpDX->m_client_height = iHeight; + m_posX = iPosX; + m_posY = iPosY; + m_pixelRatio = pixelRatio; + + if (!InitNonDx8Stuff()) return FALSE; // gives its own error messages + if (!InitVJStuff()) return FALSE; + if (!AllocateDX8Stuff()) return FALSE; // gives its own error messages + + return TRUE; +} + +void CPluginShell::PluginQuit() +{ + CleanUpDX8Stuff(1); + CleanUpVJStuff(); + CleanUpNonDx8Stuff(); + CleanUpDirectX(); + CleanUpMyDX8Stuff(1); + +// SetFocus(m_hWndWinamp); +// SetActiveWindow(m_hWndWinamp); +// SetForegroundWindow(m_hWndWinamp); +} + +void CPluginShell::ReadConfig() +{ +#if 0 + int old_ver = InternalGetPrivateProfileInt("settings","version" ,-1,m_szConfigIniFile); + int old_subver = InternalGetPrivateProfileInt("settings","subversion",-1,m_szConfigIniFile); + + // nuke old settings from prev. version: + if (old_ver < INT_VERSION) + return; + else if (old_subver < INT_SUBVERSION) + return; + + //D3DMULTISAMPLE_TYPE m_multisample_fullscreen; + //D3DMULTISAMPLE_TYPE m_multisample_desktop; + //D3DMULTISAMPLE_TYPE m_multisample_windowed; + m_multisample_fullscreen = (D3DMULTISAMPLE_TYPE)InternalGetPrivateProfileInt("settings","multisample_fullscreen",m_multisample_fullscreen,m_szConfigIniFile); + m_multisample_desktop = (D3DMULTISAMPLE_TYPE)InternalGetPrivateProfileInt("settings","multisample_desktop",m_multisample_desktop,m_szConfigIniFile); + m_multisample_windowed = (D3DMULTISAMPLE_TYPE)InternalGetPrivateProfileInt("settings","multisample_windowed" ,m_multisample_windowed ,m_szConfigIniFile); + + //GUID m_adapter_guid_fullscreen + //GUID m_adapter_guid_desktop + //GUID m_adapter_guid_windowed + char str[256]; + InternalGetPrivateProfileString("settings","adapter_guid_fullscreen","",str,sizeof(str)-1,m_szConfigIniFile); + TextToGuid(str, &m_adapter_guid_fullscreen); + InternalGetPrivateProfileString("settings","adapter_guid_desktop","",str,sizeof(str)-1,m_szConfigIniFile); + TextToGuid(str, &m_adapter_guid_desktop); + InternalGetPrivateProfileString("settings","adapter_guid_windowed","",str,sizeof(str)-1,m_szConfigIniFile); + TextToGuid(str, &m_adapter_guid_windowed); + + /* + // FONTS + #define READ_FONT(n) { \ + InternalGetPrivateProfileString("settings","szFontFace"#n,m_fontinfo[n].szFace,m_fontinfo[n].szFace,sizeof(m_fontinfo[n].szFace), m_szConfigIniFile); \ + m_fontinfo[n].nSize = InternalGetPrivateProfileInt("settings","nFontSize"#n ,m_fontinfo[n].nSize ,m_szConfigIniFile); \ + m_fontinfo[n].bBold = InternalGetPrivateProfileInt("settings","bFontBold"#n ,m_fontinfo[n].bBold ,m_szConfigIniFile); \ + m_fontinfo[n].bItalic = InternalGetPrivateProfileInt("settings","bFontItalic"#n,m_fontinfo[n].bItalic,m_szConfigIniFile); \ + m_fontinfo[n].bAntiAliased = InternalGetPrivateProfileInt("settings","bFontAA"#n,m_fontinfo[n].bItalic,m_szConfigIniFile); \ + } + READ_FONT(0); + READ_FONT(1); + READ_FONT(2); + READ_FONT(3); + #if (NUM_EXTRA_FONTS >= 1) + READ_FONT(4); + #endif + #if (NUM_EXTRA_FONTS >= 2) + READ_FONT(5); + #endif + #if (NUM_EXTRA_FONTS >= 3) + READ_FONT(6); + #endif + #if (NUM_EXTRA_FONTS >= 4) + READ_FONT(7); + #endif + #if (NUM_EXTRA_FONTS >= 5) + READ_FONT(8); + #endif +*/ + m_start_fullscreen = InternalGetPrivateProfileInt("settings","start_fullscreen",m_start_fullscreen,m_szConfigIniFile); + m_start_desktop = InternalGetPrivateProfileInt("settings","start_desktop" ,m_start_desktop ,m_szConfigIniFile); + m_fake_fullscreen_mode = InternalGetPrivateProfileInt("settings","fake_fullscreen_mode",m_fake_fullscreen_mode,m_szConfigIniFile); + m_max_fps_fs = InternalGetPrivateProfileInt("settings","max_fps_fs",m_max_fps_fs,m_szConfigIniFile); + m_max_fps_dm = InternalGetPrivateProfileInt("settings","max_fps_dm",m_max_fps_dm,m_szConfigIniFile); + m_max_fps_w = InternalGetPrivateProfileInt("settings","max_fps_w" ,m_max_fps_w ,m_szConfigIniFile); + m_show_press_f1_msg = InternalGetPrivateProfileInt("settings","show_press_f1_msg",m_show_press_f1_msg,m_szConfigIniFile); + m_allow_page_tearing_w = InternalGetPrivateProfileInt("settings","allow_page_tearing_w",m_allow_page_tearing_w,m_szConfigIniFile); + m_allow_page_tearing_fs= InternalGetPrivateProfileInt("settings","allow_page_tearing_fs",m_allow_page_tearing_fs,m_szConfigIniFile); + m_allow_page_tearing_dm= InternalGetPrivateProfileInt("settings","allow_page_tearing_dm",m_allow_page_tearing_dm,m_szConfigIniFile); + m_minimize_winamp = InternalGetPrivateProfileInt("settings","minimize_winamp",m_minimize_winamp,m_szConfigIniFile); + m_desktop_show_icons = InternalGetPrivateProfileInt("settings","desktop_show_icons",m_desktop_show_icons,m_szConfigIniFile); + m_desktop_textlabel_boxes = InternalGetPrivateProfileInt("settings","desktop_textlabel_boxes",m_desktop_textlabel_boxes,m_szConfigIniFile); + m_desktop_manual_icon_scoot = InternalGetPrivateProfileInt("settings","desktop_manual_icon_scoot",m_desktop_manual_icon_scoot,m_szConfigIniFile); + m_desktop_555_fix = InternalGetPrivateProfileInt("settings","desktop_555_fix",m_desktop_555_fix,m_szConfigIniFile); + m_dualhead_horz = InternalGetPrivateProfileInt("settings","dualhead_horz",m_dualhead_horz,m_szConfigIniFile); + m_dualhead_vert = InternalGetPrivateProfileInt("settings","dualhead_vert",m_dualhead_vert,m_szConfigIniFile); + m_save_cpu = InternalGetPrivateProfileInt("settings","save_cpu",m_save_cpu,m_szConfigIniFile); + m_skin = InternalGetPrivateProfileInt("settings","skin",m_skin,m_szConfigIniFile); + m_fix_slow_text = InternalGetPrivateProfileInt("settings","fix_slow_text",m_fix_slow_text,m_szConfigIniFile); + m_vj_mode = GetPrivateProfileBool("settings","vj_mode",m_vj_mode,m_szConfigIniFile); + + //D3DDISPLAYMODE m_fs_disp_mode + m_disp_mode_fs.Width = InternalGetPrivateProfileInt("settings","disp_mode_fs_w",m_disp_mode_fs.Width ,m_szConfigIniFile); + m_disp_mode_fs.Height = InternalGetPrivateProfileInt("settings","disp_mode_fs_h",m_disp_mode_fs.Height ,m_szConfigIniFile); + m_disp_mode_fs.RefreshRate = InternalGetPrivateProfileInt("settings","disp_mode_fs_r",m_disp_mode_fs.RefreshRate,m_szConfigIniFile); + m_disp_mode_fs.Format = (D3DFORMAT)InternalGetPrivateProfileInt("settings","disp_mode_fs_f",m_disp_mode_fs.Format ,m_szConfigIniFile); + + // note: we don't call MyReadConfig() yet, because we + // want to completely finish CPluginShell's preinit (and ReadConfig) + // before calling CPlugin's preinit and ReadConfig. + +#endif +} + +void CPluginShell::WriteConfig() +{ +#if 0 + //D3DMULTISAMPLE_TYPE m_multisample_fullscreen; + //D3DMULTISAMPLE_TYPE m_multisample_desktop; + //D3DMULTISAMPLE_TYPE m_multisample_windowed; + WritePrivateProfileInt((int)m_multisample_fullscreen,"multisample_fullscreen",m_szConfigIniFile,"settings"); + WritePrivateProfileInt((int)m_multisample_desktop ,"multisample_desktop" ,m_szConfigIniFile,"settings"); + WritePrivateProfileInt((int)m_multisample_windowed ,"multisample_windowed" ,m_szConfigIniFile,"settings"); + + //GUID m_adapter_guid_fullscreen + //GUID m_adapter_guid_desktop + //GUID m_adapter_guid_windowed + char str[256]; + GuidToText(&m_adapter_guid_fullscreen, str, sizeof(str)); + WritePrivateProfileString("settings","adapter_guid_fullscreen",str,m_szConfigIniFile); + GuidToText(&m_adapter_guid_desktop, str, sizeof(str)); + WritePrivateProfileString("settings","adapter_guid_desktop",str,m_szConfigIniFile); + GuidToText(&m_adapter_guid_windowed, str, sizeof(str)); + WritePrivateProfileString("settings","adapter_guid_windowed" ,str,m_szConfigIniFile); + + // FONTS + #define WRITE_FONT(n) { \ + WritePrivateProfileString("settings","szFontFace"#n,m_fontinfo[n].szFace,m_szConfigIniFile); \ + WritePrivateProfileInt(m_fontinfo[n].bBold, "bFontBold"#n, m_szConfigIniFile, "settings"); \ + WritePrivateProfileInt(m_fontinfo[n].bItalic,"bFontItalic"#n, m_szConfigIniFile, "settings"); \ + WritePrivateProfileInt(m_fontinfo[n].nSize, "nFontSize"#n, m_szConfigIniFile, "settings"); \ + WritePrivateProfileInt(m_fontinfo[n].bAntiAliased, "bFontAA"#n,m_szConfigIniFile, "settings"); \ + } + WRITE_FONT(0); + WRITE_FONT(1); + WRITE_FONT(2); + WRITE_FONT(3); + #if (NUM_EXTRA_FONTS >= 1) + WRITE_FONT(4); + #endif + #if (NUM_EXTRA_FONTS >= 2) + WRITE_FONT(5); + #endif + #if (NUM_EXTRA_FONTS >= 3) + WRITE_FONT(6); + #endif + #if (NUM_EXTRA_FONTS >= 4) + WRITE_FONT(7); + #endif + #if (NUM_EXTRA_FONTS >= 5) + WRITE_FONT(8); + #endif + + WritePrivateProfileInt(m_start_fullscreen,"start_fullscreen",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_start_desktop ,"start_desktop" ,m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_fake_fullscreen_mode,"fake_fullscreen_mode",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_max_fps_fs,"max_fps_fs",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_max_fps_dm,"max_fps_dm",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_max_fps_w ,"max_fps_w" ,m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_show_press_f1_msg,"show_press_f1_msg",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_allow_page_tearing_w,"allow_page_tearing_w",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_allow_page_tearing_fs,"allow_page_tearing_fs",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_allow_page_tearing_dm,"allow_page_tearing_dm",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_minimize_winamp,"minimize_winamp",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_desktop_show_icons,"desktop_show_icons",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_desktop_textlabel_boxes,"desktop_textlabel_boxes",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_desktop_manual_icon_scoot,"desktop_manual_icon_scoot",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_desktop_555_fix,"desktop_555_fix",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_dualhead_horz,"dualhead_horz",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_dualhead_vert,"dualhead_vert",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_save_cpu,"save_cpu",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_skin,"skin",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_fix_slow_text,"fix_slow_text",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_vj_mode,"vj_mode",m_szConfigIniFile,"settings"); + + //D3DDISPLAYMODE m_fs_disp_mode + WritePrivateProfileInt(m_disp_mode_fs.Width ,"disp_mode_fs_w",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_disp_mode_fs.Height ,"disp_mode_fs_h",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_disp_mode_fs.RefreshRate,"disp_mode_fs_r",m_szConfigIniFile,"settings"); + WritePrivateProfileInt(m_disp_mode_fs.Format ,"disp_mode_fs_f",m_szConfigIniFile,"settings"); + + WritePrivateProfileInt(INT_VERSION ,"version" ,m_szConfigIniFile,"settings"); + WritePrivateProfileInt(INT_SUBVERSION ,"subversion" ,m_szConfigIniFile,"settings"); + + // finally, save the plugin's unique settings: + MyWriteConfig(); + +#endif +} + +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- + +int CPluginShell::PluginRender(unsigned char *pWaveL, unsigned char *pWaveR)//, unsigned char *pSpecL, unsigned char *pSpecR) +{ + // return FALSE here to tell Winamp to terminate the plugin + + if (!m_lpDX || !m_lpDX->m_ready) + { + // note: 'm_ready' will go false when a device reset fatally fails + // (for example, when user resizes window, or toggles fullscreen.) + m_exiting = 1; + return false; // EXIT THE PLUGIN + } + +// if (m_hTextWnd) +// m_lost_focus = ((GetFocus() != GetPluginWindow()) && (GetFocus() != m_hTextWnd)); +// else +// m_lost_focus = (GetFocus() != GetPluginWindow()); + +// if ((m_screenmode==WINDOWED && m_hidden) || +// //(m_screenmode==FULLSCREEN && m_lost_focus) || +// (m_screenmode==WINDOWED && m_resizing) +// ) +// { +// Sleep(30); +// return true; +// } + + // test for lost device + // (this happens when device is fullscreen & user alt-tabs away, + // or when monitor power-saving kicks in) + //HRESULT hr = m_lpDX->m_lpDevice->TestCooperativeLevel(); + //if (hr == D3DERR_DEVICENOTRESET) + //{ + // // device WAS lost, and is now ready to be reset (and come back online): + // CleanUpDX8Stuff(0); + // if (m_lpDX->m_lpDevice->Reset(&m_lpDX->m_d3dpp) != D3D_OK) + // { + // // note: a basic warning messagebox will have already been given. + // // now suggest specific advice on how to regain more video memory: + // if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY) + // SuggestHowToFreeSomeMem(); + // return false; // EXIT THE PLUGIN + // } + // if (!AllocateDX8Stuff()) + // return false; // EXIT THE PLUGIN + //} + //else if (hr != D3D_OK) + //{ + // // device is lost, and not yet ready to come back; sleep. + // Sleep(30); + // return true; + //} + +// if (m_vjd3d8_device) +// { +// HRESULT hr = m_vjd3d8_device->TestCooperativeLevel(); +// if (hr == D3DERR_DEVICENOTRESET) +// { +// RECT c; +// GetClientRect(m_hTextWnd, &c); +// +// POINT p; +// p.x = c.left; +// p.y = c.top; +// if (ClientToScreen(m_hTextWnd, &p)) +// { +// c.left += p.x; +// c.right += p.x; +// c.top += p.y; +// c.bottom += p.y; +// } +// +// CleanUpVJStuff(); +// if (!InitVJStuff(&c)) +// return false; // EXIT THE PLUGIN +// } +// } +// +// if (m_screenmode==DESKTOP) +// { +// PushWindowToJustBeforeDesktop(GetPluginWindow()); +// } + + DoTime(); + AnalyzeNewSound(pWaveL, pWaveR); + AlignWaves(); + + DrawAndDisplay(0); + + EnforceMaxFPS(); + + m_frame++; + + return true; +} + +void CPluginShell::PushWindowToJustBeforeDesktop(HWND h) +{ +#if 0 + // if our window isn't already at the bottom of the Z order, + // freshly send it to HWND_BOTTOM. + + // this usually gives us the Program Manager window: + HWND hWndBottom = GetWindow(h, GW_HWNDLAST); + + // then, bottommost 'normal' window is usually the one just in front of it: + if (hWndBottom == m_hWndProgMan) + hWndBottom = GetWindow(hWndBottom, GW_HWNDPREV); + + if (hWndBottom != h) + { + m_force_accept_WM_WINDOWPOSCHANGING = 1; + SetWindowPos(h, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE); + m_force_accept_WM_WINDOWPOSCHANGING = 0; + } +#endif +} + +void CPluginShell::DrawAndDisplay(int redraw) +{ + int cx = m_vjd3d8_device ? m_nTextWndWidth : m_lpDX->m_client_width; + int cy = m_vjd3d8_device ? m_nTextWndHeight : m_lpDX->m_client_height; +/* + + if (m_lpDDSText) + { + D3DSURFACE_DESC desc; + if (D3D_OK == m_lpDDSText->GetLevelDesc(0, &desc)) + { + cx = min(cx, desc.Width); + cy = min(cy, desc.Height); + } + } +*/ + m_upper_left_corner_y = TEXT_MARGIN; + m_upper_right_corner_y = TEXT_MARGIN; + m_lower_left_corner_y = cy - TEXT_MARGIN; + m_lower_right_corner_y = cy - TEXT_MARGIN; + m_left_edge = TEXT_MARGIN; + m_right_edge = cx - TEXT_MARGIN; + + /* + if (m_screenmode == DESKTOP || m_screenmode == FAKE_FULLSCREEN) + { + // check if taskbar is above plugin window; + // if so, scoot text & icons out of the way. + // [...should always be true for Desktop Mode, + // but it's like this for code simplicity.] + int taskbar_is_above_plugin_window = 1; + HWND h = FindWindow("Shell_TrayWnd", NULL); + while (h) //(..shouldn't be very many windows to iterate through here) + { + h = GetWindow(h, GW_HWNDPREV); + if (h == GetPluginWindow()) + { + taskbar_is_above_plugin_window = 0; + break; + } + } + + if (taskbar_is_above_plugin_window) + { + // respect the taskbar area; make sure the text, desktop icons, etc. + // don't appear underneath it. + //m_upper_left_corner_y += m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top; + //m_upper_right_corner_y += m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top; + //m_lower_left_corner_y -= m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom; + //m_lower_right_corner_y -= m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom; + //m_left_edge += m_lpDX->m_monitor_work_rect.left - m_lpDX->m_monitor_rect.left; + //m_right_edge -= m_lpDX->m_monitor_rect.right - m_lpDX->m_monitor_work_rect.right; + m_lpDX->UpdateMonitorWorkRect(); + m_upper_left_corner_y = max(m_upper_left_corner_y , m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top + TEXT_MARGIN); + m_upper_right_corner_y = max(m_upper_right_corner_y, m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top + TEXT_MARGIN); + m_lower_left_corner_y = min(m_lower_left_corner_y , m_lpDX->m_client_height - (m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom) - TEXT_MARGIN); + m_lower_right_corner_y = min(m_lower_right_corner_y, m_lpDX->m_client_height - (m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom) - TEXT_MARGIN); + m_left_edge = max(m_left_edge , m_lpDX->m_monitor_work_rect.left - m_lpDX->m_monitor_rect.left + TEXT_MARGIN ); + m_right_edge = min(m_right_edge, m_lpDX->m_client_width - (m_lpDX->m_monitor_rect.right - m_lpDX->m_monitor_work_rect.right) + TEXT_MARGIN); + } + } +*/ + //if (D3D_OK==m_lpDX->m_lpDevice->BeginScene()) + { + MyRenderFn(redraw); + + //PrepareFor2DDrawing_B(GetDevice(), GetWidth(), GetHeight()); + + //RenderDesktop(); + //RenderBuiltInTextMsgs(); + //MyRenderUI(&m_upper_left_corner_y, &m_upper_right_corner_y, &m_lower_left_corner_y, &m_lower_right_corner_y, m_left_edge, m_right_edge); + //RenderPlaylist(); + +// if (!m_vjd3d8_device) +// { +// D3DXMATRIX Ortho2D; +// D3DXMatrixOrthoLH(&Ortho2D, 2.0f, -2.0f, 0.0f, 1.0f); +// m_lpDX->m_lpDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); +// +// m_text.DrawNow(); +// } + + // m_lpDX->m_lpDevice->EndScene(); + } +/* + // VJ Mode: + if (m_vjd3d8_device && !m_hidden_textwnd && D3D_OK==m_vjd3d8_device->BeginScene()) + { + if (!m_lpDDSText) + m_vjd3d8_device->Clear(0, 0, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0); + PrepareFor2DDrawing_B(m_vjd3d8_device, m_nTextWndWidth, m_nTextWndHeight); + + D3DXMATRIX Ortho2D; + D3DXMatrixOrthoLH(&Ortho2D, 2.0f, -2.0f, 0.0f, 1.0f); + m_vjd3d8_device->SetTransform(D3DTS_PROJECTION, &Ortho2D); + + m_text.DrawNow(); + + m_vjd3d8_device->EndScene(); + } + + if (m_screenmode == DESKTOP) + { + // window is hidden after creation, until 1st frame is ready to go; + // now that it's ready, we show it. + // see dxcontext::Internal_Init()'s call to SetWindowPos() for the DESKTOP case. + if (!IsWindowVisible(GetPluginWindow())) + ShowWindow(GetPluginWindow(), SW_SHOWNORMAL); + } + + m_lpDX->m_lpDevice->Present(NULL,NULL,NULL,NULL); + if (m_vjd3d8_device && !m_hidden_textwnd) + m_vjd3d8_device->Present(NULL,NULL,NULL,NULL); +*/ +} + +void CPluginShell::EnforceMaxFPS() +{ + int max_fps; + switch(m_screenmode) + { + case WINDOWED: max_fps = m_max_fps_w; break; + case FULLSCREEN: max_fps = m_max_fps_fs; break; + case FAKE_FULLSCREEN: max_fps = m_max_fps_fs; break; + case DESKTOP: max_fps = m_max_fps_dm; break; + } + + if (max_fps <= 0) + return; + + float fps_lo = (float)max_fps; + float fps_hi = (float)max_fps; + + if (m_save_cpu) + { + // Find the optimal lo/hi bounds for the fps + // that will result in a maximum difference, + // in the time for a single frame, of 0.002 seconds - + // the assumed granularity for Sleep(1) - + + // Using this range of acceptable fps + // will allow us to do (sloppy) fps limiting + // using only Sleep(1), and never the + // second half of it: Sleep(0) in a tight loop, + // which sucks up the CPU (whereas Sleep(1) + // leaves it idle). + + // The original equation: + // 1/(max_fps*t1) = 1/(max*fps/t1) - 0.002 + // where: + // t1 > 0 + // max_fps*t1 is the upper range for fps + // max_fps/t1 is the lower range for fps + + float a = 1; + float b = -0.002f * max_fps; + float c = -1.0f; + float det = b*b - 4*a*c; + if (det>0) + { + float t1 = (-b + sqrtf(det)) / (2*a); + //float t2 = (-b - sqrtf(det)) / (2*a); + + if (t1 > 1.0f) + { + fps_lo = max_fps / t1; + fps_hi = max_fps * t1; + // verify: now [1.0f/fps_lo - 1.0f/fps_hi] should equal 0.002 seconds. + // note: allowing tolerance to go beyond these values for + // fps_lo and fps_hi would gain nothing. + } + } + } + + if (m_high_perf_timer_freq.QuadPart > 0) + { + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + + if (m_prev_end_of_frame.QuadPart != 0) + { + int ticks_to_wait_lo = (int)((float)m_high_perf_timer_freq.QuadPart / (float)fps_hi); + int ticks_to_wait_hi = (int)((float)m_high_perf_timer_freq.QuadPart / (float)fps_lo); + int done = 0; + do + { + QueryPerformanceCounter(&t); + + int ticks_passed = (int)(t.QuadPart - m_prev_end_of_frame.QuadPart); + //int ticks_left = ticks_to_wait - ticks_passed; + + if (t.QuadPart < m_prev_end_of_frame.QuadPart) // time wrap + done = 1; + if (ticks_passed >= ticks_to_wait_lo) + done = 1; + + if (!done) + { + // if > 0.01s left, do Sleep(1), which will actually sleep some + // steady amount of up to 2 ms (depending on the OS), + // and do so in a nice way (cpu meter drops; laptop battery spared). + // otherwise, do a few Sleep(0)'s, which just give up the timeslice, + // but don't really save cpu or battery, but do pass a tiny + // amount of time. + + //if (ticks_left > (int)m_high_perf_timer_freq.QuadPart/500) + if (ticks_to_wait_hi - ticks_passed > (int)m_high_perf_timer_freq.QuadPart/100) + Sleep(5); + else if (ticks_to_wait_hi - ticks_passed > (int)m_high_perf_timer_freq.QuadPart/1000) + Sleep(1); + else + for (int i=0; i<10; i++) + Sleep(0); // causes thread to give up its timeslice + } + } + while (!done); + } + + m_prev_end_of_frame = t; + } + else + { + Sleep(1000/max_fps); + } +} + +void CPluginShell::DoTime() +{ + if (m_frame==0) + { + m_fps = 30; + m_time = 0; + m_time_hist_pos = 0; + } + + double new_raw_time; + float elapsed; + + if (m_high_perf_timer_freq.QuadPart != 0) + { + // get high-precision time + // precision: usually from 1..6 us (MICROseconds), depending on the cpu speed. + // (higher cpu speeds tend to have better precision here) + LARGE_INTEGER t; + if (!QueryPerformanceCounter(&t)) + { + m_high_perf_timer_freq.QuadPart = 0; // something went wrong (exception thrown) -> revert to crappy timer + } + else + { + new_raw_time = (double)t.QuadPart; + elapsed = (float) ((new_raw_time - m_last_raw_time)/(double)m_high_perf_timer_freq.QuadPart); + } + } + + if (m_high_perf_timer_freq.QuadPart == 0) + { + // get low-precision time + // precision: usually 1 ms (MILLIsecond) for win98, and 10 ms for win2k. + new_raw_time = (double)(GetTickCount()*0.001); + elapsed = (float)(new_raw_time - m_last_raw_time); + } + + m_last_raw_time = new_raw_time; + int slots_to_look_back = (m_high_perf_timer_freq.QuadPart==0) ? TIME_HIST_SLOTS : TIME_HIST_SLOTS/2; + + m_time += 1.0f/m_fps; + + // timekeeping goals: + // 1. keep 'm_time' increasing SMOOTHLY: (smooth animation depends on it) + // m_time += 1.0f/m_fps; // where m_fps is a bit damped + // 2. keep m_time_hist[] 100% accurate (except for filtering out pauses), + // so that when we look take the difference between two entries, + // we get the real amount of time that passed between those 2 frames. + // m_time_hist[i] = m_last_raw_time + elapsed_corrected; + + if (m_frame > TIME_HIST_SLOTS) + { + if (m_fps < 60.0f) + slots_to_look_back = (int)(slots_to_look_back*(0.1f + 0.9f*(m_fps/60.0f))); + + if (elapsed > 5.0f/m_fps || elapsed > 1.0f || elapsed < 0) + elapsed = 1.0f / 30.0f; + + float old_hist_time = m_time_hist[(m_time_hist_pos - slots_to_look_back + TIME_HIST_SLOTS) % TIME_HIST_SLOTS]; + float new_hist_time = m_time_hist[(m_time_hist_pos - 1 + TIME_HIST_SLOTS) % TIME_HIST_SLOTS] + + elapsed; + + m_time_hist[m_time_hist_pos] = new_hist_time; + m_time_hist_pos = (m_time_hist_pos+1) % TIME_HIST_SLOTS; + + float new_fps = slots_to_look_back / (float)(new_hist_time - old_hist_time); + float damping = (m_high_perf_timer_freq.QuadPart==0) ? 0.93f : 0.87f; + + // damp heavily, so that crappy timer precision doesn't make animation jerky + if (fabsf(m_fps - new_fps) > 3.0f) + m_fps = new_fps; + else + m_fps = damping*m_fps + (1-damping)*new_fps; + } + else + { + float damping = (m_high_perf_timer_freq.QuadPart==0) ? 0.8f : 0.6f; + + if (m_frame < 2) + elapsed = 1.0f / 30.0f; + else if (elapsed > 1.0f || elapsed < 0) + elapsed = 1.0f / m_fps; + + float old_hist_time = m_time_hist[0]; + float new_hist_time = m_time_hist[(m_time_hist_pos - 1 + TIME_HIST_SLOTS) % TIME_HIST_SLOTS] + + elapsed; + + m_time_hist[m_time_hist_pos] = new_hist_time; + m_time_hist_pos = (m_time_hist_pos+1) % TIME_HIST_SLOTS; + + if (m_frame > 0) + { + float new_fps = (m_frame) / (new_hist_time - old_hist_time); + m_fps = damping*m_fps + (1-damping)*new_fps; + } + } + + // Synchronize the audio and video by telling Winamp how many milliseconds we want the audio data, + // before it's actually audible. If we set this to the amount of time it takes to display 1 frame + // (1/fps), the video and audio should be perfectly synchronized. +// if (m_fps < 2.0f) +// mod1.latencyMs = 500; +// else if (m_fps > 125.0f) +// mod1.latencyMs = 8; +// else +// mod1.latencyMs = (int)(1000.0f/m_fps*m_lpDX->m_frame_delay + 0.5f); +} + +void CPluginShell::AnalyzeNewSound(unsigned char *pWaveL, unsigned char *pWaveR) +{ + // we get 512 samples in from XBMC. + // the output of the fft has 'num_frequencies' samples, + // and represents the frequency range 0 hz - 22,050 hz. + // usually, plugins only use half of this output (the range 0 hz - 11,025 hz), + // since >10 khz doesn't usually contribute much. + + int i; + + float temp_wave[2][512]; + + int old_i = 0; + for (i=0; i<512; i++) + { + m_sound.fWaveform[0][i] = (float)((pWaveL[i] ^ 128) - 128); + m_sound.fWaveform[1][i] = (float)((pWaveR[i] ^ 128) - 128); + + // simulating single frequencies from 200 to 11,025 Hz: + //float freq = 1.0f + 11050*(GetFrame() % 100)*0.01f; + //m_sound.fWaveform[0][i] = 10*sinf(i*freq*6.28f/44100.0f); + + // damp the input into the FFT a bit, to reduce high-frequency noise: + temp_wave[0][i] = 0.5f*(m_sound.fWaveform[0][i] + m_sound.fWaveform[0][old_i]); + temp_wave[1][i] = 0.5f*(m_sound.fWaveform[1][i] + m_sound.fWaveform[1][old_i]); + old_i = i; + } + + m_fftobj.time_to_frequency_domain(temp_wave[0], m_sound.fSpectrum[0]); + m_fftobj.time_to_frequency_domain(temp_wave[1], m_sound.fSpectrum[1]); + + // sum (left channel) spectrum up into 3 bands + // [note: the new ranges do it so that the 3 bands are equally spaced, pitch-wise] + float min_freq = 200.0f; + float max_freq = 11025.0f; + float net_octaves = (logf(max_freq/min_freq) / logf(2.0f)); // 5.7846348455575205777914165223593 + float octaves_per_band = net_octaves / 3.0f; // 1.9282116151858401925971388407864 + float mult = powf(2.0f, octaves_per_band); // each band's highest freq. divided by its lowest freq.; 3.805831305510122517035102576162 + // [to verify: min_freq * mult * mult * mult should equal max_freq.] + for (int ch=0; ch<2; ch++) + { + for (int i=0; i<3; i++) + { + // old guesswork code for this: + // float exp = 2.1f; + // int start = (int)(NUM_FREQUENCIES*0.5f*powf(i/3.0f, exp)); + // int end = (int)(NUM_FREQUENCIES*0.5f*powf((i+1)/3.0f, exp)); + // results: + // old range: new range (ideal): + // bass: 0-1097 200-761 + // mids: 1097-4705 761-2897 + // treb: 4705-11025 2897-11025 + int start = (int)(NUM_FREQUENCIES * min_freq*powf(mult, i )/11025.0f); + int end = (int)(NUM_FREQUENCIES * min_freq*powf(mult, i+1)/11025.0f); + if (start < 0) start = 0; + if (end > NUM_FREQUENCIES) end = NUM_FREQUENCIES; + + m_sound.imm[ch][i] = 0; + for (int j=start; j= 10) + { + sum[0] += m_sound.imm[0]; + sum[1] += m_sound.imm[1]; + sum[2] += m_sound.imm[2]; + count++; + } + } + }*/ + + // multiply by long-term, empirically-determined inverse averages: + // (for a trial of 244 songs, 10 seconds each, somewhere in the 2nd or 3rd minute, + // the average levels were: 0.326781557 0.38087377 0.199888934 + for (int ch=0; ch<2; ch++) + { + m_sound.imm[ch][0] /= 0.326781557f;//0.270f; + m_sound.imm[ch][1] /= 0.380873770f;//0.343f; + m_sound.imm[ch][2] /= 0.199888934f;//0.295f; + } + + // do temporal blending to create attenuated and super-attenuated versions + for (int ch=0; ch<2; ch++) + { + for (i=0; i<3; i++) + { + // m_sound.avg[i] + { + float avg_mix; + if (m_sound.imm[ch][i] > m_sound.avg[ch][i]) + avg_mix = AdjustRateToFPS(0.2f, 14.0f, m_fps); + else + avg_mix = AdjustRateToFPS(0.5f, 14.0f, m_fps); + m_sound.avg[ch][i] = m_sound.avg[ch][i]*avg_mix + m_sound.imm[ch][i]*(1-avg_mix); + } + + // m_sound.med_avg[i] + // m_sound.long_avg[i] + { + float med_mix = 0.91f;//0.800f + 0.11f*powf(t, 0.4f); // primarily used for velocity_damping + float long_mix = 0.96f;//0.800f + 0.16f*powf(t, 0.2f); // primarily used for smoke plumes + med_mix = AdjustRateToFPS( med_mix, 14.0f, m_fps); + long_mix = AdjustRateToFPS(long_mix, 14.0f, m_fps); + m_sound.med_avg[ch][i] = m_sound.med_avg[ch][i]*(med_mix ) + m_sound.imm[ch][i]*(1-med_mix ); + m_sound.long_avg[ch][i] = m_sound.long_avg[ch][i]*(long_mix) + m_sound.imm[ch][i]*(1-long_mix); + } + } + } +} + +void CPluginShell::PrepareFor2DDrawing_B(IDirect3DDevice9 *pDevice, int w, int h) +{ + // New 2D drawing area will have x,y coords in the range <-1,-1> .. <1,1> + // +--------+ Y=-1 + // | | + // | screen | Z=0: front of scene + // | | Z=1: back of scene + // +--------+ Y=1 + // X=-1 X=1 + // NOTE: After calling this, be sure to then call (at least): + // 1. SetVertexShader() + // 2. SetTexture(), if you need it + // before rendering primitives! + // Also, be sure your sprites have a z coordinate of 0. + + pDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); + pDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); + pDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); + pDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD ); + pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + pDevice->SetRenderState( D3DRS_FOGENABLE, FALSE ); + pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); +// pDevice->SetRenderState( D3DRS_CLIPPING, TRUE ); + pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); + pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + pDevice->SetRenderState( D3DRS_LOCALVIEWER, FALSE ); + pDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE ); + + pDevice->SetTexture(0, NULL); + pDevice->SetTexture(1, NULL); + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR); + pDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR); + pDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + pDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT ); + pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE ); + + pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + + pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + + // set up for 2D drawing: + { + D3DXMATRIX Ortho2D; + D3DXMATRIX Identity; + + D3DXMatrixOrthoLH(&Ortho2D, w, h, 0.0f, 1.0f); + D3DXMatrixIdentity(&Identity); + + pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); + pDevice->SetTransform(D3DTS_WORLD, &Identity); + pDevice->SetTransform(D3DTS_VIEW, &Identity); + } +} + +void CPluginShell::DrawDarkTranslucentBox(RECT* pr) +{ + // 'pr' is the rectangle that some text will occupy; + // a black box will be drawn around it, plus a bit of extra margin space. +#if 0 + m_text.DrawDarkBox(pr); + + if (m_vjd3d8_device) + return; + + LPDIRECT3DDEVICE8 lpDevice = GetDevice(); + int w = m_lpDX->m_client_width; + int h = m_lpDX->m_client_height; + + lpDevice->SetVertexShader( SIMPLE_VERTEX_FORMAT ); + lpDevice->SetTexture(0, NULL); + + lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); + lpDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); + lpDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + + SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + + // set up a quad + SIMPLEVERTEX verts[4]; + for (int i=0; i<4; i++) + { + verts[i].x = (i%2==0) ? (float)(-w/2 + pr->left ) : + (float)(-w/2 + pr->right ); + verts[i].y = (i/2==0) ? (float)-(-h/2 + pr->bottom) : + (float)-(-h/2 + pr->top ); + verts[i].z = 0; + verts[i].Diffuse = 0xFF000000;// (m_screenmode==DESKTOP) ? 0xE0000000 : 0xD0000000; + } + + lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(SIMPLEVERTEX)); + + // undo unusual state changes: + lpDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); + lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); +#endif +} + +void CPluginShell::RenderBuiltInTextMsgs() +{ +#if 0 + int _show_press_f1_NOW = (m_show_press_f1_msg && m_time < PRESS_F1_DUR); + + { + RECT r; + + if (m_show_help) + { + int y = m_upper_left_corner_y; + + SetRect(&r, 0, 0, GetWidth(), GetHeight()); + m_text.DrawText(m_d3dx_font[HELPSCREEN_FONT], g_szHelp, -1, &r, DT_CALCRECT, 0xFFFFFFFF); + + r.top += m_upper_left_corner_y; + r.left += m_left_edge; + r.right += m_left_edge + PLAYLIST_INNER_MARGIN*2; + r.bottom += m_upper_left_corner_y + PLAYLIST_INNER_MARGIN*2; + DrawDarkTranslucentBox(&r); + + r.top += PLAYLIST_INNER_MARGIN; + r.left += PLAYLIST_INNER_MARGIN; + r.right -= PLAYLIST_INNER_MARGIN; + r.bottom -= PLAYLIST_INNER_MARGIN; + m_text.DrawText(m_d3dx_font[HELPSCREEN_FONT], g_szHelp, -1, &r, 0, 0xFFFFFFFF); + + m_upper_left_corner_y += r.bottom-r.top + PLAYLIST_INNER_MARGIN*3; + } + + // render 'Press F1 for Help' message in lower-right corner: + if (_show_press_f1_NOW) + { + int dx = (int)(160.0f * powf(m_time/(float)(PRESS_F1_DUR), (float)(PRESS_F1_EXP))); + SetRect(&r, m_left_edge, m_lower_right_corner_y - GetFontHeight(DECORATIVE_FONT), m_right_edge + dx, m_lower_right_corner_y); + m_lower_right_corner_y -= m_text.DrawText(m_d3dx_font[DECORATIVE_FONT], PRESS_F1_MSG, &r, DT_RIGHT, 0xFFFFFFFF); + } + } +#endif +} + +void CPluginShell::RenderPlaylist() +{ +#if 0 + // draw playlist: + if (m_show_playlist) + { + RECT r; + int nSongs = SendMessage(m_hWndWinamp,WM_USER, 0, 124); + int now_playing = SendMessage(m_hWndWinamp,WM_USER, 0, 125); + + if (nSongs <= 0) + { + m_show_playlist = 0; + } + else + { + int playlist_vert_pixels = m_lower_left_corner_y - m_upper_left_corner_y; + int disp_lines = min(MAX_SONGS_PER_PAGE, (playlist_vert_pixels - PLAYLIST_INNER_MARGIN*2) / GetFontHeight(PLAYLIST_FONT)); + int total_pages = (nSongs) / disp_lines; + + if (disp_lines<=0) + return; + + // apply PgUp/PgDn keypresses since last time + m_playlist_pos -= m_playlist_pageups * disp_lines; + m_playlist_pageups = 0; + + if (m_playlist_pos < 0) + m_playlist_pos = 0; + if (m_playlist_pos >= nSongs) + m_playlist_pos = nSongs-1; + + // NOTE: 'dwFlags' is used for both DDRAW and DX8 + DWORD dwFlags = DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS; + DWORD color; + + int cur_page = (m_playlist_pos) / disp_lines; + int cur_line = (m_playlist_pos + disp_lines - 1) % disp_lines; + int new_top_idx = cur_page * disp_lines; + int new_btm_idx = new_top_idx + disp_lines; + char buf[1024]; + + // ask winamp for the song names, but DO IT BEFORE getting the DC, + // otherwise vaio will crash (~DDRAW port). + if (m_playlist_top_idx != new_top_idx || + m_playlist_btm_idx != new_btm_idx) + { + for (int i=0; im_client_width - TEXT_MARGIN*2 - PLAYLIST_INNER_MARGIN*2); + + for (int i=0; i0) + m_playlist_width_pixels = max(m_playlist_width_pixels, w); + } + else + { + m_playlist[i][0] = 0; + } + } + + if (m_playlist_width_pixels == 0 || + m_playlist_width_pixels > max_w) + m_playlist_width_pixels = max_w; + } + + int start = max(0, (cur_page )*disp_lines); + int end = min(nSongs, (cur_page+1)*disp_lines); + + // draw dark box around where the playlist will go: + + RECT r; + r.top = m_upper_left_corner_y; + r.left = m_left_edge; + r.right = m_left_edge + m_playlist_width_pixels + PLAYLIST_INNER_MARGIN*2; + r.bottom = m_upper_left_corner_y + (end-start)*GetFontHeight(PLAYLIST_FONT) + PLAYLIST_INNER_MARGIN*2; + DrawDarkTranslucentBox(&r); + + //m_d3dx_font[PLAYLIST_FONT]->Begin(); + + // draw playlist text + int y = m_upper_left_corner_y + PLAYLIST_INNER_MARGIN; + for (int i=start; iGetBitDepth() == 8) + color = (i==m_playlist_pos) ? + (i==now_playing ? 0xFFFFFFFF : 0xFFFFFFFF) : + (i==now_playing ? 0xFFFFFFFF : 0xFF707070); + else + color = (i==m_playlist_pos) ? + (i==now_playing ? PLAYLIST_COLOR_BOTH : PLAYLIST_COLOR_HILITE_TRACK) : + (i==now_playing ? PLAYLIST_COLOR_PLAYING_TRACK : PLAYLIST_COLOR_NORMAL); + + y += m_text.DrawText(GetFont(PLAYLIST_FONT), m_playlist[i-start], -1, &r, dwFlags, color); + } + + //m_d3dx_font[PLAYLIST_FONT]->End(); + } + } +#endif +} + +void CPluginShell::SuggestHowToFreeSomeMem() +{ +#if 0 + // This function is called when the plugin runs out of video memory; + // it lets you show a messagebox to the user so you can (intelligently) + // suggest how to free up some video memory, based on what settings + // they've chosen. + + char str[1024]; + + if (m_lpDX->m_current_mode.multisamp != D3DMULTISAMPLE_NONE) + { + if (m_lpDX->m_current_mode.screenmode == WINDOWED) + sprintf(str, + "To free up some memory, please RESTART WINAMP, then return\r" + " to the plugin's config panel and try setting your\r" + " WINDOWED MODE MULTISAMPLING back to 'NONE.'\r" + "\r" + "Then try running the plugin again." + ); + else if (m_lpDX->m_current_mode.screenmode == FAKE_FULLSCREEN) + sprintf(str, + "To free up some memory, please RESTART WINAMP, then return\r" + " to the plugin's config panel and try setting your\r" + " FAKE FULLSCREEN MODE MULTISAMPLING back to 'NONE.'\r" + "\r" + "Then try running the plugin again." + ); + else + sprintf(str, + "To free up some memory, please RESTART WINAMP, then return\r" + " to the plugin's config panel and try setting your\r" + " FULLSCREEN MODE MULTISAMPLING back to 'NONE.'\r" + "\r" + "Then try running the plugin again." + ); + } + else + if (m_lpDX->m_current_mode.screenmode == FULLSCREEN) // true fullscreen + sprintf(str, + "To free up some video memory, try the following:\r" + "\r" + "1. Try closing all other applications that might be using video memory, especially:\r" + "\r" + " * WINDOWS MEDIA PLAYER\r" + " * any video conferencing software, such as NETMEETING\r" + " * any DVD playback, TV tuner, or TV capture software\r" + " * any video editing software\r" + " * any software that uses Overlays, such as Drempels Desktop\r" + " * any audio dictation software, such as Dragon NaturallySpeaking\r" + " * any other 3D programs currently running\r" + "\r" + "2. Also try returning to the config panel (ALT+K) and selecting a display mode\r" + " that uses less video memory. 16-bit display modes use half as much memory\r" + " as 32-bit display modes, and lower-resolution display modes (such as 640 x 480)\r" + " use proportionally less video memory.\r" + "\r" + "After making these changes, please RESTART WINAMP before trying to run\r" + "the plugin again.\r" + ); + else // windowed, desktop mode, or fake fullscreen + sprintf(str, + "To free up some video memory, try the following:\r" + "\r" + "1. Try closing all other applications that might be using video memory, especially:\r" + "\r" + " * WINDOWS MEDIA PLAYER\r" + " * any video conferencing software, such as NETMEETING\r" + " * any DVD playback, TV tuner, or TV capture software\r" + " * any video editing software\r" + " * any software that uses Overlays, such as Drempels Desktop\r" + " * any audio dictation software, such as Dragon NaturallySpeaking\r" + " * any other 3D programs currently running\r" + "\r" + "2. Also try changing your Windows display mode to a lesser bit depth\r" + " (i.e. 16-bit color), or a smaller resolution.\r" + "\r" + "After making these changes, please RESTART WINAMP before trying to run\r" + "the plugin again.\r" + ); + + MessageBox(m_lpDX->GetHwnd(), str, "SUGGESTION", MB_OK|MB_SETFOREGROUND|MB_TOPMOST); +#endif +} + +LRESULT CALLBACK CPluginShell::WindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + CPluginShell* p = (CPluginShell*)GetWindowLong(hWnd,GWL_USERDATA); + if (p) + return p->PluginShellWindowProc(hWnd, uMsg, wParam, lParam); + else + return DefWindowProc(hWnd, uMsg, wParam, lParam); +#endif + return 0; +} + + +LRESULT CPluginShell::PluginShellWindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + SHORT mask = 1 << (sizeof(SHORT)*8 - 1); + //bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0; + bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0; + //bool bAltHeldDown: most keys come in under WM_SYSKEYDOWN when ALT is depressed. + + int i; + + #ifdef _DEBUG + if (uMsg != WM_MOUSEMOVE && + uMsg != WM_NCHITTEST && + uMsg != WM_SETCURSOR && + uMsg != WM_COPYDATA && + uMsg != WM_USER) + { + char caption[256] = "WndProc: frame 0, "; + if (m_frame > 0) + { + float time = m_time; + int hours = (int)(time/3600); + time -= hours*3600; + int minutes = (int)(time/60); + time -= minutes*60; + int seconds = (int)time; + time -= seconds; + int dsec = (int)(time*100); + sprintf(caption, "WndProc: frame %d, t=%dh:%02dm:%02d.%02ds, ", m_frame, hours, minutes, seconds, dsec); + } + OutputDebugMessage(caption, hWnd, uMsg, wParam, lParam); + } + #endif + + switch (uMsg) + { + + case WM_USER: + if (m_screenmode == DESKTOP) + { + // this function resides in vms_desktop.dll; + // its response will come later, via the WM_COPYDATA + // message (See below). + getItemData(wParam); + return 0; + } + break; + + case WM_COPYDATA: + if (m_screenmode == DESKTOP) + { + // this message is vms_desktop.dll's response to + // our call to getItemData(). + PCOPYDATASTRUCT c = (PCOPYDATASTRUCT)lParam; + if (c && (c->cbData % sizeof(icon_t) == 0)) + { + icon_t *pNewIcons = (icon_t*)c->lpData; + + EnterCriticalSection(&m_desktop_cs); + + if (m_desktop_icon_state == 1 && (c->dwData & 0x80000000) ) // if doing a total refresh... + { + // ...we build the list from zero + int len = c->dwData & 0xFFFF; + for (int i=0; idwData & 0x80000000) ) + { + // otherwise, we alter existing things in the list: + std::list::iterator p; + int start = c->dwData & 0xFFFF; + int len = c->dwData >> 16; + + int i = 0; + for (p = m_icon_list.begin(); p != m_icon_list.end() && ix = pNewIcons[i-start].x; + p->y = pNewIcons[i-start].y; + memcpy(p->name, pNewIcons[i-start].name, sizeof(p->name)); + memcpy(p->pidl, pNewIcons[i-start].pidl, sizeof(p->pidl)); + i++; + } + + m_desktop_icon_state = 2; + m_desktop_icon_update_frame = GetFrame(); + } + + LeaveCriticalSection(&m_desktop_cs); + } + + return 0; + } + break; + + case WM_ERASEBKGND: + // Repaint window when song is paused and image needs to be repainted: + if (SendMessage(m_hWndWinamp,WM_USER,0,104)!=1 && m_lpDX && m_lpDX->m_lpDevice) // WM_USER/104 return codes: 1=playing, 3=paused, other=stopped + { + m_lpDX->m_lpDevice->Present(NULL,NULL,NULL,NULL); + return 0; + } + break; + + case WM_WINDOWPOSCHANGING: + if ( + m_screenmode == DESKTOP + && (!m_force_accept_WM_WINDOWPOSCHANGING) + && m_lpDX && m_lpDX->m_ready + ) + { + // unless we requested it ourselves or it's init time, + // prevent the fake desktop window from moving around + // in the Z order! (i.e., keep it on the bottom) + + // without this code, when you click on the 'real' desktop + // in a multimon setup, any windows that are overtop of the + // 'fake' desktop will flash, since they'll be covered + // up by the fake desktop window (but then shown again on + // the next frame, when we detect that the fake desktop + // window isn't on bottom & send it back to the bottom). + + LPWINDOWPOS pwp = (LPWINDOWPOS)lParam; + if (pwp) + pwp->flags |= SWP_NOOWNERZORDER | SWP_NOZORDER; + } + if (m_screenmode==WINDOWED && m_lpDX && m_lpDX->m_ready && m_lpDX->m_current_mode.m_skin) + m_lpDX->SaveWindow(); + break; + + case WM_NCACTIVATE: + // *Very Important Handler!* + // -Without this code, the app would not work properly when running in true + // fullscreen mode on multiple monitors; it would auto-minimize whenever the + // user clicked on a window in another display. + if (wParam == 0 && + m_screenmode == FULLSCREEN && + m_frame > 0 && + !m_exiting && + m_lpDX && + m_lpDX->m_ready + && m_lpDX->m_lpD3D && + m_lpDX->m_lpD3D->GetAdapterCount() > 1 && + m_hTextWnd==NULL // important!; if text window exists on diff. monitor, DX8 knows there are multiple monitors, and we don't need to worry about the app auto-minimizing when somebody clicks on another monitor; but if there is no 2nd device (~text window), it does its auto-minimize thing. + ) + { + return 0; + } + break; + + case WM_DESTROY: + // note: don't post quit message here if the window is being destroyed + // and re-created on a switch between windowed & FAKE fullscreen modes. + if (!m_lpDX->TempIgnoreDestroyMessages()) + { + // this is a final exit, and not just destroy-then-recreate-the-window. + // so, flag DXContext so it knows that someone else + // will take care of destroying the window! + m_lpDX->OnTrulyExiting(); + PostQuitMessage(0); + } + return FALSE; + break; + + case WM_SIZE: + // clear or set activity flag to reflect focus + if (m_lpDX && m_lpDX->m_ready && m_screenmode==WINDOWED && !m_resizing) + { + m_hidden = (SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam) ? TRUE : FALSE; + + if (SIZE_MAXIMIZED==wParam || SIZE_RESTORED==wParam) // the window has been maximized or restored + OnUserResizeWindow(); + } + break; + + case WM_ENTERSIZEMOVE: + m_resizing = 1; + break; + + case WM_EXITSIZEMOVE: + if( m_lpDX && m_lpDX->m_ready && m_screenmode==WINDOWED ) + OnUserResizeWindow(); + m_resizing = 0; + break; + + case WM_GETMINMAXINFO: + { + // don't let the window get too small + MINMAXINFO* p = (MINMAXINFO*)lParam; + if (p->ptMinTrackSize.x < 64) + p->ptMinTrackSize.x = 64; + p->ptMinTrackSize.y = p->ptMinTrackSize.x*3/4; + } + return 0; + + case WM_MOUSEMOVE: + if (m_screenmode==DESKTOP && (m_desktop_dragging==1 || m_desktop_box==1)) + { + m_desktop_drag_curpos.x = LOWORD(lParam); + m_desktop_drag_curpos.y = HIWORD(lParam); + if (m_desktop_box==1) + { + // update selection based on box coords + RECT box, temp; + box.left = min(m_desktop_drag_curpos.x, m_desktop_drag_startpos.x); + box.right = max(m_desktop_drag_curpos.x, m_desktop_drag_startpos.x); + box.top = min(m_desktop_drag_curpos.y, m_desktop_drag_startpos.y); + box.bottom = max(m_desktop_drag_curpos.y, m_desktop_drag_startpos.y); + + std::list::iterator p; + for (p = m_icon_list.begin(); p != m_icon_list.end(); p++) + { + p->selected = 0; + + if (IntersectRect(&temp, &box, &p->label_rect)) + p->selected = 1; + else if (IntersectRect(&temp, &box, &p->icon_rect)) + p->selected = 1; + } + } + + // repaint window manually, if winamp is paused + if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1) + { + PushWindowToJustBeforeDesktop(GetPluginWindow()); + DrawAndDisplay(1); + } + + //return 0; + } + break; + + case WM_LBUTTONUP: + if (m_screenmode==DESKTOP) + { + if (m_desktop_dragging) + { + m_desktop_dragging = 0; + + // move selected item(s) to new cursor position + int dx = LOWORD(lParam) - m_desktop_drag_startpos.x; + int dy = HIWORD(lParam) - m_desktop_drag_startpos.y; + + if (dx!=0 || dy!=0) + { + int idx=0; + std::list::iterator p; + for (p = m_icon_list.begin(); p != m_icon_list.end(); p++) + { + if (p->selected) + { + SendMessage(m_hWndDesktopListView, LVM_SETITEMPOSITION, idx, MAKELPARAM(p->x + dx, p->y + dy)); + p->x += dx; + p->y += dy; + } + idx++; + } + } + + // repaint window manually, if winamp is paused + if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1) + { + PushWindowToJustBeforeDesktop(GetPluginWindow()); + DrawAndDisplay(1); + } + } + + if (m_desktop_box) + { + m_desktop_box = 0; + + // repaint window manually, if winamp is paused + if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1) + { + PushWindowToJustBeforeDesktop(GetPluginWindow()); + DrawAndDisplay(1); + } + } + + //return 0; + } + break; + + + case WM_USER+1666: + if (wParam == 1 && lParam == 15) + { + if (m_screenmode == FULLSCREEN || m_screenmode == FAKE_FULLSCREEN) + ToggleFullScreen(); + } + return 0; + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + // Toggle between Fullscreen and Windowed modes on double-click + // note: this requires the 'CS_DBLCLKS' windowclass style! + if (m_screenmode != DESKTOP) + { + SetFocus(hWnd); + if (uMsg==WM_LBUTTONDBLCLK && m_frame>0) + { + ToggleFullScreen(); + return 0; + } + } + else + { + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + int done = 0; + + for (int pass=0; pass<2 && !done; pass++) + { + std::list::iterator p; + for (p = m_icon_list.begin(); p != m_icon_list.end(); p++) + { + RECT *pr = (pass==0) ? &p->icon_rect : &p->label_rect; + int bottom_extend = (pass==0) ? 3 : 0; // accepts clicks in the 3-pixel gap between the icon and the text label. + if (pt.x >= pr->left && + pt.x <= pr->right && + pt.y >= pr->top && + pt.y <= pr->bottom + bottom_extend) + { + switch(uMsg) + { + case WM_RBUTTONUP: + //pt.x += m_lpDX->m_monitor_rect.left; + //pt.y += m_lpDX->m_monitor_rect.top; + DoExplorerMenu(GetPluginWindow(), (LPITEMIDLIST)p->pidl, pt); + break; + case WM_LBUTTONDBLCLK: + { + char buf[MAX_PATH]; + sprintf(buf, "%s\\%s", m_szDesktopFolder, p->name); + ExecutePidl((LPITEMIDLIST)p->pidl, buf, m_szDesktopFolder, GetPluginWindow()); + } + break; + case WM_LBUTTONDOWN: + m_desktop_dragging = 1; + memcpy(m_desktop_drag_pidl, p->pidl, sizeof(m_desktop_drag_pidl)); + m_desktop_drag_startpos.x = LOWORD(lParam); + m_desktop_drag_startpos.y = HIWORD(lParam); + m_desktop_drag_curpos.x = LOWORD(lParam); + m_desktop_drag_curpos.y = HIWORD(lParam); + if (!(wParam & MK_CONTROL)) // if CTRL not held down + { + if (!p->selected) + { + DeselectDesktop(); + p->selected = 1; + } + } + else + { + p->selected = 1-p->selected; + } + break; + case WM_RBUTTONDOWN: + DeselectDesktop(); + p->selected = 1; + break; + } + + done = 1; + break; + } + } + } + + if (!done) + { + // deselect all, unless they're CTRL+clicking and missed an icon. + if (uMsg!=WM_LBUTTONDOWN || !(wParam & MK_CONTROL)) + DeselectDesktop(); + + if (uMsg==WM_RBUTTONUP)// || uMsg==WM_RBUTTONDOWN) + { + // note: can't use GetMenu and TrackPopupMenu here because the hwnd param to TrackPopupMenu must belong to current application. + + // (before sending coords to desktop window, xform them into its client coords:) + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + ScreenToClient(m_hWndDesktopListView, &pt); + lParam = MAKELPARAM(pt.x + m_lpDX->m_monitor_rect.left, pt.y + m_lpDX->m_monitor_rect.top); + + PostMessage(m_hWndDesktopListView, uMsg, wParam, lParam); + //PostMessage(m_hWndDesktopListView, WM_CONTEXTMENU, (WPARAM)m_hWndDesktopListView, lParam); + } + else if (uMsg==WM_LBUTTONDOWN) + { + m_desktop_box = 1; + m_desktop_drag_startpos.x = LOWORD(lParam); + m_desktop_drag_startpos.y = HIWORD(lParam); + m_desktop_drag_curpos.x = LOWORD(lParam); + m_desktop_drag_curpos.y = HIWORD(lParam); + } + } + + // repaint window manually, if winamp is paused + if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1) + { + PushWindowToJustBeforeDesktop(GetPluginWindow()); + DrawAndDisplay(1); + } + + //return 0; + } + break; + + /* + case WM_SETFOCUS: + // note: this msg never comes in when embedwnd is used, but that's ok, because that's only + // in Windowed mode, and m_lost_focus only makes us sleep when fullscreen. + m_lost_focus = 0; + break; + + case WM_KILLFOCUS: + // note: this msg never comes in when embedwnd is used, but that's ok, because that's only + // in Windowed mode, and m_lost_focus only makes us sleep when fullscreen. + m_lost_focus = 1; + break; + */ + + case WM_SETCURSOR: + if ( + (m_screenmode == FULLSCREEN) || + (m_screenmode == FAKE_FULLSCREEN && m_lpDX && m_lpDX->m_fake_fs_covers_all) + ) + { + // hide the cursor + SetCursor(NULL); + return TRUE; // prevent Windows from setting cursor to window class cursor + } + break; + + case WM_NCHITTEST: + // Prevent the user from selecting the menu in fullscreen mode + if (m_screenmode != WINDOWED) + return HTCLIENT; + break; + + case WM_SYSCOMMAND: + // Prevent *moving/sizing* and *entering standby mode* when in fullscreen mode + switch( wParam ) + { + case SC_MOVE: + case SC_SIZE: + case SC_MAXIMIZE: + case SC_KEYMENU: + if (m_screenmode != WINDOWED) + return 1; + break; + case SC_MONITORPOWER: + if (m_screenmode == FULLSCREEN || m_screenmode == FAKE_FULLSCREEN) + return 1; + break; + } + break; + + case WM_CONTEXTMENU: + // launch popup context menu. see handler for WM_COMMAND also. + if (m_screenmode == DESKTOP) + { + // note: execution should never reach this point, + // because we don't pass WM_RBUTTONUP to DefWindowProc + // when in desktop mode! + return 0; + } + else if (m_screenmode == WINDOWED) // context menus only allowed in ~windowed modes + { + TrackPopupMenuEx( m_context_menu, TPM_VERTICAL, LOWORD(lParam), HIWORD(lParam), hWnd, NULL ); + return 0; + } + break; + + case WM_COMMAND: + // handle clicks on items on context menu. + if (m_screenmode == WINDOWED) + { + switch( LOWORD(wParam) ) + { + case ID_QUIT: + m_exiting = 1; + PostMessage(hWnd, WM_CLOSE, 0, 0); + return 0; + case ID_GO_FS: + if (m_frame > 0) + ToggleFullScreen(); + return 0; + case ID_DESKTOP_MODE: + if (m_frame > 0) + ToggleDesktop(); + return 0; + case ID_SHOWHELP: + ToggleHelp(); + return 0; + case ID_SHOWPLAYLIST: + TogglePlaylist(); + return 0; + } + // then allow the plugin to override any command: + if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0) + return 0; + } + break; + + /* + KEY HANDLING: the basic idea: + -in all cases, handle or capture: + -ZXCVBRS, zxcvbrs + -also make sure it's case-insensitive! (lowercase come through only as WM_CHAR; uppercase come in as both) + -(ALT+ENTER) + -(F1, ESC, UP, DN, Left, Right, SHIFT+l/r) + -(P for playlist) + -when playlist showing: steal J, HOME, END, PGUP, PGDN, UP, DOWN, ESC + -(BLOCK J, L) + -when integrated with winamp (using embedwnd), also handle these keys: + -j, l, L, CTRL+L [windowed mode only!] + -CTRL+P, CTRL+D + -CTRL+TAB + -ALT-E + -ALT+F (main menu) + -ALT+3 (id3) + */ + + case WM_SYSKEYDOWN: + if (wParam==VK_RETURN && m_frame > 0) + { + ToggleFullScreen(); + return 0; + } + // if in embedded mode (using winamp skin), pass ALT+ keys on to winamp + // ex: ALT+E, ALT+F, ALT+3... + if (m_screenmode==WINDOWED && m_lpDX->m_current_mode.m_skin) + return PostMessage(m_hWndWinamp, uMsg, wParam, lParam); // force-pass to winamp; required for embedwnd + break; + + case WM_SYSKEYUP: + if (m_screenmode==WINDOWED && m_lpDX->m_current_mode.m_skin) + return PostMessage(m_hWndWinamp, uMsg, wParam, lParam); // force-pass to winamp; required for embedwnd + break; + + case WM_SYSCHAR: + if ((wParam=='d' || wParam=='D') && m_frame > 0) + { + ToggleDesktop(); + return 0; + } + break; + + case WM_CHAR: + // if playlist is showing, steal p/j keys from the plugin: + if (m_show_playlist) + { + switch(wParam) + { + /* + case 'p': + case 'P': + TogglePlaylist(); + return 0;*/ + case 'j': + case 'J': + m_playlist_pos = SendMessage(m_hWndWinamp,WM_USER, 0, 125); + return 0; + default: + { + int nSongs = SendMessage(m_hWndWinamp,WM_USER, 0, 124); + int found = 0; + int orig_pos = m_playlist_pos; + int inc = (wParam>='A' && wParam<='Z') ? -1 : 1; + while (1) + { + if (inc==1 && m_playlist_pos >= nSongs-1) + break; + if (inc==-1 && m_playlist_pos <= 0) + break; + + m_playlist_pos += inc; + + char buf[32]; + strncpy(buf, (char*)SendMessage(m_hWndWinamp, WM_USER, m_playlist_pos, 212), 31); + buf[31] = 0; + + // remove song # and period from beginning + char *p = buf; + while (*p >= '0' && *p <= '9') p++; + if (*p == '.' && *(p+1) == ' ') + { + p += 2; + int pos = 0; + while (*p != 0) + { + buf[pos++] = *p; + p++; + } + buf[pos++] = 0; + } + + int wParam2 = (wParam>='A' && wParam<='Z') ? (wParam + 'a'-'A') : (wParam + 'A'-'a'); + if (buf[0]==wParam || buf[0]==wParam2) + { + found = 1; + break; + } + } + + if (!found) + m_playlist_pos = orig_pos; + } + return 0; + } + } + + // then allow the plugin to override any keys: + if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0) + return 0; + + // finally, default key actions: + switch(wParam) + { + // WINAMP PLAYBACK CONTROL KEYS: + case 'z': + case 'Z': + PostMessage(m_hWndWinamp,WM_COMMAND,40044,0); + return 0; + case 'x': + case 'X': + PostMessage(m_hWndWinamp,WM_COMMAND,40045,0); + return 0; + case 'c': + case 'C': + PostMessage(m_hWndWinamp,WM_COMMAND,40046,0); + return 0; + case 'v': + case 'V': + PostMessage(m_hWndWinamp,WM_COMMAND,40047,0); + return 0; + case 'b': + case 'B': + PostMessage(m_hWndWinamp,WM_COMMAND,40048,0); + return 0; + case 's': + case 'S': + //if (SendMessage(m_hWndWinamp,WM_USER,0,250)) + // sprintf(m_szUserMessage, "shuffle is now OFF"); // shuffle was on + //else + // sprintf(m_szUserMessage, "shuffle is now ON"); // shuffle was off + + // toggle shuffle + PostMessage(m_hWndWinamp,WM_COMMAND,40023,0); + return 0; + case 'r': + case 'R': + // toggle repeat + PostMessage(m_hWndWinamp,WM_COMMAND,40022,0); + return 0; + case 'p': + case 'P': + TogglePlaylist(); + return 0; + case 'l': + // note that this is actually correct; when you hit 'l' from the + // MAIN winamp window, you get an "open files" dialog; when you hit + // 'l' from the playlist editor, you get an "add files to playlist" dialog. + // (that sends IDC_PLAYLIST_ADDMP3==1032 to the playlist, which we can't + // do from here.) + PostMessage(m_hWndWinamp,WM_COMMAND,40029,0); + return 0; + case 'L': + PostMessage(m_hWndWinamp,WM_COMMAND,40187,0); + return 0; + case 'j': + PostMessage(m_hWndWinamp,WM_COMMAND,40194,0); + return 0; + } + + return 0;//DefWindowProc(hWnd,uMsg,wParam,lParam); + break; // end case WM_CHAR + + case WM_KEYUP: + + // allow the plugin to override any keys: + if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0) + return 0; + + /* + switch(wParam) + { + case VK_SOMETHING: + ... + break; + } + */ + + return 0; + break; + + case WM_KEYDOWN: + if (m_show_playlist) + { + switch(wParam) + { + case VK_ESCAPE: + m_show_playlist = 0; + return 0; + + case VK_UP: + { + int nRepeat = lParam & 0xFFFF; + if (GetKeyState(VK_SHIFT) & mask) + m_playlist_pos -= 10*nRepeat; + else + m_playlist_pos -= nRepeat; + } + return 0; + + case VK_DOWN: + { + int nRepeat = lParam & 0xFFFF; + if (GetKeyState(VK_SHIFT) & mask) + m_playlist_pos += 10*nRepeat; + else + m_playlist_pos += nRepeat; + } + return 0; + + case VK_HOME: + m_playlist_pos = 0; + return 0; + + case VK_END: + m_playlist_pos = SendMessage(m_hWndWinamp,WM_USER, 0, 124) - 1; + return 0; + + case VK_PRIOR: + if (GetKeyState(VK_SHIFT) & mask) + m_playlist_pageups += 10; + else + m_playlist_pageups++; + return 0; + + case VK_NEXT: + if (GetKeyState(VK_SHIFT) & mask) + m_playlist_pageups -= 10; + else + m_playlist_pageups--; + return 0; + + case VK_RETURN: + SendMessage(m_hWndWinamp,WM_USER, m_playlist_pos, 121); // set sel + SendMessage(m_hWndWinamp,WM_COMMAND, 40045, 0); // play it + return 0; + } + } + + // allow the plugin to override any keys: + if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0) + return 0; + + switch(wParam) + { + case VK_F1: + m_show_press_f1_msg = 0; + ToggleHelp(); + return 0; + + case VK_ESCAPE: + if (m_show_help) + ToggleHelp(); + else + { + if (m_screenmode == FAKE_FULLSCREEN || m_screenmode == FULLSCREEN) + { + ToggleFullScreen(); + } + else if (m_screenmode == DESKTOP) + { + ToggleDesktop(); + } + // exit the program on escape + //m_exiting = 1; + //PostMessage(hWnd, WM_CLOSE, 0, 0); + } + return 0; + + case VK_UP: + // increase volume + { + int nRepeat = lParam & 0xFFFF; + for (i=0; im_current_mode.m_skin) + { + if ( bCtrlHeldDown && ((wParam >= 'A' && wParam <= 'Z') || wParam==VK_TAB) ) + { + PostMessage(m_hWndWinamp, uMsg, wParam, lParam); + return 0; + } + } + return 0; + } + + return 0; + break; + } + + return MyWindowProc(hWnd, uMsg, wParam, lParam);//DefWindowProc(hWnd, uMsg, wParam, lParam); + //return 0L; +#endif + return 0; +} + +LRESULT CALLBACK CPluginShell::DesktopWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + CPluginShell* p = (CPluginShell*)GetWindowLong(hWnd,GWL_USERDATA); + if (p) + return p->PluginShellDesktopWndProc(hWnd, uMsg, wParam, lParam); + else + return DefWindowProc(hWnd, uMsg, wParam, lParam); +#endif + return 0; +} + +LRESULT CPluginShell::PluginShellDesktopWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + //#ifdef _DEBUG + // OutputDebugMessage("kbfocus", hWnd, uMsg, wParam, lParam); + //#endif + + switch (uMsg) + { + case WM_KEYDOWN: + case WM_KEYUP: + case WM_CHAR: + case WM_SYSCHAR: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + //PostMessage(GetPluginWindow(), uMsg, wParam, lParam); + PluginShellWindowProc(GetPluginWindow(), uMsg, wParam, lParam); + return 0; + break; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +#endif + return 0; +} + +void CPluginShell::AlignWaves() +{ + // align waves, using recursive (mipmap-style) least-error matching + // note: NUM_WAVEFORM_SAMPLES must be between 32 and 512. + + int align_offset[2] = { 0, 0 }; + +#if (NUM_WAVEFORM_SAMPLES < 512) // [don't let this code bloat our DLL size if it's not going to be used] + + int nSamples = NUM_WAVEFORM_SAMPLES; + + #define MAX_OCTAVES 10 + + int octaves = floorf(logf(512-nSamples)/logf(2.0f)); + if (octaves < 4) + return; + if (octaves > MAX_OCTAVES) + octaves = MAX_OCTAVES; + + for (int ch=0; ch<2; ch++) + { + // only worry about matching the lower 'nSamples' samples + float temp_new[MAX_OCTAVES][512]; + float temp_old[MAX_OCTAVES][512]; + static float temp_weight[MAX_OCTAVES][512]; + static int first_nonzero_weight[MAX_OCTAVES]; + static int last_nonzero_weight[MAX_OCTAVES]; + int spls[MAX_OCTAVES]; + int space[MAX_OCTAVES]; + + memcpy(temp_new[0], m_sound.fWaveform[ch], sizeof(float)*512); + memcpy(temp_old[0], &m_oldwave[ch][m_prev_align_offset[ch]], sizeof(float)*nSamples); + spls[0] = 512; + space[0] = 512 - nSamples; + + // potential optimization: could reuse (instead of recompute) mip levels for m_oldwave[2][]? + for (int octave=1; octave1) temp_weight[octave][n] = 1; + if (temp_weight[octave][n]<0) temp_weight[octave][n] = 0; + } + + int n = 0; + while (temp_weight[octave][n] == 0 && n < compare_samples) + n++; + first_nonzero_weight[octave] = n; + + n = compare_samples-1; + while (temp_weight[octave][n] == 0 && n >= 0) + n--; + last_nonzero_weight[octave] = n; + } + } + + int n1 = 0; + int n2 = space[octaves-1]; + for (int octave = octaves-1; octave>=0; octave--) + { + // for example: + // space[octave] == 4 + // spls[octave] == 36 + // (so we test 32 samples, w/4 offsets) + int compare_samples = spls[octave]-space[octave]; + + int lowest_err_offset = -1; + float lowest_err_amount = 0; + for (int n=n1; n0) + err_sum += x; + else + err_sum -= x; + } + + if (lowest_err_offset == -1 || err_sum < lowest_err_amount) + { + lowest_err_offset = n; + lowest_err_amount = err_sum; + } + } + + // now use 'lowest_err_offset' to guide bounds of search in next octave: + // space[octave] == 8 + // spls[octave] == 72 + // -say 'lowest_err_offset' was 2 + // -that corresponds to samples 4 & 5 of the next octave + // -also, expand about this by 2 samples? YES. + // (so we'd test 64 samples, w/8->4 offsets) + if (octave > 0) + { + n1 = lowest_err_offset*2 -1; + n2 = lowest_err_offset*2+2+1; + if (n1 < 0) n1=0; + if (n2 > space[octave-1]) n2 = space[octave-1]; + } + else + align_offset[ch] = lowest_err_offset; + } + } +#endif + memcpy(m_oldwave[0], m_sound.fWaveform[0], sizeof(float)*512); + memcpy(m_oldwave[1], m_sound.fWaveform[1], sizeof(float)*512); + m_prev_align_offset[0] = align_offset[0]; + m_prev_align_offset[1] = align_offset[1]; + + // finally, apply the results: modify m_sound.fWaveform[2][0..512] + // by scooting the aligned samples so that they start at m_sound.fWaveform[2][0]. + for (int ch=0; ch<2; ch++) + if (align_offset[ch]>0) + { + for (int i=0; iPluginShellVJModeWndProc(hWnd, uMsg, wParam, lParam); + else + return DefWindowProc(hWnd, uMsg, wParam, lParam); +#endif + return 0; +} + +LRESULT CPluginShell::PluginShellVJModeWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +#if 0 + #ifdef _DEBUG + if (message != WM_MOUSEMOVE && + message != WM_NCHITTEST && + message != WM_SETCURSOR && + message != WM_COPYDATA && + message != WM_USER) + { + char caption[256] = "VJWndProc: frame 0, "; + if (m_frame > 0) + { + float time = m_time; + int hours = (int)(time/3600); + time -= hours*3600; + int minutes = (int)(time/60); + time -= minutes*60; + int seconds = (int)time; + time -= seconds; + int dsec = (int)(time*100); + sprintf(caption, "VJWndProc: frame %d, t=%dh:%02dm:%02d.%02ds, ", m_frame, hours, minutes, seconds, dsec); + } + OutputDebugMessage(caption, hwnd, message, wParam, lParam); + } + #endif + + switch(message) + { + case WM_KEYDOWN: + case WM_KEYUP: + case WM_CHAR: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_SYSCHAR: + // pass keystrokes on to plugin! + return PluginShellWindowProc(GetPluginWindow(),message,wParam,lParam); + + case WM_ERASEBKGND: + // Repaint window when song is paused and image needs to be repainted: + if (SendMessage(m_hWndWinamp,WM_USER,0,104)!=1 && m_vjd3d8_device) // WM_USER/104 return codes: 1=playing, 3=paused, other=stopped + { + m_vjd3d8_device->Present(NULL,NULL,NULL,NULL); + return 0; + } + break; + + /* + case WM_WINDOWPOSCHANGING: + if (m_screenmode == DESKTOP) + { + LPWINDOWPOS pwp = (LPWINDOWPOS)lParam; + if (pwp) + pwp->flags |= SWP_NOOWNERZORDER | SWP_NOZORDER; + } + break; + + case WM_ACTIVATEAPP: + // *Very Important Handler!* + // -Without this code, the app would not work properly when running in true + // fullscreen mode on multiple monitors; it would auto-minimize whenever the + // user clicked on a window in another display. + if (wParam == 1 && + m_screenmode == DESKTOP && + m_frame > 0 && + !m_exiting + ) + { + return 0; + } + break; + + /* + case WM_NCACTIVATE: + // *Very Important Handler!* + // -Without this code, the app would not work properly when running in true + // fullscreen mode on multiple monitors; it would auto-minimize whenever the + // user clicked on a window in another display. + // (NOTE: main window also handles this message this way) + if (wParam == 0 && + m_screenmode == FULLSCREEN && + m_frame > 0 && + !m_exiting && + m_lpDX && + m_lpDX->m_ready + && m_lpDX->m_lpD3D && + m_lpDX->m_lpD3D->GetAdapterCount() > 1 + ) + { + return 0; + } + break; + */ + + /* + case WM_ACTIVATEAPP: + if (wParam == 1 && + m_screenmode == DESKTOP && + m_frame > 0 && + !m_exiting && + m_vjd3d8_device + ) + { + return 0; + } + break; + */ + + /* + case WM_WINDOWPOSCHANGING: + if ( + m_screenmode == DESKTOP + && (!m_force_accept_WM_WINDOWPOSCHANGING) + && m_lpDX && m_lpDX->m_ready + ) + { + // unless we requested it ourselves or it's init time, + // prevent the fake desktop window from moving around + // in the Z order! (i.e., keep it on the bottom) + + // without this code, when you click on the 'real' desktop + // in a multimon setup, any windows that are overtop of the + // 'fake' desktop will flash, since they'll be covered + // up by the fake desktop window (but then shown again on + // the next frame, when we detect that the fake desktop + // window isn't on bottom & send it back to the bottom). + + LPWINDOWPOS pwp = (LPWINDOWPOS)lParam; + if (pwp) + pwp->flags |= SWP_NOOWNERZORDER | SWP_NOZORDER; + } + break; + */ + + case WM_CLOSE: + // if they close the VJ window (by some means other than ESC key), + // this will make the graphics window close, too. + m_exiting = 1; + if (GetPluginWindow()) + PostMessage(GetPluginWindow(), WM_CLOSE, 0, 0); + break; + + case WM_GETMINMAXINFO: + { + // don't let the window get too small + MINMAXINFO* p = (MINMAXINFO*)lParam; + if (p->ptMinTrackSize.x < 64) + p->ptMinTrackSize.x = 64; + p->ptMinTrackSize.y = p->ptMinTrackSize.x*3/4; + } + return 0; + + case WM_SIZE: + // clear or set activity flag to reflect focus + if (m_vjd3d8_device && !m_resizing_textwnd) + { + m_hidden_textwnd = (SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam) ? TRUE : FALSE; + + if (SIZE_MAXIMIZED==wParam || SIZE_RESTORED==wParam) // the window has been maximized or restored + OnUserResizeTextWindow(); + } + break; + + case WM_ENTERSIZEMOVE: + m_resizing_textwnd = 1; + break; + + case WM_EXITSIZEMOVE: + if( m_vjd3d8_device ) + OnUserResizeTextWindow(); + m_resizing_textwnd = 0; + break; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +#endif + return 0; +} diff --git a/lib/vis_milkdrop/pluginshell.h b/lib/vis_milkdrop/pluginshell.h new file mode 100644 index 0000000..4418b59 --- /dev/null +++ b/lib/vis_milkdrop/pluginshell.h @@ -0,0 +1,397 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __NULLSOFT_DX8_PLUGIN_SHELL_H__ +#define __NULLSOFT_DX8_PLUGIN_SHELL_H__ 1 + +#include "shell_defines.h" +#include "dxcontext.h" +#include "fft.h" +#include "defines.h" +//#include "textmgr.h" + +//#include "icon_t.h" +//#include +//using std::list; + +//extern "C" void SetTextureStageState( int x, DWORD dwY, DWORD dwZ); +//extern "C" void d3dSetSamplerState( int x, DWORD dwY, DWORD dwZ); +//extern "C" void d3dSetRenderState(DWORD dwY, DWORD dwZ); + +#define TIME_HIST_SLOTS 128 // # of slots used if fps > 60. half this many if fps==30. +#define MAX_SONGS_PER_PAGE 40 + +typedef struct +{ + char szFace[256]; + int nSize; // size requested @ font creation time + int bBold; + int bItalic; + int bAntiAliased; +} td_fontinfo; + +typedef struct +{ + float imm[2][3]; // bass, mids, treble, no damping, for each channel (long-term average is 1) + float avg[2][3]; // bass, mids, treble, some damping, for each channel (long-term average is 1) + float med_avg[2][3]; // bass, mids, treble, more damping, for each channel (long-term average is 1) + float long_avg[2][3]; // bass, mids, treble, heavy damping, for each channel (long-term average is 1) + float infinite_avg[2][3]; // bass, mids, treble: winamp's average output levels. (1) + float fWaveform[2][576]; // Not all 576 are valid! - only NUM_WAVEFORM_SAMPLES samples are valid for each channel (note: NUM_WAVEFORM_SAMPLES is declared in shell_defines.h) + float fSpectrum[2][NUM_FREQUENCIES]; // NUM_FREQUENCIES samples for each channel (note: NUM_FREQUENCIES is declared in shell_defines.h) +} td_soundinfo; // ...range is 0 Hz to 22050 Hz, evenly spaced. + +class CPluginShell +{ +protected: + + // GET METHODS + // ------------------------------------------------------------ +public: + int GetFrame(); // returns current frame # (starts at zero) + float GetTime(); // returns current animation time (in seconds) (starts at zero) (updated once per frame) + float GetFps(); // returns current estimate of framerate (frames per second) +protected: + eScrMode GetScreenMode(); // returns WINDOWED, FULLSCREEN, FAKE_FULLSCREEN, DESKTOP, or NOT_YET_KNOWN (if called before or during OverrideDefaults()). + HWND GetWinampWindow(); // returns handle to Winamp main window + HINSTANCE GetInstance(); // returns handle to the plugin DLL module; used for things like loading resources (dialogs, bitmaps, icons...) that are built into the plugin. + char* GetPluginsDirPath(); // usually returns 'c:\\program files\\winamp\\plugins\\' + char* GetConfigIniFile(); // usually returns 'c:\\program files\\winamp\\plugins\\something.ini' - filename is determined from identifiers in 'defines.h' + + // GET METHODS THAT ONLY WORK ONCE DIRECTX IS READY + // ------------------------------------------------------------ + // The following 'Get' methods are only available after DirectX has been initialized. + // If you call these from OverrideDefaults, MyPreInitialize, or MyReadConfig, + // they will return NULL (zero). + // ------------------------------------------------------------ + HWND GetPluginWindow(); // returns handle to the plugin window. NOT persistent; can change! + int GetWidth(); // returns width of plugin window interior, in pixels. + int GetHeight(); // returns height of plugin window interior, in pixels. + int GetBitDepth(); // returns 8, 16, 24 (rare), or 32 + LPDIRECT3DDEVICE9 GetDevice(); // returns a pointer to the DirectX 8 Device. NOT persistent; can change! + D3DCAPS9* GetCaps(); // returns a pointer to the D3DCAPS8 structer for the device. NOT persistent; can change. + D3DFORMAT GetBackBufFormat(); // returns the pixelformat of the back buffer (probably D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, D3DFMT_A4R4G4B4, D3DFMT_R3G3B2, D3DFMT_A8R3G3B2, D3DFMT_X4R4G4B4, or D3DFMT_UNKNOWN) + D3DFORMAT GetBackBufZFormat(); // returns the pixelformat of the back buffer's Z buffer (probably D3DFMT_D16_LOCKABLE, D3DFMT_D32, D3DFMT_D15S1, D3DFMT_D24S8, D3DFMT_D16, D3DFMT_D24X8, D3DFMT_D24X4S4, or D3DFMT_UNKNOWN) + char* GetDriverFilename(); // returns a text string with the filename of the current display adapter driver, such as "nv4_disp.dll" + char* GetDriverDescription(); // returns a text string describing the current display adapter, such as "NVIDIA GeForce4 Ti 4200" + + // FONTS & TEXT + // ------------------------------------------------------------ +public: +// LPD3DXFONT GetFont(eFontIndex idx); // returns a D3DX font handle for drawing text; see shell_defines.h for the definition of the 'eFontIndex' enum. +// int GetFontHeight(eFontIndex idx); // returns the height of the font, in pixels; see shell_defines.h for the definition of the 'eFontIndex' enum. +// CTextManager m_text; +protected: + + // MISC + // ------------------------------------------------------------ + td_soundinfo m_sound; // a structure always containing the most recent sound analysis information; defined in pluginshell.h. + void SuggestHowToFreeSomeMem(); // gives the user a 'smart' messagebox that suggests how they can free up some video memory. + + // CONFIG PANEL SETTINGS + // ------------------------------------------------------------ + // *** only read/write these values during CPlugin::OverrideDefaults! *** + int m_start_fullscreen; // 0 or 1 + int m_start_desktop; // 0 or 1 + int m_fake_fullscreen_mode; // 0 or 1 + // JM HACK +public: + int m_max_fps_fs; // 1-120, or 0 for 'unlimited' +protected: + // JM HACK + int m_max_fps_dm; // 1-120, or 0 for 'unlimited' + int m_max_fps_w; // 1-120, or 0 for 'unlimited' + int m_show_press_f1_msg; // 0 or 1 + int m_allow_page_tearing_w; // 0 or 1 + int m_allow_page_tearing_fs; // 0 or 1 + int m_allow_page_tearing_dm; // 0 or 1 + int m_minimize_winamp; // 0 or 1 + int m_desktop_show_icons; // 0 or 1 + int m_desktop_textlabel_boxes; // 0 or 1 + int m_desktop_manual_icon_scoot; // 0 or 1 + int m_desktop_555_fix; // 0 = 555, 1 = 565, 2 = 888 + int m_dualhead_horz; // 0 = both, 1 = left, 2 = right + int m_dualhead_vert; // 0 = both, 1 = top, 2 = bottom + int m_save_cpu; // 0 or 1 + int m_skin; // 0 or 1 + int m_fix_slow_text; // 0 or 1 + td_fontinfo m_fontinfo[NUM_BASIC_FONTS + NUM_EXTRA_FONTS]; + D3DDISPLAYMODE m_disp_mode_fs; // a D3DDISPLAYMODE struct that specifies the width, height, refresh rate, and color format to use when the plugin goes fullscreen. + int m_posX; + int m_posY; + int m_backBufferWidth; + int m_backBufferHeight; + float m_pixelRatio; + + // PURE VIRTUAL FUNCTIONS (...must be implemented by derived classes) + // ------------------------------------------------------------ + virtual void OverrideDefaults() {}; + virtual void MyPreInitialize() {}; + virtual void MyReadConfig() {}; + virtual void MyWriteConfig() {}; + virtual int AllocateMyNonDx8Stuff() { return 0; }; + virtual void CleanUpMyNonDx8Stuff() {}; + virtual int AllocateMyDX8Stuff() { return 0; }; + virtual void CleanUpMyDX8Stuff(int final_cleanup) {}; + virtual void MyRenderFn(int redraw) {}; + virtual void MyRenderUI(int *upper_left_corner_y, int *upper_right_corner_y, int *lower_left_corner_y, int *lower_right_corner_y, int xL, int xR) {}; + virtual LRESULT MyWindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam) { return 0; }; + virtual BOOL MyConfigTabProc(int nPage, HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) { return true;}; + +//===================================================================================================================== +private: + + // GENERAL PRIVATE STUFF + eScrMode m_screenmode; // // WINDOWED, FULLSCREEN, or FAKE_FULLSCREEN (i.e. running in a full-screen-sized window) + int m_frame; // current frame #, starting at zero + float m_time; // current animation time in seconds; starts at zero. + float m_fps; // current estimate of frames per second + HWND m_hWndWinamp; // handle to Winamp window + HINSTANCE m_hInstance; // handle to application instance + DXContext* m_lpDX; // pointer to DXContext object + char m_szPluginsDirPath[MAX_PATH]; // usually 'c:\\program files\\winamp\\plugins\\' + char m_szConfigIniFile[MAX_PATH]; // usually 'c:\\program files\\winamp\\plugins\\something.ini' - filename is determined from identifiers in 'defines.h' + LPDIRECT3DDEVICE9 m_device; + // FONTS + IDirect3DTexture9* m_lpDDSText; +// LPD3DXFONT m_d3dx_font[NUM_BASIC_FONTS + NUM_EXTRA_FONTS]; +// LPD3DXFONT m_d3dx_desktop_font; +// HFONT m_font[NUM_BASIC_FONTS + NUM_EXTRA_FONTS]; +// HFONT m_font_desktop; + + // PRIVATE CONFIG PANEL SETTINGS + D3DMULTISAMPLE_TYPE m_multisample_fullscreen; + D3DMULTISAMPLE_TYPE m_multisample_desktop; + D3DMULTISAMPLE_TYPE m_multisample_windowed; + GUID m_adapter_guid_fullscreen; + GUID m_adapter_guid_desktop; +public: + GUID m_adapter_guid_windowed; +private: + + // PRIVATE RUNTIME SETTINGS + int m_lost_focus; // ~mostly for fullscreen mode + int m_hidden; // ~mostly for windowed mode + int m_resizing; // ~mostly for windowed mode + int m_show_help; + int m_show_playlist; + int m_playlist_pos; // current selection on (plugin's) playlist menu + int m_playlist_pageups; // can be + or - + int m_playlist_top_idx; // used to track when our little playlist cache (m_playlist) needs updated. + int m_playlist_btm_idx; // used to track when our little playlist cache (m_playlist) needs updated. + int m_playlist_width_pixels; // considered invalid whenever 'm_playlist_top_idx' is -1. + char m_playlist[MAX_SONGS_PER_PAGE][256]; // considered invalid whenever 'm_playlist_top_idx' is -1. + int m_exiting; + int m_upper_left_corner_y; + int m_lower_left_corner_y; + int m_upper_right_corner_y; + int m_lower_right_corner_y; + int m_left_edge; + int m_right_edge; + int m_force_accept_WM_WINDOWPOSCHANGING; + + // PRIVATE - GDI STUFF + HMENU m_main_menu; + HMENU m_context_menu; + + // PRIVATE - DESKTOP MODE STUFF +// list m_icon_list; + IDirect3DTexture9* m_desktop_icons_texture[MAX_ICON_TEXTURES]; + HWND m_hWndProgMan; + HWND m_hWndDesktop; + HWND m_hWndDesktopListView; + char m_szDesktopFolder[MAX_PATH]; // *without* the final backslash + int m_desktop_icon_size; + int m_desktop_dragging; // '1' when user is dragging icons around + int m_desktop_box; // '1' when user is drawing a box + BYTE m_desktop_drag_pidl[1024]; // cast this to ITEMIDLIST + POINT m_desktop_drag_startpos; // applies to dragging or box-drawing + POINT m_desktop_drag_curpos; // applies to dragging or box-drawing + int m_desktop_wc_registered; + DWORD m_desktop_bk_color; + DWORD m_desktop_text_color; + DWORD m_desktop_sel_color; + DWORD m_desktop_sel_text_color; + int m_desktop_icon_state; // 0=uninit, 1=total refresh in progress, 2=ready, 3=update in progress + int m_desktop_icon_count; + int m_desktop_icon_update_frame; +// CRITICAL_SECTION m_desktop_cs; + int m_desktop_icons_disabled; + int m_vms_desktop_loaded; + int m_desktop_hook_set; + + // PRIVATE - MORE TIMEKEEPING + double m_last_raw_time; + float m_time_hist[TIME_HIST_SLOTS]; // cumulative + int m_time_hist_pos; + LARGE_INTEGER m_high_perf_timer_freq; // 0 if high-precision timer not available + LARGE_INTEGER m_prev_end_of_frame; + + // PRIVATE AUDIO PROCESSING DATA + FFT m_fftobj; + float m_oldwave[2][576]; // for wave alignment + int m_prev_align_offset[2]; // for wave alignment + int m_align_weights_ready; + +public: + CPluginShell(); + ~CPluginShell(); + + // called by vis.cpp, on behalf of Winamp: + int PluginPreInitialize(HWND hWinampWnd, HINSTANCE hWinampInstance); + int PluginInitialize(LPDIRECT3DDEVICE9 device, int iPosX, int iPosY, int iWidth, int iHeight, float pixelRatio); + int PluginRender(unsigned char *pWaveL, unsigned char *pWaveR); + void PluginQuit(); + int AllocateDX8Stuff(); + void CleanUpDX8Stuff(int final_cleanup); + + void ToggleHelp(); + void TogglePlaylist(); + + // config panel / windows messaging processes: + static LRESULT CALLBACK WindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK DesktopWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK VJModeWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); + static BOOL CALLBACK ConfigDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + static BOOL CALLBACK TabCtrlProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + static BOOL CALLBACK FontDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + static BOOL CALLBACK DesktopOptionsDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + static BOOL CALLBACK DualheadDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + +private: + void PushWindowToJustBeforeDesktop(HWND h); + void DrawAndDisplay(int redraw); + void ReadConfig(); + void WriteConfig(); + void DoTime(); + void AnalyzeNewSound(unsigned char *pWaveL, unsigned char *pWaveR); + void AlignWaves(); + int InitDirectX(); + void CleanUpDirectX(); + int InitGDIStuff(); + void CleanUpGDIStuff(); + int InitNonDx8Stuff(); + void CleanUpNonDx8Stuff(); + int InitVJStuff(RECT* pClientRect=NULL); + void CleanUpVJStuff(); + int AllocateFonts(IDirect3DDevice9 *pDevice); + void CleanUpFonts(); + void AllocateTextSurface(); + void ToggleDesktop(); + void OnUserResizeWindow(); + void OnUserResizeTextWindow(); + void PrepareFor2DDrawing_B(IDirect3DDevice9 *pDevice, int w, int h); + void RenderBuiltInTextMsgs(); +public: + void ToggleFullScreen(); + void DrawDarkTranslucentBox(RECT* pr); +private: + void RenderPlaylist(); + void StuffParams(DXCONTEXT_PARAMS *pParams); + void EnforceMaxFPS(); + + // DESKTOP MODE FUNCTIONS (found in desktop_mode.cpp) + int InitDesktopMode(); + void CleanUpDesktopMode(); + int CreateDesktopIconTexture(IDirect3DTexture9** ppTex); + void DeselectDesktop(); + void UpdateDesktopBitmaps(); + int StuffIconBitmaps(int iStartIconIdx, int iTexNum, int *show_msgs); + void RenderDesktop(); + + // SEPARATE TEXT WINDOW (FOR VJ MODE) + int m_vj_mode; + int m_hidden_textwnd; + int m_resizing_textwnd; + protected: + HWND m_hTextWnd; + private: + int m_nTextWndWidth; + int m_nTextWndHeight; + bool m_bTextWindowClassRegistered; + LPDIRECT3D9 m_vjd3d8; + LPDIRECT3DDEVICE9 m_vjd3d8_device; + //HDC m_memDC; // memory device context + //HBITMAP m_memBM, m_oldBM; + //HBRUSH m_hBlackBrush; + + // WINDOWPROC FUNCTIONS + LRESULT PluginShellWindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); // in windowproc.cpp + LRESULT PluginShellDesktopWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); + LRESULT PluginShellVJModeWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam); + + // CONFIG PANEL FUNCTIONS: + BOOL PluginShellConfigDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + BOOL PluginShellConfigTab1Proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + BOOL PluginShellFontDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + BOOL PluginShellDesktopOptionsDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + BOOL PluginShellDualheadDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); + bool InitConfig(HWND hDialogWnd); + void EndConfig(); + void UpdateAdapters(int screenmode); + void UpdateFSAdapterDispModes(); // (fullscreen only) + void UpdateDispModeMultiSampling(int screenmode); + void UpdateMaxFps(int screenmode); + int GetCurrentlySelectedAdapter(int screenmode); + void SaveDisplayMode(); + void SaveMultiSamp(int screenmode); + void SaveAdapter(int screenmode); + void SaveMaxFps(int screenmode); + void OnTabChanged(int nNewTab); + LPDIRECT3DDEVICE9 GetTextDevice() { return (m_vjd3d8_device) ? m_vjd3d8_device : m_lpDX->m_lpDevice; } +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif \ No newline at end of file diff --git a/lib/vis_milkdrop/shell_defines.h b/lib/vis_milkdrop/shell_defines.h new file mode 100644 index 0000000..0167670 --- /dev/null +++ b/lib/vis_milkdrop/shell_defines.h @@ -0,0 +1,106 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __NULLSOFT_DX8_PLUGIN_SHELL_SHELL_DEFINES_H__ +#define __NULLSOFT_DX8_PLUGIN_SHELL_SHELL_DEFINES_H__ 1 + +#include +//#include + +#define DEFAULT_FULLSCREEN_WIDTH 640 +#define DEFAULT_FULLSCREEN_HEIGHT 480 +#define MAX_ICON_TEXTURES 8 +#define ICON_TEXTURE_SIZE 256 +#define DEFAULT_WINDOW_SIZE 0.625f // as a portion of the width or height of the screen (whichever is smaller) +#define DESKTOP_MODE_KEYBOARD_INPUT_WINDOW_CLASSNAME "DESKTOP MODE KEYBOARD INPUT WINDOW" +#define BGR2RGB(x) (((x>>16)&0xFF) | (x & 0xFF00) | ((x<<16)&0xFF0000)) + +#define NUM_BASIC_FONTS 4 +#define SYS_FONT 0 +#define DEC_FONT 1 +#define HELP_FONT 2 +#define DESK_FONT 3 +#define MAX_EXTRA_FONTS 5 +typedef enum +{ + SIMPLE_FONT = 0, // aka 'system' font; should be legible + DECORATIVE_FONT = 1, + HELPSCREEN_FONT = 2, + PLAYLIST_FONT = 3, + EXTRA_1 = 4, + EXTRA_2 = 5, + EXTRA_3 = 6, + EXTRA_4 = 7, + EXTRA_5 = 8 +} +eFontIndex; + +// for m_screenmode: +typedef enum +{ + NOT_YET_KNOWN = -1, + FULLSCREEN = 0, + WINDOWED = 1, + FAKE_FULLSCREEN = 2, + DESKTOP = 3 // doesn't use overlays! =) +} +eScrMode; + +// embedding stuff +#define WM_WA_IPC WM_USER +#define IPC_GET_EMBEDIF 505 // pass an embedWindowState; returns an HWND embedWindow(embedWindowState *); if the data is NULL, otherwise returns the HWND directly +#define EMBED_FLAGS_NORESIZE 1 // set this bit in embedWindowState.flags to keep window from being resizable +#define EMBED_FLAGS_NOTRANSPARENCY 2 // set this bit in embedWindowState.flags to make gen_ff turn transparency off for this wnd +#define IPC_SETVISWND 611 +#define ID_VIS_NEXT 40382 +#define ID_VIS_PREV 40383 +#define ID_VIS_RANDOM 40384 +#define ID_VIS_FS 40389 +#define ID_VIS_CFG 40390 +#define ID_VIS_MENU 40391 + +typedef struct +{ + HWND me; //hwnd of the window + int flags; + RECT r; + void *user_ptr; // for application use + int extra_data[64]; // for internal winamp use +} +embedWindowState; + + + + + + + + +#endif \ No newline at end of file diff --git a/lib/vis_milkdrop/state.cpp b/lib/vis_milkdrop/state.cpp new file mode 100644 index 0000000..b9ef5c0 --- /dev/null +++ b/lib/vis_milkdrop/state.cpp @@ -0,0 +1,1797 @@ + +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include "state.h" +#include "support.h" +#include "evallib/compiler.h" +#include "plugin.h" +#include "utility.h" + +//#include +//#include +#include +#include + +extern CPlugin* g_plugin; // declared in main.cpp + + + +CState::CState() +{ + //Default(); + + // this is the list of variables that can be used for a PER-FRAME calculation; + // it is a SUBSET of the per-vertex calculation variable list. + m_pf_codehandle = NULL; + m_pp_codehandle = NULL; + for (int i=0; i"); + //strcpy(m_szSection, "n/a"); + + m_fRating = 3.0f; + m_bBlending = false; + + m_fGammaAdj = 2.0f; // 1.0 = reg; +2.0 = double, +3.0 = triple... + m_fVideoEchoZoom = 2.0f; + m_fVideoEchoAlpha = 0.0f; + m_nVideoEchoOrientation = 0; // 0-3 + + m_fDecay = 0.98f; // 1.0 = none, 0.95 = heavy decay + + m_nWaveMode = 0; + m_nOldWaveMode = -1; + m_bAdditiveWaves = false; + m_fWaveAlpha = 0.8f; + m_fWaveScale = 1.0f; + m_fWaveSmoothing = 0.75f; // 0 = no smoothing, 0.9 = HEAVY smoothing + m_bWaveDots = false; + m_bWaveThick = false; + m_fWaveParam = 0.0f; + m_bModWaveAlphaByVolume = false; + m_fModWaveAlphaStart = 0.75f; // when relative volume hits this level, alpha -> 0 + m_fModWaveAlphaEnd = 0.95f; // when relative volume hits this level, alpha -> 1 + + m_fWarpAnimSpeed = 1.0f; // additional timescaling for warp animation + m_fWarpScale = 1.0f; + m_fZoomExponent = 1.0f; + m_fShader = 0.0f; + m_bMaximizeWaveColor = true; + m_bTexWrap = true; + m_bDarkenCenter = false; + m_bRedBlueStereo = false; + m_fMvX = 12.0f; + m_fMvY = 9.0f; + m_fMvDX = 0.0f; + m_fMvDY = 0.0f; + m_fMvL = 0.9f; + m_fMvR = 1.0f; + m_fMvG = 1.0f; + m_fMvB = 1.0f; + m_fMvA = 1.0f; + m_bBrighten = false; + m_bDarken = false; + m_bSolarize = false; + m_bInvert = false; + + // DON'T FORGET TO ADD NEW VARIABLES TO BLEND FUNCTION, IMPORT, and EXPORT AS WELL!!!!!!!! + // ALSO BE SURE TO REGISTER THEM ON THE MAIN MENU (SEE MILKDROP.CPP) + + // time-varying variables: base, var, varFreq1, varFreq2 + m_fZoom = 1.0f; + m_fRot = 0.0f; + m_fRotCX = 0.5f; + m_fRotCY = 0.5f; + m_fXPush = 0.0f; + m_fYPush = 0.0f; + m_fWarpAmount = 1.0f; + m_fStretchX = 1.0f; + m_fStretchY = 1.0f; + m_fWaveR = 1.0f; + m_fWaveG = 1.0f; + m_fWaveB = 1.0f; + m_fWaveX = 0.5f; + m_fWaveY = 0.5f; + m_fOuterBorderSize = 0.01f; + m_fOuterBorderR = 0.0f; + m_fOuterBorderG = 0.0f; + m_fOuterBorderB = 0.0f; + m_fOuterBorderA = 0.0f; + m_fInnerBorderSize = 0.01f; + m_fInnerBorderR = 0.25f; + m_fInnerBorderG = 0.25f; + m_fInnerBorderB = 0.25f; + m_fInnerBorderA = 0.0f; + + for (int i=0; im_fVideoEchoAlphaOld = s_from->m_fVideoEchoAlpha.eval(-1); + s_to->m_nVideoEchoOrientationOld = s_from->m_nVideoEchoOrientation; + s_to->m_nOldWaveMode = s_from->m_nWaveMode; + + /* + s_to->m_fVideoEchoAlphaOld = s_from->m_fVideoEchoAlpha.eval(-1); + s_to->m_nVideoEchoOrientationOld = s_from->m_nVideoEchoOrientation; + + s_to->m_nOldWaveMode = s_from->m_nWaveMode; + s_to->m_nWaveMode = s_from->m_nWaveMode; + s_to->m_bAdditiveWaves = s_from->m_bAdditiveWaves; + s_to->m_nVideoEchoOrientation = s_from->m_nVideoEchoOrientation; + s_to->m_fWarpAnimSpeed = s_from->m_fWarpAnimSpeed; // would req. 10 phase-matches to blend this one!!! + s_to->m_bWaveDots = s_from->m_bWaveDots; + s_to->m_bWaveThick = s_from->m_bWaveThick; + s_to->m_bModWaveAlphaByVolume = s_from->m_bModWaveAlphaByVolume; + s_to->m_bMaximizeWaveColor = s_from->m_bMaximizeWaveColor; + s_to->m_bTexWrap = s_from->m_bTexWrap; + s_to->m_bDarkenCenter = s_from->m_bDarkenCenter; + s_to->m_bRedBlueStereo = s_from->m_bRedBlueStereo; + s_to->m_bBrighten = s_from->m_bBrighten; + s_to->m_bDarken = s_from->m_bDarken; + s_to->m_bSolarize = s_from->m_bSolarize; + s_to->m_bInvert = s_from->m_bInvert; + s_to->m_fRating = s_from->m_fRating; + */ + + // expr. eval. also copies over immediately (replaces prev.) + m_bBlending = true; + m_fBlendStartTime = fAnimTime; + m_fBlendDuration = fTimespan; + + /* + //for (int e=0; em_szPerFrameExpr); + strcpy(s_to->m_szPerFrameExpr, szTemp); + + strcpy(szTemp, m_szPerPixelExpr); + strcpy(m_szPerPixelExpr, s_to->m_szPerPixelExpr); + strcpy(s_to->m_szPerPixelExpr, szTemp); + + strcpy(szTemp, m_szPerFrameInit); + strcpy(m_szPerFrameInit, s_to->m_szPerFrameInit); + strcpy(s_to->m_szPerFrameInit, szTemp); + } + RecompileExpressions(); + s_to->RecompileExpressions(); + + strcpy(m_szDesc, s_to->m_szDesc); + //strcpy(m_szSection, s_to->m_szSection); + */ + + // CBlendableFloats & SuperValues blend over time + m_fGammaAdj .StartBlendFrom(&s_from->m_fGammaAdj , fAnimTime, fTimespan); + m_fVideoEchoZoom .StartBlendFrom(&s_from->m_fVideoEchoZoom , fAnimTime, fTimespan); + m_fVideoEchoAlpha.StartBlendFrom(&s_from->m_fVideoEchoAlpha, fAnimTime, fTimespan); + m_fDecay .StartBlendFrom(&s_from->m_fDecay , fAnimTime, fTimespan); + m_fWaveAlpha .StartBlendFrom(&s_from->m_fWaveAlpha , fAnimTime, fTimespan); + m_fWaveScale .StartBlendFrom(&s_from->m_fWaveScale , fAnimTime, fTimespan); + m_fWaveSmoothing .StartBlendFrom(&s_from->m_fWaveSmoothing , fAnimTime, fTimespan); + m_fWaveParam .StartBlendFrom(&s_from->m_fWaveParam , fAnimTime, fTimespan); + m_fWarpScale .StartBlendFrom(&s_from->m_fWarpScale , fAnimTime, fTimespan); + m_fZoomExponent .StartBlendFrom(&s_from->m_fZoomExponent , fAnimTime, fTimespan); + m_fShader .StartBlendFrom(&s_from->m_fShader , fAnimTime, fTimespan); + m_fModWaveAlphaStart.StartBlendFrom(&s_from->m_fModWaveAlphaStart, fAnimTime, fTimespan); + m_fModWaveAlphaEnd .StartBlendFrom(&s_from->m_fModWaveAlphaEnd, fAnimTime, fTimespan); + + m_fZoom .StartBlendFrom(&s_from->m_fZoom , fAnimTime, fTimespan); + m_fRot .StartBlendFrom(&s_from->m_fRot , fAnimTime, fTimespan); + m_fRotCX .StartBlendFrom(&s_from->m_fRotCX , fAnimTime, fTimespan); + m_fRotCY .StartBlendFrom(&s_from->m_fRotCY , fAnimTime, fTimespan); + m_fXPush .StartBlendFrom(&s_from->m_fXPush , fAnimTime, fTimespan); + m_fYPush .StartBlendFrom(&s_from->m_fYPush , fAnimTime, fTimespan); + m_fWarpAmount.StartBlendFrom(&s_from->m_fWarpAmount,fAnimTime, fTimespan); + m_fStretchX .StartBlendFrom(&s_from->m_fStretchX , fAnimTime, fTimespan); + m_fStretchY .StartBlendFrom(&s_from->m_fStretchY , fAnimTime, fTimespan); + m_fWaveR .StartBlendFrom(&s_from->m_fWaveR , fAnimTime, fTimespan); + m_fWaveG .StartBlendFrom(&s_from->m_fWaveG , fAnimTime, fTimespan); + m_fWaveB .StartBlendFrom(&s_from->m_fWaveB , fAnimTime, fTimespan); + m_fWaveX .StartBlendFrom(&s_from->m_fWaveX , fAnimTime, fTimespan); + m_fWaveY .StartBlendFrom(&s_from->m_fWaveY , fAnimTime, fTimespan); + m_fOuterBorderSize .StartBlendFrom(&s_from->m_fOuterBorderSize , fAnimTime, fTimespan); + m_fOuterBorderR .StartBlendFrom(&s_from->m_fOuterBorderR , fAnimTime, fTimespan); + m_fOuterBorderG .StartBlendFrom(&s_from->m_fOuterBorderG , fAnimTime, fTimespan); + m_fOuterBorderB .StartBlendFrom(&s_from->m_fOuterBorderB , fAnimTime, fTimespan); + m_fOuterBorderA .StartBlendFrom(&s_from->m_fOuterBorderA , fAnimTime, fTimespan); + m_fInnerBorderSize .StartBlendFrom(&s_from->m_fInnerBorderSize , fAnimTime, fTimespan); + m_fInnerBorderR .StartBlendFrom(&s_from->m_fInnerBorderR , fAnimTime, fTimespan); + m_fInnerBorderG .StartBlendFrom(&s_from->m_fInnerBorderG , fAnimTime, fTimespan); + m_fInnerBorderB .StartBlendFrom(&s_from->m_fInnerBorderB , fAnimTime, fTimespan); + m_fInnerBorderA .StartBlendFrom(&s_from->m_fInnerBorderA , fAnimTime, fTimespan); + m_fMvX .StartBlendFrom(&s_from->m_fMvX , fAnimTime, fTimespan); + m_fMvY .StartBlendFrom(&s_from->m_fMvY , fAnimTime, fTimespan); + m_fMvDX .StartBlendFrom(&s_from->m_fMvDX , fAnimTime, fTimespan); + m_fMvDY .StartBlendFrom(&s_from->m_fMvDY , fAnimTime, fTimespan); + m_fMvL .StartBlendFrom(&s_from->m_fMvL , fAnimTime, fTimespan); + m_fMvR .StartBlendFrom(&s_from->m_fMvR , fAnimTime, fTimespan); + m_fMvG .StartBlendFrom(&s_from->m_fMvG , fAnimTime, fTimespan); + m_fMvB .StartBlendFrom(&s_from->m_fMvB , fAnimTime, fTimespan); + m_fMvA .StartBlendFrom(&s_from->m_fMvA , fAnimTime, fTimespan); + + // if motion vectors were transparent before, don't morph the # in X and Y - just + // start in the right place, and fade them in. + bool bOldStateTransparent = (s_from->m_fMvA.eval(-1) < 0.001f); + bool bNewStateTransparent = (s_to->m_fMvA.eval(-1) < 0.001f); + if (!bOldStateTransparent && bNewStateTransparent) + { + s_from->m_fMvX = s_to->m_fMvX.eval(fAnimTime); + s_from->m_fMvY = s_to->m_fMvY.eval(fAnimTime); + s_from->m_fMvDX = s_to->m_fMvDX.eval(fAnimTime); + s_from->m_fMvDY = s_to->m_fMvDY.eval(fAnimTime); + s_from->m_fMvL = s_to->m_fMvL.eval(fAnimTime); + s_from->m_fMvR = s_to->m_fMvR.eval(fAnimTime); + s_from->m_fMvG = s_to->m_fMvG.eval(fAnimTime); + s_from->m_fMvB = s_to->m_fMvB.eval(fAnimTime); + } + if (bNewStateTransparent && !bOldStateTransparent) + { + s_to->m_fMvX = s_from->m_fMvX.eval(fAnimTime); + s_to->m_fMvY = s_from->m_fMvY.eval(fAnimTime); + s_to->m_fMvDX = s_from->m_fMvDX.eval(fAnimTime); + s_to->m_fMvDY = s_from->m_fMvDY.eval(fAnimTime); + s_to->m_fMvL = s_from->m_fMvL.eval(fAnimTime); + s_to->m_fMvR = s_from->m_fMvR.eval(fAnimTime); + s_to->m_fMvG = s_from->m_fMvG.eval(fAnimTime); + s_to->m_fMvB = s_from->m_fMvB.eval(fAnimTime); + } + +} + +void WriteCode(FILE* fOut, int i, char* pStr, char* prefix) +{ + char szLineName[32]; + int line = 1; + int start_pos = 0; + int char_pos = 0; + + while (pStr[start_pos] != 0) + { + while ( pStr[char_pos] != 0 && + pStr[char_pos] != LINEFEED_CONTROL_CHAR) + char_pos++; + + sprintf(szLineName, "%s%d", prefix, line); + + char ch = pStr[char_pos]; + pStr[char_pos] = 0; + //if (!WritePrivateProfileString(szSectionName,szLineName,&pStr[start_pos],szIniFile)) return false; + fprintf(fOut, "%s=%s\n", szLineName, &pStr[start_pos]); + pStr[char_pos] = ch; + + if (pStr[char_pos] != 0) char_pos++; + start_pos = char_pos; + line++; + } +} + +bool CState::Export(char *szSectionName, char *szIniFile) +{ + FILE *fOut = fopen(szIniFile, "w"); + if (!fOut) return false; + + fprintf(fOut, "[%s]\n", szSectionName); + + fprintf(fOut, "%s=%f\n", "fRating", m_fRating); + fprintf(fOut, "%s=%f\n", "fGammaAdj", m_fGammaAdj.eval(-1)); + fprintf(fOut, "%s=%f\n", "fDecay", m_fDecay.eval(-1)); + fprintf(fOut, "%s=%f\n", "fVideoEchoZoom", m_fVideoEchoZoom.eval(-1)); + fprintf(fOut, "%s=%f\n", "fVideoEchoAlpha", m_fVideoEchoAlpha.eval(-1)); + fprintf(fOut, "%s=%d\n", "nVideoEchoOrientation", m_nVideoEchoOrientation); + + fprintf(fOut, "%s=%d\n", "nWaveMode", m_nWaveMode); + fprintf(fOut, "%s=%d\n", "bAdditiveWaves", m_bAdditiveWaves); + fprintf(fOut, "%s=%d\n", "bWaveDots", m_bWaveDots); + fprintf(fOut, "%s=%d\n", "bWaveThick", m_bWaveThick); + fprintf(fOut, "%s=%d\n", "bModWaveAlphaByVolume", m_bModWaveAlphaByVolume); + fprintf(fOut, "%s=%d\n", "bMaximizeWaveColor", m_bMaximizeWaveColor); + fprintf(fOut, "%s=%d\n", "bTexWrap", m_bTexWrap ); + fprintf(fOut, "%s=%d\n", "bDarkenCenter", m_bDarkenCenter ); + fprintf(fOut, "%s=%d\n", "bRedBlueStereo", m_bRedBlueStereo ); + fprintf(fOut, "%s=%d\n", "bBrighten", m_bBrighten ); + fprintf(fOut, "%s=%d\n", "bDarken", m_bDarken ); + fprintf(fOut, "%s=%d\n", "bSolarize", m_bSolarize ); + fprintf(fOut, "%s=%d\n", "bInvert", m_bInvert ); + + fprintf(fOut, "%s=%f\n", "fWaveAlpha", m_fWaveAlpha.eval(-1)); + fprintf(fOut, "%s=%f\n", "fWaveScale", m_fWaveScale.eval(-1)); + fprintf(fOut, "%s=%f\n", "fWaveSmoothing", m_fWaveSmoothing.eval(-1)); + fprintf(fOut, "%s=%f\n", "fWaveParam", m_fWaveParam.eval(-1)); + fprintf(fOut, "%s=%f\n", "fModWaveAlphaStart", m_fModWaveAlphaStart.eval(-1)); + fprintf(fOut, "%s=%f\n", "fModWaveAlphaEnd", m_fModWaveAlphaEnd.eval(-1)); + fprintf(fOut, "%s=%f\n", "fWarpAnimSpeed", m_fWarpAnimSpeed); + fprintf(fOut, "%s=%f\n", "fWarpScale", m_fWarpScale.eval(-1)); + fprintf(fOut, "%s=%f\n", "fZoomExponent", m_fZoomExponent.eval(-1)); + fprintf(fOut, "%s=%f\n", "fShader", m_fShader.eval(-1)); + + fprintf(fOut, "%s=%f\n", "zoom", m_fZoom .eval(-1)); + fprintf(fOut, "%s=%f\n", "rot", m_fRot .eval(-1)); + fprintf(fOut, "%s=%f\n", "cx", m_fRotCX .eval(-1)); + fprintf(fOut, "%s=%f\n", "cy", m_fRotCY .eval(-1)); + fprintf(fOut, "%s=%f\n", "dx", m_fXPush .eval(-1)); + fprintf(fOut, "%s=%f\n", "dy", m_fYPush .eval(-1)); + fprintf(fOut, "%s=%f\n", "warp", m_fWarpAmount.eval(-1)); + fprintf(fOut, "%s=%f\n", "sx", m_fStretchX .eval(-1)); + fprintf(fOut, "%s=%f\n", "sy", m_fStretchY .eval(-1)); + fprintf(fOut, "%s=%f\n", "wave_r", m_fWaveR .eval(-1)); + fprintf(fOut, "%s=%f\n", "wave_g", m_fWaveG .eval(-1)); + fprintf(fOut, "%s=%f\n", "wave_b", m_fWaveB .eval(-1)); + fprintf(fOut, "%s=%f\n", "wave_x", m_fWaveX .eval(-1)); + fprintf(fOut, "%s=%f\n", "wave_y", m_fWaveY .eval(-1)); + + fprintf(fOut, "%s=%f\n", "ob_size", m_fOuterBorderSize.eval(-1)); + fprintf(fOut, "%s=%f\n", "ob_r", m_fOuterBorderR.eval(-1)); + fprintf(fOut, "%s=%f\n", "ob_g", m_fOuterBorderG.eval(-1)); + fprintf(fOut, "%s=%f\n", "ob_b", m_fOuterBorderB.eval(-1)); + fprintf(fOut, "%s=%f\n", "ob_a", m_fOuterBorderA.eval(-1)); + fprintf(fOut, "%s=%f\n", "ib_size", m_fInnerBorderSize.eval(-1)); + fprintf(fOut, "%s=%f\n", "ib_r", m_fInnerBorderR.eval(-1)); + fprintf(fOut, "%s=%f\n", "ib_g", m_fInnerBorderG.eval(-1)); + fprintf(fOut, "%s=%f\n", "ib_b", m_fInnerBorderB.eval(-1)); + fprintf(fOut, "%s=%f\n", "ib_a", m_fInnerBorderA.eval(-1)); + fprintf(fOut, "%s=%f\n", "nMotionVectorsX", m_fMvX.eval(-1)); + fprintf(fOut, "%s=%f\n", "nMotionVectorsY", m_fMvY.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_dx", m_fMvDX.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_dy", m_fMvDY.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_l", m_fMvL.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_r", m_fMvR.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_g", m_fMvG.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_b", m_fMvB.eval(-1)); + fprintf(fOut, "%s=%f\n", "mv_a", m_fMvA.eval(-1)); + + int i=0; + + for (i=0; i= 8191-char_pos-1)) // or if we're out of space + { + bDone = true; + } + else + { + sprintf(&pStr[char_pos], "%s%c", szLine, LINEFEED_CONTROL_CHAR); + } + + char_pos += len + 1; + line++; + } + pStr[char_pos++] = 0; // null-terminate + + // read in & compile arbitrary expressions + /* + int n2 = 3 + MAX_CUSTOM_WAVES*3 + MAX_CUSTOM_SHAPES*2; + for (int n=0; n= 8191-char_pos-1)) // or if we're out of space + { + bDone = true; + } + else + { + sprintf(&pStr[char_pos], "%s%c", szLine, LINEFEED_CONTROL_CHAR); + } + + char_pos += len + 1; + line++; + } + pStr[char_pos++] = 0; // null-terminate + } + */ +} + +int CWave::Import(char* szSectionName, char *szIniFile, int i) +{ +// if (GetFileAttributes(szIniFile)==0xFFFFFFFF) +// return 0; + + char buf[64]; + sprintf(buf, "wavecode_%d_%s", i, "enabled" ); enabled = InternalGetPrivateProfileInt (szSectionName, buf, enabled , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "samples" ); samples = InternalGetPrivateProfileInt (szSectionName, buf, samples , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "sep" ); sep = InternalGetPrivateProfileInt (szSectionName, buf, sep , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "bSpectrum" ); bSpectrum = InternalGetPrivateProfileInt (szSectionName, buf, bSpectrum , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "bUseDots" ); bUseDots = InternalGetPrivateProfileInt (szSectionName, buf, bUseDots , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "bDrawThick"); bDrawThick = InternalGetPrivateProfileInt (szSectionName, buf, bDrawThick, szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "bAdditive" ); bAdditive = InternalGetPrivateProfileInt (szSectionName, buf, bAdditive , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "scaling" ); scaling = InternalGetPrivateProfileFloat(szSectionName, buf, scaling , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "smoothing" ); smoothing = InternalGetPrivateProfileFloat(szSectionName, buf, smoothing , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "r" ); r = InternalGetPrivateProfileFloat(szSectionName, buf, r , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "g" ); g = InternalGetPrivateProfileFloat(szSectionName, buf, g , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "b" ); b = InternalGetPrivateProfileFloat(szSectionName, buf, b , szIniFile); + sprintf(buf, "wavecode_%d_%s", i, "a" ); a = InternalGetPrivateProfileFloat(szSectionName, buf, a , szIniFile); + + // READ THE CODE IN + char prefix[64]; + sprintf(prefix, "wave_%d_init", i); ReadCode(szSectionName, szIniFile, m_szInit, prefix); + sprintf(prefix, "wave_%d_per_frame", i); ReadCode(szSectionName, szIniFile, m_szPerFrame, prefix); + sprintf(prefix, "wave_%d_per_point", i); ReadCode(szSectionName, szIniFile, m_szPerPoint, prefix); + + return 1; +} + +int CShape::Import(char* szSectionName, char *szIniFile, int i) +{ +// if (GetFileAttributes(szIniFile)==0xFFFFFFFF) +// return 0; + + char buf[64]; + sprintf(buf, "shapecode_%d_%s", i, "enabled" ); enabled = InternalGetPrivateProfileInt (szSectionName, buf, enabled , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "sides" ); sides = InternalGetPrivateProfileInt (szSectionName, buf, sides , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "additive" ); additive = InternalGetPrivateProfileInt (szSectionName, buf, additive , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "thickOutline"); thickOutline = InternalGetPrivateProfileInt (szSectionName, buf, thickOutline, szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "textured" ); textured = InternalGetPrivateProfileInt (szSectionName, buf, textured , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "x" ); x = InternalGetPrivateProfileFloat(szSectionName, buf, x , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "y" ); y = InternalGetPrivateProfileFloat(szSectionName, buf, y , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "rad" ); rad = InternalGetPrivateProfileFloat(szSectionName, buf, rad , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "ang" ); ang = InternalGetPrivateProfileFloat(szSectionName, buf, ang , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "tex_ang" ); tex_ang = InternalGetPrivateProfileFloat(szSectionName, buf, tex_ang , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "tex_zoom" ); tex_zoom = InternalGetPrivateProfileFloat(szSectionName, buf, tex_zoom , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "r" ); r = InternalGetPrivateProfileFloat(szSectionName, buf, r , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "g" ); g = InternalGetPrivateProfileFloat(szSectionName, buf, g , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "b" ); b = InternalGetPrivateProfileFloat(szSectionName, buf, b , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "a" ); a = InternalGetPrivateProfileFloat(szSectionName, buf, a , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "r2" ); r2 = InternalGetPrivateProfileFloat(szSectionName, buf, r2 , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "g2" ); g2 = InternalGetPrivateProfileFloat(szSectionName, buf, g2 , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "b2" ); b2 = InternalGetPrivateProfileFloat(szSectionName, buf, b2 , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "a2" ); a2 = InternalGetPrivateProfileFloat(szSectionName, buf, a2 , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "border_r" ); border_r = InternalGetPrivateProfileFloat(szSectionName, buf, border_r , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "border_g" ); border_g = InternalGetPrivateProfileFloat(szSectionName, buf, border_g , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "border_b" ); border_b = InternalGetPrivateProfileFloat(szSectionName, buf, border_b , szIniFile); + sprintf(buf, "shapecode_%d_%s", i, "border_a" ); border_a = InternalGetPrivateProfileFloat(szSectionName, buf, border_a , szIniFile); + + // READ THE CODE IN + char prefix[64]; + sprintf(prefix, "shape_%d_init", i); ReadCode(szSectionName, szIniFile, m_szInit, prefix); + sprintf(prefix, "shape_%d_per_frame", i); ReadCode(szSectionName, szIniFile, m_szPerFrame, prefix); + + return 1; +} + +void CState::Import(char *szSectionName, char *szIniFile) +{ + + Default(); + + //strcpy(m_szSection, szSectionName); + //InternalGetPrivateProfileString(szSectionName, "szDesc", "", m_szDesc, sizeof(m_szDesc), szIniFile); + + // extract a description of the preset from the filename + { + // copy get the filename (without the path) + char *p = strrchr(szIniFile, '/'); + if (p==NULL) p = szIniFile; + strcpy(m_szDesc, p+1); + + // next remove the extension + RemoveExtension(m_szDesc); + } + + m_fRating = InternalGetPrivateProfileFloat(szSectionName,"fRating",m_fRating,szIniFile); + m_fDecay = InternalGetPrivateProfileFloat(szSectionName,"fDecay",m_fDecay.eval(-1),szIniFile); + m_fGammaAdj = InternalGetPrivateProfileFloat(szSectionName,"fGammaAdj" ,m_fGammaAdj.eval(-1),szIniFile); + m_fVideoEchoZoom = InternalGetPrivateProfileFloat(szSectionName,"fVideoEchoZoom",m_fVideoEchoZoom.eval(-1),szIniFile); + m_fVideoEchoAlpha = InternalGetPrivateProfileFloat(szSectionName,"fVideoEchoAlpha",m_fVideoEchoAlpha.eval(-1),szIniFile); + m_nVideoEchoOrientation = InternalGetPrivateProfileInt (szSectionName,"nVideoEchoOrientation",m_nVideoEchoOrientation,szIniFile); + + m_nWaveMode = InternalGetPrivateProfileInt (szSectionName,"nWaveMode",m_nWaveMode,szIniFile); + m_bAdditiveWaves = (InternalGetPrivateProfileInt (szSectionName,"bAdditiveWaves",m_bAdditiveWaves,szIniFile) != 0); + m_bWaveDots = (InternalGetPrivateProfileInt (szSectionName,"bWaveDots",m_bWaveDots,szIniFile) != 0); + m_bWaveThick = (InternalGetPrivateProfileInt (szSectionName,"bWaveThick",m_bWaveThick,szIniFile) != 0); + m_bModWaveAlphaByVolume = (InternalGetPrivateProfileInt (szSectionName,"bModWaveAlphaByVolume",m_bModWaveAlphaByVolume,szIniFile) != 0); + m_bMaximizeWaveColor = (InternalGetPrivateProfileInt (szSectionName,"bMaximizeWaveColor" ,m_bMaximizeWaveColor,szIniFile) != 0); + m_bTexWrap = (InternalGetPrivateProfileInt (szSectionName,"bTexWrap", m_bTexWrap,szIniFile) != 0); + m_bDarkenCenter = (InternalGetPrivateProfileInt (szSectionName,"bDarkenCenter", m_bDarkenCenter,szIniFile) != 0); + m_bRedBlueStereo = (InternalGetPrivateProfileInt (szSectionName,"bRedBlueStereo", m_bRedBlueStereo,szIniFile) != 0); + m_bBrighten = (InternalGetPrivateProfileInt (szSectionName,"bBrighten",m_bBrighten ,szIniFile) != 0); + m_bDarken = (InternalGetPrivateProfileInt (szSectionName,"bDarken" ,m_bDarken ,szIniFile) != 0); + m_bSolarize = (InternalGetPrivateProfileInt (szSectionName,"bSolarize",m_bSolarize ,szIniFile) != 0); + m_bInvert = (InternalGetPrivateProfileInt (szSectionName,"bInvert" ,m_bInvert ,szIniFile) != 0); + + m_fWaveAlpha = InternalGetPrivateProfileFloat(szSectionName,"fWaveAlpha",m_fWaveAlpha.eval(-1),szIniFile); + m_fWaveScale = InternalGetPrivateProfileFloat(szSectionName,"fWaveScale",m_fWaveScale.eval(-1),szIniFile); + m_fWaveSmoothing = InternalGetPrivateProfileFloat(szSectionName,"fWaveSmoothing",m_fWaveSmoothing.eval(-1),szIniFile); + m_fWaveParam = InternalGetPrivateProfileFloat(szSectionName,"fWaveParam",m_fWaveParam.eval(-1),szIniFile); + m_fModWaveAlphaStart = InternalGetPrivateProfileFloat(szSectionName,"fModWaveAlphaStart",m_fModWaveAlphaStart.eval(-1),szIniFile); + m_fModWaveAlphaEnd = InternalGetPrivateProfileFloat(szSectionName,"fModWaveAlphaEnd",m_fModWaveAlphaEnd.eval(-1),szIniFile); + m_fWarpAnimSpeed = InternalGetPrivateProfileFloat(szSectionName,"fWarpAnimSpeed",m_fWarpAnimSpeed,szIniFile); + m_fWarpScale = InternalGetPrivateProfileFloat(szSectionName,"fWarpScale",m_fWarpScale.eval(-1),szIniFile); + m_fZoomExponent = InternalGetPrivateProfileFloat(szSectionName,"fZoomExponent",m_fZoomExponent.eval(-1),szIniFile); + m_fShader = InternalGetPrivateProfileFloat(szSectionName,"fShader",m_fShader.eval(-1),szIniFile); + + m_fZoom = InternalGetPrivateProfileFloat(szSectionName,"zoom",m_fZoom.eval(-1),szIniFile); + m_fRot = InternalGetPrivateProfileFloat(szSectionName,"rot",m_fRot.eval(-1),szIniFile); + m_fRotCX = InternalGetPrivateProfileFloat(szSectionName,"cx",m_fRotCX.eval(-1),szIniFile); + m_fRotCY = InternalGetPrivateProfileFloat(szSectionName,"cy",m_fRotCY.eval(-1),szIniFile); + m_fXPush = InternalGetPrivateProfileFloat(szSectionName,"dx",m_fXPush.eval(-1),szIniFile); + m_fYPush = InternalGetPrivateProfileFloat(szSectionName,"dy",m_fYPush.eval(-1),szIniFile); + m_fWarpAmount = InternalGetPrivateProfileFloat(szSectionName,"warp",m_fWarpAmount.eval(-1),szIniFile); + m_fStretchX = InternalGetPrivateProfileFloat(szSectionName,"sx",m_fStretchX.eval(-1),szIniFile); + m_fStretchY = InternalGetPrivateProfileFloat(szSectionName,"sy",m_fStretchY.eval(-1),szIniFile); + m_fWaveR = InternalGetPrivateProfileFloat(szSectionName,"wave_r",m_fRot.eval(-1),szIniFile); + m_fWaveG = InternalGetPrivateProfileFloat(szSectionName,"wave_g",m_fRot.eval(-1),szIniFile); + m_fWaveB = InternalGetPrivateProfileFloat(szSectionName,"wave_b",m_fRot.eval(-1),szIniFile); + m_fWaveX = InternalGetPrivateProfileFloat(szSectionName,"wave_x",m_fRot.eval(-1),szIniFile); + m_fWaveY = InternalGetPrivateProfileFloat(szSectionName,"wave_y",m_fRot.eval(-1),szIniFile); + + m_fOuterBorderSize = InternalGetPrivateProfileFloat(szSectionName,"ob_size",m_fOuterBorderSize.eval(-1),szIniFile); + m_fOuterBorderR = InternalGetPrivateProfileFloat(szSectionName,"ob_r", m_fOuterBorderR.eval(-1),szIniFile); + m_fOuterBorderG = InternalGetPrivateProfileFloat(szSectionName,"ob_g", m_fOuterBorderG.eval(-1),szIniFile); + m_fOuterBorderB = InternalGetPrivateProfileFloat(szSectionName,"ob_b", m_fOuterBorderB.eval(-1),szIniFile); + m_fOuterBorderA = InternalGetPrivateProfileFloat(szSectionName,"ob_a", m_fOuterBorderA.eval(-1),szIniFile); + m_fInnerBorderSize = InternalGetPrivateProfileFloat(szSectionName,"ib_size",m_fInnerBorderSize.eval(-1),szIniFile); + m_fInnerBorderR = InternalGetPrivateProfileFloat(szSectionName,"ib_r", m_fInnerBorderR.eval(-1),szIniFile); + m_fInnerBorderG = InternalGetPrivateProfileFloat(szSectionName,"ib_g", m_fInnerBorderG.eval(-1),szIniFile); + m_fInnerBorderB = InternalGetPrivateProfileFloat(szSectionName,"ib_b", m_fInnerBorderB.eval(-1),szIniFile); + m_fInnerBorderA = InternalGetPrivateProfileFloat(szSectionName,"ib_a", m_fInnerBorderA.eval(-1),szIniFile); + m_fMvX = InternalGetPrivateProfileFloat(szSectionName,"nMotionVectorsX", m_fMvX.eval(-1),szIniFile); + m_fMvY = InternalGetPrivateProfileFloat(szSectionName,"nMotionVectorsY", m_fMvY.eval(-1),szIniFile); + m_fMvDX = InternalGetPrivateProfileFloat(szSectionName,"mv_dx", m_fMvDX.eval(-1),szIniFile); + m_fMvDY = InternalGetPrivateProfileFloat(szSectionName,"mv_dy", m_fMvDY.eval(-1),szIniFile); + m_fMvL = InternalGetPrivateProfileFloat(szSectionName,"mv_l", m_fMvL.eval(-1),szIniFile); + m_fMvR = InternalGetPrivateProfileFloat(szSectionName,"mv_r", m_fMvR.eval(-1),szIniFile); + m_fMvG = InternalGetPrivateProfileFloat(szSectionName,"mv_g", m_fMvG.eval(-1),szIniFile); + m_fMvB = InternalGetPrivateProfileFloat(szSectionName,"mv_b", m_fMvB.eval(-1),szIniFile); + m_fMvA = (InternalGetPrivateProfileInt (szSectionName,"bMotionVectorsOn",false,szIniFile) == 0) ? 0.0f : 1.0f; // for backwards compatibility + m_fMvA = InternalGetPrivateProfileFloat(szSectionName,"mv_a", m_fMvA.eval(-1),szIniFile); + + for (int i=0; i= 8191-char_pos-1)) // or if we're out of space + { + bDone = true; + } + else + { + sprintf(&pStr[char_pos], "%s%c", szLine, LINEFEED_CONTROL_CHAR); + } + + char_pos += len + 1; + line++; + } + pStr[char_pos++] = 0; // null-terminate + } + */ + + RecompileExpressions(); +} + +void CState::FreeVarsAndCode() +{ + // free the compiled expressions + if (m_pf_codehandle) + { + freeCode(m_pf_codehandle); + m_pf_codehandle = NULL; + } + if (m_pp_codehandle) + { + freeCode(m_pp_codehandle); + m_pp_codehandle = NULL; + } + + for (int i=0; i= sizeof(src). + + int i2 = 0; + int len = strlen(src); + int bComment = false; + for (int i=0; im_fShowUserMessageUntilThisTime = g_plugin->GetTime(); + + char buf[8192*3]; + + if (flags & RECOMPILE_PRESET_CODE) + { + resetVars(m_pf_vars); + + // 1. compile AND EXECUTE preset init code + StripLinefeedCharsAndComments(m_szPerFrameInit, buf); + if (buf[0] && bReInit) + { + int pf_codehandle_init; + + if ( ! (pf_codehandle_init = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in 'per_frame_init' code", m_szDesc); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + + q_values_after_init_code[0] = 0; + q_values_after_init_code[1] = 0; + q_values_after_init_code[2] = 0; + q_values_after_init_code[3] = 0; + q_values_after_init_code[4] = 0; + q_values_after_init_code[5] = 0; + q_values_after_init_code[6] = 0; + q_values_after_init_code[7] = 0; + monitor_after_init_code = 0; + } + else + { + // now execute the code, save the values of q1..q8, and clean up the code! + + g_plugin->LoadPerFrameEvallibVars(g_plugin->m_pState); + + executeCode(pf_codehandle_init); + + q_values_after_init_code[0] = *var_pf_q1; + q_values_after_init_code[1] = *var_pf_q2; + q_values_after_init_code[2] = *var_pf_q3; + q_values_after_init_code[3] = *var_pf_q4; + q_values_after_init_code[4] = *var_pf_q5; + q_values_after_init_code[5] = *var_pf_q6; + q_values_after_init_code[6] = *var_pf_q7; + q_values_after_init_code[7] = *var_pf_q8; + monitor_after_init_code = *var_pf_monitor; + + freeCode(pf_codehandle_init); + pf_codehandle_init = NULL; + } + } + + // 2. compile preset per-frame code + StripLinefeedCharsAndComments(m_szPerFrameExpr, buf); + if (buf[0]) + { + if ( ! (m_pf_codehandle = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in 'per_frame' code", m_szDesc); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + } + } + + resetVars(NULL); + resetVars(m_pv_vars); + + // 3. compile preset per-pixel code + StripLinefeedCharsAndComments(m_szPerPixelExpr, buf); + if (buf[0]) + { + if ( ! (m_pp_codehandle = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in 'per_pixel' code", m_szDesc); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + } + } + + resetVars(NULL); + } + + if (flags & RECOMPILE_WAVE_CODE) + { + for (int i=0; im_szUserMessage, "warning: preset \"%s\": error in wave %d init code", m_szDesc, i); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + + *m_wave[i].var_pf_q1 = q_values_after_init_code[0]; + *m_wave[i].var_pf_q2 = q_values_after_init_code[1]; + *m_wave[i].var_pf_q3 = q_values_after_init_code[2]; + *m_wave[i].var_pf_q4 = q_values_after_init_code[3]; + *m_wave[i].var_pf_q5 = q_values_after_init_code[4]; + *m_wave[i].var_pf_q6 = q_values_after_init_code[5]; + *m_wave[i].var_pf_q7 = q_values_after_init_code[6]; + *m_wave[i].var_pf_q8 = q_values_after_init_code[7]; + m_wave[i].t_values_after_init_code[0] = 0; + m_wave[i].t_values_after_init_code[1] = 0; + m_wave[i].t_values_after_init_code[2] = 0; + m_wave[i].t_values_after_init_code[3] = 0; + m_wave[i].t_values_after_init_code[4] = 0; + m_wave[i].t_values_after_init_code[5] = 0; + m_wave[i].t_values_after_init_code[6] = 0; + m_wave[i].t_values_after_init_code[7] = 0; + } + else + { + // now execute the code, save the values of q1..q8, and clean up the code! + + g_plugin->LoadCustomWavePerFrameEvallibVars(g_plugin->m_pState, i); + + executeCode(codehandle_temp); + + m_wave[i].t_values_after_init_code[0] = *m_wave[i].var_pf_t1; + m_wave[i].t_values_after_init_code[1] = *m_wave[i].var_pf_t2; + m_wave[i].t_values_after_init_code[2] = *m_wave[i].var_pf_t3; + m_wave[i].t_values_after_init_code[3] = *m_wave[i].var_pf_t4; + m_wave[i].t_values_after_init_code[4] = *m_wave[i].var_pf_t5; + m_wave[i].t_values_after_init_code[5] = *m_wave[i].var_pf_t6; + m_wave[i].t_values_after_init_code[6] = *m_wave[i].var_pf_t7; + m_wave[i].t_values_after_init_code[7] = *m_wave[i].var_pf_t8; + + freeCode(codehandle_temp); + codehandle_temp = NULL; + } + } + resetVars(NULL); + } + + // 2. compile custom waveform per-frame code + StripLinefeedCharsAndComments(m_wave[i].m_szPerFrame, buf); + if (buf[0]) + { + resetVars(m_wave[i].m_pf_vars); + if ( ! (m_wave[i].m_pf_codehandle = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in wave %d per-frame code", m_szDesc, i); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + } + resetVars(NULL); + } + + // 3. compile custom waveform per-point code + StripLinefeedCharsAndComments(m_wave[i].m_szPerPoint, buf); + if (buf[0]) + { + resetVars(m_wave[i].m_pp_vars); + if ( ! (m_wave[i].m_pp_codehandle = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in wave %d per-point code", m_szDesc, i); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + } + resetVars(NULL); + } + } + } + + if (flags & RECOMPILE_SHAPE_CODE) + { + for (int i=0; im_szUserMessage, "warning: preset \"%s\": error in shape %d init code", m_szDesc, i); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + + *m_shape[i].var_pf_q1 = q_values_after_init_code[0]; + *m_shape[i].var_pf_q2 = q_values_after_init_code[1]; + *m_shape[i].var_pf_q3 = q_values_after_init_code[2]; + *m_shape[i].var_pf_q4 = q_values_after_init_code[3]; + *m_shape[i].var_pf_q5 = q_values_after_init_code[4]; + *m_shape[i].var_pf_q6 = q_values_after_init_code[5]; + *m_shape[i].var_pf_q7 = q_values_after_init_code[6]; + *m_shape[i].var_pf_q8 = q_values_after_init_code[7]; + m_shape[i].t_values_after_init_code[0] = 0; + m_shape[i].t_values_after_init_code[1] = 0; + m_shape[i].t_values_after_init_code[2] = 0; + m_shape[i].t_values_after_init_code[3] = 0; + m_shape[i].t_values_after_init_code[4] = 0; + m_shape[i].t_values_after_init_code[5] = 0; + m_shape[i].t_values_after_init_code[6] = 0; + m_shape[i].t_values_after_init_code[7] = 0; + } + else + { + // now execute the code, save the values of q1..q8, and clean up the code! + + g_plugin->LoadCustomShapePerFrameEvallibVars(g_plugin->m_pState, i); + + executeCode(codehandle_temp); + + m_shape[i].t_values_after_init_code[0] = *m_shape[i].var_pf_t1; + m_shape[i].t_values_after_init_code[1] = *m_shape[i].var_pf_t2; + m_shape[i].t_values_after_init_code[2] = *m_shape[i].var_pf_t3; + m_shape[i].t_values_after_init_code[3] = *m_shape[i].var_pf_t4; + m_shape[i].t_values_after_init_code[4] = *m_shape[i].var_pf_t5; + m_shape[i].t_values_after_init_code[5] = *m_shape[i].var_pf_t6; + m_shape[i].t_values_after_init_code[6] = *m_shape[i].var_pf_t7; + m_shape[i].t_values_after_init_code[7] = *m_shape[i].var_pf_t8; + + freeCode(codehandle_temp); + codehandle_temp = NULL; + } + } + #endif + resetVars(NULL); + } + + // 2. compile custom shape per-frame code + StripLinefeedCharsAndComments(m_shape[i].m_szPerFrame, buf); + if (buf[0]) + { + resetVars(m_shape[i].m_pf_vars); + #ifndef _NO_EXPR_ + if ( ! (m_shape[i].m_pf_codehandle = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in shape %d per-frame code", m_szDesc, i); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + } + #endif + resetVars(NULL); + } + + /* + // 3. compile custom shape per-point code + StripLinefeedCharsAndComments(m_shape[i].m_szPerPoint, buf); + if (buf[0]) + { + resetVars(m_shape[i].m_pp_vars); + #ifndef _NO_EXPR_ + if ( ! (m_shape[i].m_pp_codehandle = compileCode(buf))) + { + sprintf(g_plugin->m_szUserMessage, "warning: preset \"%s\": error in shape %d per-point code", m_szDesc, i); + g_plugin->m_fShowUserMessageUntilThisTime = g_plugin->GetTime() + 6.0f; + } + #endif + resetVars(NULL); + } + */ + } + } + } + #endif +} + + + + + + + + + + + +CBlendableFloat::CBlendableFloat() +{ + m_bBlending = false; +} + +CBlendableFloat::~CBlendableFloat() +{ +} + +//-------------------------------------------------------------------------------- + +float CBlendableFloat::eval(float fTime) +{ + if (fTime < 0) + { + return val; + } + + if (m_bBlending && (fTime > m_fBlendStartTime + m_fBlendDuration) || (fTime < m_fBlendStartTime)) + { + m_bBlending = false; + } + + if (!m_bBlending) + { + return val; + } + else + { + float mix = (fTime - m_fBlendStartTime) / m_fBlendDuration; + return (m_fBlendFrom*(1.0f - mix) + val*mix); + } +} + +//-------------------------------------------------------------------------------- + +void CBlendableFloat::StartBlendFrom(CBlendableFloat *f_from, float fAnimTime, float fDuration) +{ + if (fDuration < 0.001f) + return; + + m_fBlendFrom = f_from->eval(fAnimTime); + m_bBlending = true; + m_fBlendStartTime = fAnimTime; + m_fBlendDuration = fDuration; +} diff --git a/lib/vis_milkdrop/state.h b/lib/vis_milkdrop/state.h new file mode 100644 index 0000000..5f6b106 --- /dev/null +++ b/lib/vis_milkdrop/state.h @@ -0,0 +1,408 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#ifndef _MILKDROP_STATE_ +#define _MILKDROP_STATE_ 1 + + +#include +#include +#include + +#include "evallib/eval.h" +#include "md_defines.h" + +// flags for CState::RecompileExpressions(): +#define RECOMPILE_PRESET_CODE 1 +#define RECOMPILE_WAVE_CODE 2 +#define RECOMPILE_SHAPE_CODE 4 + +class CBlendableFloat +{ +public: + CBlendableFloat(); + ~CBlendableFloat(); + + float operator = (float f) { + val = f; + m_bBlending = false; + return val; + }; + float operator *= (float f) { + val *= f; + m_bBlending = false; + return val; + }; + float operator /= (float f) { + val /= f; + m_bBlending = false; + return val; + }; + float operator -= (float f) { + val -= f; + m_bBlending = false; + return val; + }; + float operator += (float f) { + val += f; + m_bBlending = false; + return val; + }; + + float eval(float fTime); // call this from animation code. if fTime < 0, it will return unblended 'val'. + void StartBlendFrom(CBlendableFloat *f_from, float fAnimTime, float fDuration); + +protected: + float val; + bool m_bBlending; + float m_fBlendStartTime; + float m_fBlendDuration; + float m_fBlendFrom; +}; + +class CShape +{ +public: + int Import(char* szSection, char* szFile, int i); + int Export(char* szSection, char* szFile, int i, FILE* fOut=NULL); + + int enabled; + int sides; + int additive; + int thickOutline; + int textured; + float x,y,rad,ang; + float r,g,b,a; + float r2,g2,b2,a2; + float border_r,border_g,border_b,border_a; + float tex_ang, tex_zoom; + + char m_szInit[8192]; // note: only executed once -> don't need to save codehandle + char m_szPerFrame[8192]; + //char m_szPerPoint[8192]; + int m_pf_codehandle; + //int m_pp_codehandle; + + // for per-frame expression evaluation: + varType m_pf_vars[EVAL_MAX_VARS]; + double *var_pf_time, *var_pf_fps; + double *var_pf_frame; + double *var_pf_progress; + double *var_pf_q1, *var_pf_q2, *var_pf_q3, *var_pf_q4, *var_pf_q5, *var_pf_q6, *var_pf_q7, *var_pf_q8; + double *var_pf_t1, *var_pf_t2, *var_pf_t3, *var_pf_t4, *var_pf_t5, *var_pf_t6, *var_pf_t7, *var_pf_t8; + double *var_pf_bass, *var_pf_mid, *var_pf_treb, *var_pf_bass_att, *var_pf_mid_att, *var_pf_treb_att; + double *var_pf_r, *var_pf_g, *var_pf_b, *var_pf_a; + double *var_pf_r2, *var_pf_g2, *var_pf_b2, *var_pf_a2; + double *var_pf_border_r, *var_pf_border_g, *var_pf_border_b, *var_pf_border_a; + double *var_pf_x, *var_pf_y, *var_pf_rad, *var_pf_ang; + double *var_pf_sides, *var_pf_textured, *var_pf_additive, *var_pf_thick; + double *var_pf_tex_zoom, *var_pf_tex_ang; + + // for per-point expression evaluation: + /* + varType m_pp_vars[EVAL_MAX_VARS]; + double *var_pp_time, *var_pp_fps; + double *var_pp_frame; + double *var_pp_progress; + double *var_pp_q1, *var_pp_q2, *var_pp_q3, *var_pp_q4, *var_pp_q5, *var_pp_q6, *var_pp_q7, *var_pp_q8; + double *var_pp_t1, *var_pp_t2, *var_pp_t3, *var_pp_t4, *var_pp_t5, *var_pp_t6, *var_pp_t7, *var_pp_t8; + double *var_pp_bass, *var_pp_mid, *var_pp_treb, *var_pp_bass_att, *var_pp_mid_att, *var_pp_treb_att; + double *var_pp_r, *var_pp_g, *var_pp_b, *var_pp_a; + double *var_pp_r2, *var_pp_g2, *var_pp_b2, *var_pp_a2; + double *var_pp_border_r, *var_pp_border_g, *var_pp_border_b, *var_pp_border_a; + double *var_pp_x, *var_pp_y, *var_pp_rad, *var_pp_ang, *var_pp_sides; + */ + + double t_values_after_init_code[8]; + +}; + +class CWave +{ +public: + int Import(char* szSection, char *szFile, int i); + int Export(char* szSection, char* szFile, int i, FILE* fOut=NULL); + + int enabled; + int samples; + int sep; + float scaling; + float smoothing; + float x,y,r,g,b,a; + int bSpectrum; + int bUseDots; + int bDrawThick; + int bAdditive; + + char m_szInit[8192]; // note: only executed once -> don't need to save codehandle + char m_szPerFrame[8192]; + char m_szPerPoint[8192]; + int m_pf_codehandle; + int m_pp_codehandle; + + // for per-frame expression evaluation: + varType m_pf_vars[EVAL_MAX_VARS]; + double *var_pf_time, *var_pf_fps; + double *var_pf_frame; + double *var_pf_progress; + double *var_pf_q1, *var_pf_q2, *var_pf_q3, *var_pf_q4, *var_pf_q5, *var_pf_q6, *var_pf_q7, *var_pf_q8; + double *var_pf_t1, *var_pf_t2, *var_pf_t3, *var_pf_t4, *var_pf_t5, *var_pf_t6, *var_pf_t7, *var_pf_t8; + double *var_pf_bass, *var_pf_mid, *var_pf_treb, *var_pf_bass_att, *var_pf_mid_att, *var_pf_treb_att; + double *var_pf_r, *var_pf_g, *var_pf_b, *var_pf_a; + + // for per-point expression evaluation: + varType m_pp_vars[EVAL_MAX_VARS]; + double *var_pp_time, *var_pp_fps; + double *var_pp_frame; + double *var_pp_progress; + double *var_pp_q1, *var_pp_q2, *var_pp_q3, *var_pp_q4, *var_pp_q5, *var_pp_q6, *var_pp_q7, *var_pp_q8; + double *var_pp_t1, *var_pp_t2, *var_pp_t3, *var_pp_t4, *var_pp_t5, *var_pp_t6, *var_pp_t7, *var_pp_t8; + double *var_pp_bass, *var_pp_mid, *var_pp_treb, *var_pp_bass_att, *var_pp_mid_att, *var_pp_treb_att; + double *var_pp_sample, *var_pp_value1, *var_pp_value2; + double *var_pp_x, *var_pp_y, *var_pp_r, *var_pp_g, *var_pp_b, *var_pp_a; + + double t_values_after_init_code[8]; + +}; + +typedef struct +{ + int type; + int in_var; + int out_var; + float constant; + float min; + float max; + float in_scale; + float amp; // for sine functions + float freq; // for sine functions + float freq2; // for sine functions + float phase; // for sine functions + float phase2; // for sine functions +} td_modifier; + + +//#define MAX_EVALS 8 + + +class CState +{ +public: + CState(); + ~CState(); + + void Default(); + void Randomize(int nMode); + void StartBlendFrom(CState *s_from, float fAnimTime, float fTimespan); + void Import(char *szSectionName, char *szIniFile); + bool Export(char *szSectionName, char *szIniFile); + void RecompileExpressions(int flags=0xFFFFFFFF, int bReInit=1); + + char m_szDesc[512]; // this is just the filename, without a path or extension. + //char m_szSection[256]; + + float m_fRating; // 0..5 + // post-processing: + CBlendableFloat m_fGammaAdj; // +0 -> +1.0 (double), +2.0 (triple)... + CBlendableFloat m_fVideoEchoZoom; + CBlendableFloat m_fVideoEchoAlpha; + float m_fVideoEchoAlphaOld; + int m_nVideoEchoOrientation; + int m_nVideoEchoOrientationOld; + + // fps-dependant: + CBlendableFloat m_fDecay; // 1.0 = none, 0.95 = heavy decay + + // other: + int m_nWaveMode; + int m_nOldWaveMode; + bool m_bAdditiveWaves; + CBlendableFloat m_fWaveAlpha; + CBlendableFloat m_fWaveScale; + CBlendableFloat m_fWaveSmoothing; + bool m_bWaveDots; + bool m_bWaveThick; + CBlendableFloat m_fWaveParam; // -1..1; 0 is normal + bool m_bModWaveAlphaByVolume; + CBlendableFloat m_fModWaveAlphaStart; // when relative volume hits this level, alpha -> 0 + CBlendableFloat m_fModWaveAlphaEnd; // when relative volume hits this level, alpha -> 1 + float m_fWarpAnimSpeed; // 1.0 = normal, 2.0 = double, 0.5 = half, etc. + CBlendableFloat m_fWarpScale; + CBlendableFloat m_fZoomExponent; + CBlendableFloat m_fShader; // 0 = no color shader, 1 = full color shader + bool m_bMaximizeWaveColor; + bool m_bTexWrap; + bool m_bDarkenCenter; + bool m_bRedBlueStereo; + bool m_bBrighten; + bool m_bDarken; + bool m_bSolarize; + bool m_bInvert; + /* + bool m_bPlates; + int m_nPlates; + CBlendableFloat m_fPlateAlpha; // 0 = off, 0.1 = barely visible, 1.0 = solid + CBlendableFloat m_fPlateR; + CBlendableFloat m_fPlateG; + CBlendableFloat m_fPlateB; + CBlendableFloat m_fPlateWidth; // 1.0=normal, 2.0=double, etc. + CBlendableFloat m_fPlateLength; // 1.0=normal, 2.0=double, etc. + float m_fPlateSpeed; // 1.0=normal, 2.0=double, etc. + bool m_bPlatesAdditive; + */ + + // map controls: + CBlendableFloat m_fZoom; + CBlendableFloat m_fRot; + CBlendableFloat m_fRotCX; + CBlendableFloat m_fRotCY; + CBlendableFloat m_fXPush; + CBlendableFloat m_fYPush; + CBlendableFloat m_fWarpAmount; + CBlendableFloat m_fStretchX; + CBlendableFloat m_fStretchY; + CBlendableFloat m_fWaveR; + CBlendableFloat m_fWaveG; + CBlendableFloat m_fWaveB; + CBlendableFloat m_fWaveX; + CBlendableFloat m_fWaveY; + CBlendableFloat m_fOuterBorderSize; + CBlendableFloat m_fOuterBorderR; + CBlendableFloat m_fOuterBorderG; + CBlendableFloat m_fOuterBorderB; + CBlendableFloat m_fOuterBorderA; + CBlendableFloat m_fInnerBorderSize; + CBlendableFloat m_fInnerBorderR; + CBlendableFloat m_fInnerBorderG; + CBlendableFloat m_fInnerBorderB; + CBlendableFloat m_fInnerBorderA; + CBlendableFloat m_fMvX; + CBlendableFloat m_fMvY; + CBlendableFloat m_fMvDX; + CBlendableFloat m_fMvDY; + CBlendableFloat m_fMvL; + CBlendableFloat m_fMvR; + CBlendableFloat m_fMvG; + CBlendableFloat m_fMvB; + CBlendableFloat m_fMvA; + + CShape m_shape[MAX_CUSTOM_SHAPES]; + CWave m_wave[MAX_CUSTOM_WAVES]; + + //COscillator m_waveR; + //COscillator m_waveG; + //COscillator m_waveB; + //COscillator m_wavePosX; // 0 = centered + //COscillator m_wavePosY; // 0 = centered + + // for arbitrary function evaluation: + int m_pf_codehandle; + int m_pp_codehandle; + char m_szPerFrameInit[8192]; + char m_szPerFrameExpr[8192]; + //char m_szPerPixelInit[8192]; + char m_szPerPixelExpr[8192]; + void FreeVarsAndCode(); + void RegisterBuiltInVariables(int flags); + void StripLinefeedCharsAndComments(char *src, char *dest); + + bool m_bBlending; + float m_fBlendStartTime; + float m_fBlendDuration; + float m_fBlendProgress; // 0..1; updated every frame based on StartTime and Duration. + + // for once-per-frame expression evaluation: + varType m_pf_vars[EVAL_MAX_VARS]; + double *var_pf_zoom, *var_pf_zoomexp, *var_pf_rot, *var_pf_warp, *var_pf_cx, *var_pf_cy, *var_pf_dx, *var_pf_dy, *var_pf_sx, *var_pf_sy; + double *var_pf_time, *var_pf_fps; + double *var_pf_bass, *var_pf_mid, *var_pf_treb, *var_pf_bass_att, *var_pf_mid_att, *var_pf_treb_att; + double *var_pf_wave_a, *var_pf_wave_r, *var_pf_wave_g, *var_pf_wave_b, *var_pf_wave_x, *var_pf_wave_y, *var_pf_wave_mystery, *var_pf_wave_mode; + double *var_pf_decay; + double *var_pf_frame; + double *var_pf_q1, *var_pf_q2, *var_pf_q3, *var_pf_q4, *var_pf_q5, *var_pf_q6, *var_pf_q7, *var_pf_q8; + double *var_pf_progress; + double *var_pf_ob_size, *var_pf_ob_r, *var_pf_ob_g, *var_pf_ob_b, *var_pf_ob_a; + double *var_pf_ib_size, *var_pf_ib_r, *var_pf_ib_g, *var_pf_ib_b, *var_pf_ib_a; + double *var_pf_mv_x; + double *var_pf_mv_y; + double *var_pf_mv_dx; + double *var_pf_mv_dy; + double *var_pf_mv_l; + double *var_pf_mv_r; + double *var_pf_mv_g; + double *var_pf_mv_b; + double *var_pf_mv_a; + double *var_pf_monitor; + double *var_pf_echo_zoom, *var_pf_echo_alpha, *var_pf_echo_orient; + // new in v1.04: + double *var_pf_wave_usedots, *var_pf_wave_thick, *var_pf_wave_additive, *var_pf_wave_brighten; + double *var_pf_darken_center, *var_pf_gamma, *var_pf_wrap; + double *var_pf_invert, *var_pf_brighten, *var_pf_darken, *var_pf_solarize; + double *var_pf_meshx, *var_pf_meshy; + // NOTE: IF YOU ADD NEW VARIABLES, BE SURE TO INCREASE THE VALUE OF + // 'EVAL_MAX_VARS' IN EVAL.H. OTHERWISE, SOME PRESETS MIGHT BREAK. + + + // for per-vertex expression evaluation: + varType m_pv_vars[EVAL_MAX_VARS]; + double *var_pv_zoom, *var_pv_zoomexp, *var_pv_rot, *var_pv_warp, *var_pv_cx, *var_pv_cy, *var_pv_dx, *var_pv_dy, *var_pv_sx, *var_pv_sy; + double *var_pv_time, *var_pv_fps; + double *var_pv_bass, *var_pv_mid, *var_pv_treb, *var_pv_bass_att, *var_pv_mid_att, *var_pv_treb_att; + double *var_pv_x, *var_pv_y, *var_pv_rad, *var_pv_ang; + double *var_pv_frame; + double *var_pv_q1, *var_pv_q2, *var_pv_q3, *var_pv_q4, *var_pv_q5, *var_pv_q6, *var_pv_q7, *var_pv_q8; + double *var_pv_progress; + double *var_pv_meshx, *var_pv_meshy; + + double q_values_after_init_code[8]; + double monitor_after_init_code; +}; + + + + + + + + + + + + + + + + + + + + + + +#endif \ No newline at end of file diff --git a/lib/vis_milkdrop/support.cpp b/lib/vis_milkdrop/support.cpp new file mode 100644 index 0000000..21c6375 --- /dev/null +++ b/lib/vis_milkdrop/support.cpp @@ -0,0 +1,509 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +#include "support.h" +#include "utility.h" +#include "md_defines.h" +#include +#include +#include + +bool g_bDebugOutput = false; +bool g_bDumpFileCleared = false; + +//--------------------------------------------------- +void PrepareFor3DDrawing( + IDirect3DDevice9 *pDevice, + int viewport_width, + int viewport_height, + float fov_in_degrees, + float near_clip, + float far_clip, + D3DXVECTOR3* pvEye, + D3DXVECTOR3* pvLookat, + D3DXVECTOR3* pvUp + ) +{ +#if 0 + + // This function sets up DirectX up for 3D rendering. + // Only call it once per frame, as it is VERY slow. + // INPUTS: + // pDevice a pointer to the D3D device + // viewport_width the width of the client area of the window + // viewport_height the height of the client area of the window + // fov_in_degrees the field of view, in degrees + // near_clip the distance to the near clip plane; should be > 0! + // far_clip the distance to the far clip plane + // eye the eyepoint coordinates, in world space + // lookat the point toward which the eye is looking, in world space + // up a vector indicating which dir. is up; usually <0,1,0> + // + // What this function does NOT do: + // 1. set the current texture (SetTexture) + // 2. set up the texture stages for texturing (SetTextureStageState) + // 3. set the current vertex format (SetVertexShader) + // 4. set up the world matrix (SetTransform(D3DTS_WORLD, &my_world_matrix)) + + + // set up render state to some nice defaults: + { + // some defaults + d3dSetRenderState( D3DRS_ZENABLE, TRUE ); + d3dSetRenderState( D3DRS_ZWRITEENABLE, TRUE ); + d3dSetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); + d3dSetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); +// d3dSetRenderState( D3DRS_CLIPPING, TRUE ); + d3dSetRenderState( D3DRS_LIGHTING, FALSE ); + d3dSetRenderState( D3DRS_COLORVERTEX, TRUE ); + d3dSetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD ); + d3dSetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + d3dSetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + + // turn fog off + d3dSetRenderState( D3DRS_FOGENABLE, FALSE ); + d3dSetRenderState( D3DRS_RANGEFOGENABLE, FALSE ); + + // turn on high-quality bilinear interpolations + pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + pDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + pDevice->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + } + + // set up view & projection matrices (but not the world matrix!) + { + // if the window is not square, instead of distorting the scene, + // clip it so that the longer dimension of the window has the + // regular FOV, and the shorter dimension has a reduced FOV. + float fov_x = fov_in_degrees * 3.1415927f/180.0f; + float fov_y = fov_in_degrees * 3.1415927f/180.0f; + float aspect = (float)viewport_height / (float)viewport_width; + if (aspect < 1) + fov_y *= aspect; + else + fov_x /= aspect; + + if (near_clip < 0.1f) + near_clip = 0.1f; + if (far_clip < near_clip + 1.0f) + far_clip = near_clip + 1.0f; + + D3DXMATRIX proj; + MakeProjectionMatrix(&proj, near_clip, far_clip, fov_x, fov_y); + pDevice->SetTransform(D3DTS_PROJECTION, &proj); + + D3DXMATRIX view; + D3DXMatrixLookAtLH(&view, pvEye, pvLookat, pvUp); + pDevice->SetTransform(D3DTS_VIEW, &view); + + // Optimization note: "You can minimize the number of required calculations + // by concatenating your world and view matrices into a world-view matrix + // that you set as the world matrix, and then setting the view matrix + // to the identity." + //D3DXMatrixMultiply(&world, &world, &view); + //D3DXMatrixIdentity(&view); + } +#endif +} + +void PrepareFor2DDrawing(IDirect3DDevice9 *pDevice) +{ + // New 2D drawing area will have x,y coords in the range <-1,-1> .. <1,1> + // +--------+ Y=-1 + // | | + // | screen | Z=0: front of scene + // | | Z=1: back of scene + // +--------+ Y=1 + // X=-1 X=1 + // NOTE: After calling this, be sure to then call (at least): + // 1. SetVertexShader() + // 2. SetTexture(), if you need it + // before rendering primitives! + // Also, be sure your sprites have a z coordinate of 0. + pDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); + pDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE ); + pDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); + pDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT ); + pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + pDevice->SetRenderState( D3DRS_FOGENABLE, FALSE ); + pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); +// d3dSetRenderState( D3DRS_CLIPPING, TRUE ); + pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); + pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + pDevice->SetRenderState( D3DRS_LOCALVIEWER, FALSE ); + + pDevice->SetTexture(0, NULL); + pDevice->SetTexture(1, NULL); +// SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR); +// SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR); + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + pDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT ); + pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE ); + + pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); + pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); + pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + + pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + + // set up for 2D drawing: + { + D3DXMATRIX Ortho2D; + D3DXMATRIX Identity; + + D3DXMatrixOrthoLH(&Ortho2D, 2.0f, -2.0f, 0.0f, 1.0f); + D3DXMatrixIdentity(&Identity); + + pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D); + pDevice->SetTransform(D3DTS_WORLD, &Identity); + pDevice->SetTransform(D3DTS_VIEW, &Identity); + } +} + +//--------------------------------------------------- + +void MakeWorldMatrix( D3DXMATRIX* pOut, + float xpos, float ypos, float zpos, + float sx, float sy, float sz, + float pitch, float yaw, float roll) +{ +#if 0 + /* + * The m_xPos, m_yPos, m_zPos variables contain the model's + * location in world coordinates. + * The m_fPitch, m_fYaw, and m_fRoll variables are floats that + * contain the model's orientation in terms of pitch, yaw, and roll + * angles, in radians. + */ + + D3DXMATRIX MatTemp; + D3DXMatrixIdentity(pOut); + + // 1. first, rotation + if (pitch || yaw || roll) + { + D3DXMATRIX MatRot; + D3DXMatrixIdentity(&MatRot); + + D3DXMatrixRotationX(&MatTemp, pitch); // Pitch + D3DXMatrixMultiply(&MatRot, &MatRot, &MatTemp); + D3DXMatrixRotationY(&MatTemp, yaw); // Yaw + D3DXMatrixMultiply(&MatRot, &MatRot, &MatTemp); + D3DXMatrixRotationZ(&MatTemp, roll); // Roll + D3DXMatrixMultiply(&MatRot, &MatRot, &MatTemp); + + D3DXMatrixMultiply(pOut, pOut, &MatRot); + } + + // 2. then, scaling + D3DXMatrixScaling(&MatTemp, sx, sy, sz); + D3DXMatrixMultiply(pOut, pOut, &MatTemp); + + // 3. last, translation to final world pos. + D3DXMatrixTranslation(&MatTemp, xpos, ypos, zpos); + D3DXMatrixMultiply(pOut, pOut, &MatTemp); +#endif +} + +void MakeProjectionMatrix( D3DXMATRIX* pOut, + const float near_plane, // Distance to near clipping plane + const float far_plane, // Distance to far clipping plane + const float fov_horiz, // Horizontal field of view angle, in radians + const float fov_vert) // Vertical field of view angle, in radians +{ + float w = (float)1/tanf(fov_horiz*0.5f); // 1/tan(x) == cot(x) + float h = (float)1/tanf(fov_vert*0.5f); // 1/tan(x) == cot(x) + float Q = far_plane/(far_plane - near_plane); + + ZeroMemory(pOut, sizeof(D3DXMATRIX)); + pOut->_11 = w; + pOut->_22 = h; + pOut->_33 = Q; + pOut->_43 = -Q*near_plane; + pOut->_34 = 1; +} + +//--------------------------------------------------- + +void GetWinampSongTitle(HWND hWndWinamp, char *szSongTitle, int nSize) +{ + szSongTitle[0] = 0; +#if 0 + if (::GetWindowText(hWndWinamp, szSongTitle, nSize)) + { + // remove ' - Winamp' if found at end + if (strlen(szSongTitle) > 9) + { + int check_pos = strlen(szSongTitle) - 9; + if (strcmp(" - Winamp", (char *)(szSongTitle + check_pos)) == 0) + szSongTitle[check_pos] = 0; + } + + // remove ' - Winamp [Paused]' if found at end + if (strlen(szSongTitle) > 18) + { + int check_pos = strlen(szSongTitle) - 18; + if (strcmp(" - Winamp [Paused]", (char *)(szSongTitle + check_pos)) == 0) + szSongTitle[check_pos] = 0; + } + + // remove song # and period from beginning + char *p = szSongTitle; + while (*p >= '0' && *p <= '9') p++; + if (*p == '.' && *(p+1) == ' ') + { + p += 2; + int pos = 0; + while (*p != 0) + { + szSongTitle[pos++] = *p; + p++; + } + szSongTitle[pos++] = 0; + } + + // fix &'s for display + // note: this is not necessary if you use the DT_NOPREFIX flag with text drawing functions! + /* + { + int pos = 0; + int len = strlen(szSongTitle); + while (szSongTitle[pos]) + { + if (szSongTitle[pos] == '&') + { + for (int x=len; x>=pos; x--) + szSongTitle[x+1] = szSongTitle[x]; + len++; + pos++; + } + pos++; + } + }*/ + } +#endif +} + +void GetWinampSongPosAsText(HWND hWndWinamp, char *szSongPos) +{ + // note: size(szSongPos[]) must be at least 64. + + szSongPos[0] = 0; + +#if 0 + int nSongPosMS = SendMessage(hWndWinamp,WM_USER,0,105); + if (nSongPosMS > 0) + { + float time_s = nSongPosMS*0.001f; + int minutes = (int)(time_s/60); + time_s -= minutes*60; + int seconds = (int)time_s; + time_s -= seconds; + int dsec = (int)(time_s*100); + sprintf(szSongPos, "%d:%02d.%02d", minutes, seconds, dsec); + } + +#endif +} + +void GetWinampSongLenAsText(HWND hWndWinamp, char *szSongLen) +{ + // note: size(szSongLen[]) must be at least 64. + szSongLen[0] = 0; +#if 0 + int nSongLenMS = SendMessage(hWndWinamp,WM_USER,1,105)*1000; + if (nSongLenMS > 0) + { + int len_s = nSongLenMS/1000; + int minutes = len_s/60; + int seconds = len_s - minutes*60; + sprintf(szSongLen, "%d:%02d", minutes, seconds); + } +#endif +} + +float GetWinampSongPos(HWND hWndWinamp) +{ + // returns answer in seconds +// return (float)SendMessage(hWndWinamp,WM_USER,0,105)*0.001f; + return 0; +} + +float GetWinampSongLen(HWND hWndWinamp) +{ + // returns answer in seconds +// return (float)SendMessage(hWndWinamp,WM_USER,1,105); + return 0; +} + +/* +void g_dumpmsg(char *s) +{ + if (g_bDebugOutput) + { + if (!g_bDumpFileCleared) + { + g_bDumpFileCleared = true; + FILE *infile = fopen(DEBUGFILE, "w"); + if (infile) + { + fprintf(infile, DEBUGFILEHEADER); + fclose(infile); + } + } + + FILE *infile2; + infile2 = fopen(DEBUGFILE, "a"); + if (infile2) + { + fprintf(infile2, "%s\n", s); + OutputDebugString(s); + OutputDebugString("\n"); + fclose(infile2); + } + } +} + +void ClipWindowToScreen(RECT *rect) +{ + int screen_width = GetSystemMetrics(SM_CXSCREEN); + int screen_height = GetSystemMetrics(SM_CYSCREEN); + + // make sure it's not too small + if (rect->right - rect->left < 64) + rect->right = rect->left + 64; + if (rect->bottom - rect->top < 64) + rect->bottom = rect->top + 64; + + // make sure it's not too big + if (rect->right - rect->left > screen_width) + rect->right = rect->left + screen_width; + if (rect->bottom - rect->top > screen_height) + rect->bottom = rect->top + screen_height; + + // clip vs. screen edges + if (rect->top < 0) + { + rect->bottom -= rect->top; + rect->top = 0; + } + + if (rect->top > screen_height - 64) + { + rect->bottom += (screen_height - 64) - rect->top; + rect->top = screen_height - 64; + } + + if (rect->right < 64) + { + rect->left -= rect->right - 64; + rect->right = 64; + } + + if (rect->left > screen_width - 64) + { + rect->right += (screen_width - 64) - rect->left; + rect->left = screen_width - 64; + } +} +*/ + +const unsigned char LC2UC[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,255, + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, + 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, + 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, + 113,114,115,116,117,118,119,120,121,122,91,92,93,94,95,96, + 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, + 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, + 129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144, + 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160, + 161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, + 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, + 193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208, + 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224, + 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240, + 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; + +int mystrcmpi(char *s1, char *s2) +{ + // returns 1 if s1 comes before s2 + // returns 0 if equal + // returns -1 if s1 comes after s2 + // treats all characters/symbols by their ASCII values, + // except that it DOES ignore case. + + int i=0; + + while (LC2UC[s1[i]] == LC2UC[s2[i]] && s1[i] != 0) + i++; + + //FIX THIS! + + if (s1[i]==0 && s2[i]==0) + return 0; + else if (s1[i]==0) + return -1; + else if (s2[i]==0) + return 1; + else + return (LC2UC[s1[i]] < LC2UC[s2[i]]) ? -1 : 1; +} + +void SetScrollLock(bool bNewState) +{ +#if 0 + if (bNewState != (bool)(GetKeyState(VK_SCROLL) & 1)) + { + // Simulate a key press + keybd_event( VK_SCROLL, + 0x45, + KEYEVENTF_EXTENDEDKEY | 0, + 0 ); + + // Simulate a key release + keybd_event( VK_SCROLL, + 0x45, + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, + 0); + } +#endif +} diff --git a/lib/vis_milkdrop/support.h b/lib/vis_milkdrop/support.h new file mode 100644 index 0000000..61144d4 --- /dev/null +++ b/lib/vis_milkdrop/support.h @@ -0,0 +1,111 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __NULLSOFT_DX8_EXAMPLE_PLUGIN_SUPPORT_H__ +#define __NULLSOFT_DX8_EXAMPLE_PLUGIN_SUPPORT_H__ 1 +#include +//#include +#include + +//extern "C" void SetTextureStageState( int x, DWORD dwY, DWORD dwZ); +//extern "C" void d3dSetSamplerState( int x, DWORD dwY, DWORD dwZ); +//extern "C" void d3dSetRenderState(DWORD dwY, DWORD dwZ); + +void MakeWorldMatrix( D3DXMATRIX* pOut, + float xpos, float ypos, float zpos, + float sx, float sy, float sz, + float pitch, float yaw, float roll); +void MakeProjectionMatrix( D3DXMATRIX* pOut, + const float near_plane, // Distance to near clipping plane + const float far_plane, // Distance to far clipping plane + const float fov_horiz, // Horizontal field of view angle, in radians + const float fov_vert); // Vertical field of view angle, in radians +void PrepareFor3DDrawing( + IDirect3DDevice9 *pDevice, + int viewport_width, + int viewport_height, + float fov_in_degrees, + float near_clip, + float far_clip, + D3DXVECTOR3* pvEye, + D3DXVECTOR3* pvLookat, + D3DXVECTOR3* pvUp + ); +void PrepareFor2DDrawing(IDirect3DDevice9 *pDevice); + +// Define vertex formats you'll be using here: +typedef struct _MYVERTEX +{ + float x, y; // screen position + float z; // Z-buffer depth + DWORD Diffuse; // diffuse color + float tu1, tv1; // texture coordinates for texture #0 + float tu2, tv2; // texture coordinates for texture #1 + // note: even though tu2/tv2 aren't used when multitexturing is off, + // they are still useful for padding the structure to 32 bytes, + // which is good for random (indexed) access. +} MYVERTEX, *LPMYVERTEX; + +typedef struct _WFVERTEX +{ + float x, y, z; + DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims) +} WFVERTEX, *LPWFVERTEX; + +typedef struct _SPRITEVERTEX +{ + float x, y; // screen position + float z; // Z-buffer depth + DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims) + float tu, tv; // texture coordinates for texture #0 +} SPRITEVERTEX, *LPSPRITEVERTEX; + +// Also prepare vertex format descriptors for each +// of the 3 kinds of vertices we'll be using: +#define MYVERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2) +#define WFVERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE ) +#define SPRITEVERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1) + +#define IsAlphabetChar(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')) +#define IsAlphanumericChar(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || (x >= '0' && x <= '9') || x == '.') + +void GetWinampSongTitle(HWND hWndWinamp, char *szSongTitle, int nSize); +void GetWinampSongPosAsText(HWND hWndWinamp, char *szSongPos); +void GetWinampSongLenAsText(HWND hWndWinamp, char *szSongLen); +float GetWinampSongPos(HWND hWndWinamp); // returns answer in seconds +float GetWinampSongLen(HWND hWndWinamp); // returns answer in seconds + +//void g_dumpmsg(char *s); +//void ClipWindowToScreen(RECT *rect); +int mystrcmpi(char *s1, char *s2); +void SetScrollLock(bool bNewState); + + +#endif diff --git a/lib/vis_milkdrop/utility.cpp b/lib/vis_milkdrop/utility.cpp new file mode 100644 index 0000000..cba6aea --- /dev/null +++ b/lib/vis_milkdrop/utility.cpp @@ -0,0 +1,1762 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "utility.h" +#include +#include +#include +//#include +#include + +float PowCosineInterp(float x, float pow) +{ + // input (x) & output should be in range 0..1. + // pow > 0: tends to push things toward 0 and 1 + // pow < 0: tends to push things toward 0.5. + + if (x<0) + return 0; + if (x>1) + return 1; + + int bneg = (pow < 0) ? 1 : 0; + if (bneg) + pow = -pow; + + if (pow>1000) pow=1000; + + int its = (int)pow; + for (int i=0; i0)&&(size>4)) + { + fread(&chr,sizeof(char),1,Fh); + fsize--; + + if((chr==0x0a)||(chr==0x0d)) + { + if(strcount) + { + while (ReturnBuffer[-1]==32) + { + ReturnBuffer--; + size++; + } + + ReturnBuffer[0] = 0; + ReturnBuffer++; + size--; + } + break; + } + else + { + if (chr==0x09) chr=32; + ReturnBuffer[0] = chr; + ReturnBuffer++; + size--; + strcount++; + } + } + } + } + + while (ReturnBuffer[-1]==32) + { + ReturnBuffer--; + size++; + } + + ReturnBuffer[0] = 0; + ReturnBuffer[1] = 0; +} + +int InternalGetPrivateProfileSection(char *Group,char *ReturnBuffer,int size,char *filename) +{ + FILE* Fh; + int fsize; + char chr; + int count; + int strcount; + char tmpbuf[256]; + + count = 0; + + Fh = fopen(filename,"rb"); + if(Fh==0) return(0); + + fseek(Fh, 0, SEEK_END); + fsize = ftell(Fh); + fseek(Fh,0, SEEK_SET); + + while((fsize>0)&&(size>4)) + { + fread(&chr,sizeof(char),1,Fh); + fsize--; + + if(chr=='[') + { + strcount = 0; + + while((fsize>0)&&(size>4)) + { + fread(&chr,sizeof(char),1,Fh); + fsize--; + + if(chr==']') + { + if(strcount) + { + tmpbuf[strcount] = 0; + + // string found, check against 'group' + + if(stricmp(Group,tmpbuf)==0) + { + // got it! + + InternalGetPrivateProfileSectionData(Fh,fsize,ReturnBuffer,size); + fclose(Fh); + return(0); + } + } + break; + } + else + { + tmpbuf[strcount] = chr; + strcount++; + } + } + } + } + + ReturnBuffer[0] = 0; + ReturnBuffer[1] = 0; + + fclose(Fh); + return(0); +} + +bool validIniFile = false; +char* iniFile = NULL; +char currIniFilename[MAX_PATH]; +char currIniSection[256]; +int iniFileSize = 0; + + +int InternalGetPrivateProfileString(char *szSectionName, char *szKeyName, char *szDefault, char *buffer, int size, char *szIniFile) +{ + bool newFile = false; + + if (stricmp(currIniFilename, szIniFile)) + { + // Load new ini file + newFile = true; + + FILE* handle; + + handle = fopen(szIniFile, "rb"); + if (handle == 0) + { + validIniFile = false; + GetFromSectionCache(szKeyName, szDefault, buffer, size); + return (strlen(buffer)); + } + + fseek(Fh, 0, SEEK_END); + iniFileSize = ftell(Fh); + fseek(Fh,0, SEEK_SET); + + iniFile = new char[iniFileSize]; + fread(iniFile, iniFileSize, 1, handle); + fclose(iniFile); + } + + if (newFile || stricmp(currIniSection, szSectionName)) + { + + } + + + +/* + + if (stricmp(INIfsp, szIniFile)!=0 || stricmp(INIsection, szSectionName)!=0) + { + InternalGetPrivateProfileSection(szSectionName, INITempBuffer, INITEMPBUFFERSIZE, szIniFile); + strcpy(INIfsp, szIniFile); + strcpy(INIsection, szSectionName); + } + + GetFromINIArray(INITempBuffer, szKeyName, szDefault, buffer, size); + return(strlen(buffer)); +*/ +} + +#endif + +#define SECTION_CACHE_SIZE (1024 * 40) +bool validIni = false; +char currIniFilename[MAX_PATH]; +char currIniSection[256]; +char sectionCache[SECTION_CACHE_SIZE]; + + +void GetFromCache(char *cache, char *key, char *szDefault, char *buffer, int buffersize) +{ + char *p; + + memcpy(buffer, szDefault, buffersize); // Copy default + + if (!validIni) + return; + + int keyLength = strlen(key); + + while (cache[0] != 0 || cache[1] != 0) + { + if (strnicmp(key, cache, keyLength)==0) + { + if (cache[keyLength] == '=') + { + p = strchr(cache, '='); + if (p) + { + p++; + while(*p==32) + p++; + + memcpy(buffer, p, buffersize); + return; + } + } + } + cache += strlen(cache)+1; + } + +} + +void InternalGetPrivateProfileSection(char *szSectionName, char *buffer, int size, char *szIniFile) +{ + FILE* handle; + int fileSize; + char tempSectionName[256]; + int strIndex; + char* fileData; + char* filePtr; + char c; + + validIni = false; + + handle = fopen(szIniFile, "rb"); + + if (handle == 0) + { + return; + } + + fseek(handle, 0, SEEK_END); + fileSize = ftell(handle); + fseek(handle,0, SEEK_SET); + fileData = new char[fileSize]; + fread(fileData, fileSize, 1, handle); + fclose(handle); + + filePtr = fileData; + + while (fileSize > 0) + { + c = *filePtr++; + fileSize--; + + if (c == '[') + { + // Start of section name + strIndex = 0; + + while (fileSize > 0) + { + c = *filePtr++; + fileSize--; + + if (c == ']') + { + // End of section name, check if its the one we want + tempSectionName[strIndex] = 0; + + if (stricmp(szSectionName, tempSectionName) == 0) + { + while (fileSize > 0) + { + c = *filePtr++; + fileSize--; + + if ((c > ' ') && (c <='z')) + { + if (c == '[') + break; // end of section + + strIndex = 0; + + buffer[0] = c; + buffer++; + size--; + strIndex++; + + if (size == 0) + { + OutputDebugString("Section cache size too small.\n"); + delete[] fileData; + return; + } + + while (fileSize > 0) + { + c = *filePtr++; + fileSize--; + + if ((c == 0x0a) || (c == 0x0d)) + { + if (strIndex) + { + while (buffer[-1] == 32) + { + buffer--; + size++; + } + + buffer[0] = 0; + buffer++; + size--; + } + break; + } + else + { +// if (c == 0x09) +// c = 32; + if (c != 0x09 && c != 32) + { + buffer[0] = c; + buffer++; + size--; + strIndex++; + + if (size == 0) + { + OutputDebugString("Section cache size too small.\n"); + delete[] fileData; + return; + } + } + } + } + } + } + + while (buffer[-1] == 32) + { + buffer--; + size++; + } + + buffer[0] = 0; + buffer[1] = 0; + + delete[] fileData; + validIni = true; + return; + } + break; + } + else + { + tempSectionName[strIndex] = c; + strIndex++; + } + } + } + } + + delete[] fileData; + +} + +int InternalGetPrivateProfileString(char *szSectionName, char *szKeyName, char *szDefault, char *buffer, int size, char *szIniFile) +{ + if (stricmp(currIniFilename, szIniFile) || stricmp(currIniSection, szSectionName)) + { + InternalGetPrivateProfileSection(szSectionName, sectionCache, SECTION_CACHE_SIZE, szIniFile); + + strcpy(currIniFilename, szIniFile); + strcpy(currIniSection, szSectionName); + } + + GetFromCache(sectionCache, szKeyName, szDefault, buffer, size); + + return (strlen(buffer)); +} + +int InternalGetPrivateProfileInt(char *szSectionName, char *szKeyName, int iDefault, char *szIniFile) +{ + char string[64]; + char szDefault[64]; + int ret = iDefault; + + sprintf(szDefault, "%d", iDefault); + if (InternalGetPrivateProfileString(szSectionName, szKeyName, szDefault, string, 64, szIniFile) > 0) + { + sscanf(string, "%d", &ret); + } + + return ret; +} + +float InternalGetPrivateProfileFloat(char *szSectionName, char *szKeyName, float fDefault, char *szIniFile) +{ + char string[64]; + char szDefault[64]; + float ret = fDefault; + + sprintf(szDefault, "%f", fDefault); + + if (InternalGetPrivateProfileString(szSectionName, szKeyName, szDefault, string, 64, szIniFile) > 0) + { + sscanf(string, "%f", &ret); + } + + return ret; +} + +bool WritePrivateProfileFloat(float f, char *szKeyName, char *szIniFile, char *szSectionName) +{ +// char szValue[32]; +// sprintf(szValue, "%f", f); +// return (WritePrivateProfileString(szSectionName, szKeyName, szValue, szIniFile) != 0); + return true; +} + +bool WritePrivateProfileInt(int d, char *szKeyName, char *szIniFile, char *szSectionName) +{ +// char szValue[32]; +// sprintf(szValue, "%d", d); +// return (WritePrivateProfileString(szSectionName, szKeyName, szValue, szIniFile) != 0); + return true; + +} + +void SetScrollLock(int bNewState) +{ +/* + if (bNewState != (GetKeyState(VK_SCROLL) & 1)) + { + // Simulate a key press + keybd_event( VK_SCROLL, + 0x45, + KEYEVENTF_EXTENDEDKEY | 0, + 0 ); + + // Simulate a key release + keybd_event( VK_SCROLL, + 0x45, + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, + 0); + } +*/ +} + +void RemoveExtension(char *str) +{ + char *p = strrchr(str, '.'); + if (p) *p = 0; +} + +void RemoveSingleAmpersands(char *str) +{ + int len = strlen(str); + int deleted = 0; + + for (int i=0; i 0) + str[i-deleted] = str[i]; + } + str[len-deleted] = 0; +} + +void TextToGuid(char *str, GUID *pGUID) +{ + if (!str) return; + if (!pGUID) return; + + DWORD d[11]; + + sscanf(str, "%u %u %u %u %u %u %u %u %u %u %u", + &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], &d[8], &d[9], &d[10]); + + pGUID->Data1 = (DWORD)d[0]; + pGUID->Data2 = (WORD)d[1]; + pGUID->Data3 = (WORD)d[2]; + pGUID->Data4[0] = (BYTE)d[3]; + pGUID->Data4[1] = (BYTE)d[4]; + pGUID->Data4[2] = (BYTE)d[5]; + pGUID->Data4[3] = (BYTE)d[6]; + pGUID->Data4[4] = (BYTE)d[7]; + pGUID->Data4[5] = (BYTE)d[8]; + pGUID->Data4[6] = (BYTE)d[9]; + pGUID->Data4[7] = (BYTE)d[10]; +} + +void GuidToText(GUID *pGUID, char *str, int nStrLen) +{ + // note: nStrLen should be set to sizeof(str). + if (!str) return; + if (!nStrLen) return; + str[0] = 0; + if (!pGUID) return; + + DWORD d[11]; + d[0] = (DWORD)pGUID->Data1; + d[1] = (DWORD)pGUID->Data2; + d[2] = (DWORD)pGUID->Data3; + d[3] = (DWORD)pGUID->Data4[0]; + d[4] = (DWORD)pGUID->Data4[1]; + d[5] = (DWORD)pGUID->Data4[2]; + d[6] = (DWORD)pGUID->Data4[3]; + d[7] = (DWORD)pGUID->Data4[4]; + d[8] = (DWORD)pGUID->Data4[5]; + d[9] = (DWORD)pGUID->Data4[6]; + d[10] = (DWORD)pGUID->Data4[7]; + + sprintf(str, "%u %u %u %u %u %u %u %u %u %u %u", + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10]); +} + +/* +int GetPentiumTimeRaw(unsigned __int64 *cpu_timestamp) +{ + // returns 0 on failure, 1 on success + // warning: watch out for wraparound! + + // note: it's probably better to use QueryPerformanceFrequency + // and QueryPerformanceCounter()! + + // get high-precision time: + __try + { + unsigned __int64 *dest = (unsigned __int64 *)cpu_timestamp; + __asm + { + _emit 0xf // these two bytes form the 'rdtsc' asm instruction, + _emit 0x31 // available on Pentium I and later. + mov esi, dest + mov [esi ], eax // lower 32 bits of tsc + mov [esi+4], edx // upper 32 bits of tsc + } + return 1; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + return 0; + } + + return 0; +} + +double GetPentiumTimeAsDouble(unsigned __int64 frequency) +{ + // returns < 0 on failure; otherwise, returns current cpu time, in seconds. + // warning: watch out for wraparound! + + // note: it's probably better to use QueryPerformanceFrequency + // and QueryPerformanceCounter()! + + if (frequency==0) + return -1.0; + + // get high-precision time: + __try + { + unsigned __int64 high_perf_time; + unsigned __int64 *dest = &high_perf_time; + __asm + { + _emit 0xf // these two bytes form the 'rdtsc' asm instruction, + _emit 0x31 // available on Pentium I and later. + mov esi, dest + mov [esi ], eax // lower 32 bits of tsc + mov [esi+4], edx // upper 32 bits of tsc + } + __int64 time_s = (__int64)(high_perf_time / frequency); // unsigned->sign conversion should be safe here + __int64 time_fract = (__int64)(high_perf_time % frequency); // unsigned->sign conversion should be safe here + // note: here, we wrap the timer more frequently (once per week) + // than it otherwise would (VERY RARELY - once every 585 years on + // a 1 GHz), to alleviate floating-point precision errors that start + // to occur when you get to very high counter values. + double ret = (time_s % (60*60*24*7)) + (double)time_fract/(double)((__int64)frequency); + return ret; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + return -1.0; + } + + return -1.0; +} +*/ + +#ifdef _DEBUG + void OutputDebugMessage(char *szStartText, HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) + { + // note: this function does NOT log WM_MOUSEMOVE, WM_NCHITTEST, or WM_SETCURSOR + // messages, since they are so frequent. + // note: these identifiers were pulled from winuser.h + + //if (msg == WM_MOUSEMOVE || msg == WM_NCHITTEST || msg == WM_SETCURSOR) + // return; + + #ifdef _DEBUG + char buf[64]; + int matched = 1; + + sprintf(buf, "WM_"); + + switch(msg) + { + case 0x0001: strcat(buf, "CREATE"); break; + case 0x0002: strcat(buf, "DESTROY"); break; + case 0x0003: strcat(buf, "MOVE"); break; + case 0x0005: strcat(buf, "SIZE"); break; + case 0x0006: strcat(buf, "ACTIVATE"); break; + case 0x0007: strcat(buf, "SETFOCUS"); break; + case 0x0008: strcat(buf, "KILLFOCUS"); break; + case 0x000A: strcat(buf, "ENABLE"); break; + case 0x000B: strcat(buf, "SETREDRAW"); break; + case 0x000C: strcat(buf, "SETTEXT"); break; + case 0x000D: strcat(buf, "GETTEXT"); break; + case 0x000E: strcat(buf, "GETTEXTLENGTH"); break; + case 0x000F: strcat(buf, "PAINT"); break; + case 0x0010: strcat(buf, "CLOSE"); break; + case 0x0011: strcat(buf, "QUERYENDSESSION"); break; + case 0x0012: strcat(buf, "QUIT"); break; + case 0x0013: strcat(buf, "QUERYOPEN"); break; + case 0x0014: strcat(buf, "ERASEBKGND"); break; + case 0x0015: strcat(buf, "SYSCOLORCHANGE"); break; + case 0x0016: strcat(buf, "ENDSESSION"); break; + case 0x0018: strcat(buf, "SHOWWINDOW"); break; + case 0x001A: strcat(buf, "WININICHANGE"); break; + case 0x001B: strcat(buf, "DEVMODECHANGE"); break; + case 0x001C: strcat(buf, "ACTIVATEAPP"); break; + case 0x001D: strcat(buf, "FONTCHANGE"); break; + case 0x001E: strcat(buf, "TIMECHANGE"); break; + case 0x001F: strcat(buf, "CANCELMODE"); break; + case 0x0020: strcat(buf, "SETCURSOR"); break; + case 0x0021: strcat(buf, "MOUSEACTIVATE"); break; + case 0x0022: strcat(buf, "CHILDACTIVATE"); break; + case 0x0023: strcat(buf, "QUEUESYNC"); break; + case 0x0024: strcat(buf, "GETMINMAXINFO"); break; + case 0x0026: strcat(buf, "PAINTICON"); break; + case 0x0027: strcat(buf, "ICONERASEBKGND"); break; + case 0x0028: strcat(buf, "NEXTDLGCTL"); break; + case 0x002A: strcat(buf, "SPOOLERSTATUS"); break; + case 0x002B: strcat(buf, "DRAWITEM"); break; + case 0x002C: strcat(buf, "MEASUREITEM"); break; + case 0x002D: strcat(buf, "DELETEITEM"); break; + case 0x002E: strcat(buf, "VKEYTOITEM"); break; + case 0x002F: strcat(buf, "CHARTOITEM"); break; + case 0x0030: strcat(buf, "SETFONT"); break; + case 0x0031: strcat(buf, "GETFONT"); break; + case 0x0032: strcat(buf, "SETHOTKEY"); break; + case 0x0033: strcat(buf, "GETHOTKEY"); break; + case 0x0037: strcat(buf, "QUERYDRAGICON"); break; + case 0x0039: strcat(buf, "COMPAREITEM"); break; + case 0x0041: strcat(buf, "COMPACTING"); break; + case 0x0044: strcat(buf, "COMMNOTIFY"); break; + case 0x0046: strcat(buf, "WINDOWPOSCHANGING"); break; + case 0x0047: strcat(buf, "WINDOWPOSCHANGED"); break; + case 0x0048: strcat(buf, "POWER"); break; + case 0x004A: strcat(buf, "COPYDATA"); break; + case 0x004B: strcat(buf, "CANCELJOURNAL"); break; + + #if(WINVER >= 0x0400) + case 0x004E: strcat(buf, "NOTIFY"); break; + case 0x0050: strcat(buf, "INPUTLANGCHANGEREQUEST"); break; + case 0x0051: strcat(buf, "INPUTLANGCHANGE"); break; + case 0x0052: strcat(buf, "TCARD"); break; + case 0x0053: strcat(buf, "HELP"); break; + case 0x0054: strcat(buf, "USERCHANGED"); break; + case 0x0055: strcat(buf, "NOTIFYFORMAT"); break; + case 0x007B: strcat(buf, "CONTEXTMENU"); break; + case 0x007C: strcat(buf, "STYLECHANGING"); break; + case 0x007D: strcat(buf, "STYLECHANGED"); break; + case 0x007E: strcat(buf, "DISPLAYCHANGE"); break; + case 0x007F: strcat(buf, "GETICON"); break; + case 0x0080: strcat(buf, "SETICON"); break; + #endif + + case 0x0081: strcat(buf, "NCCREATE"); break; + case 0x0082: strcat(buf, "NCDESTROY"); break; + case 0x0083: strcat(buf, "NCCALCSIZE"); break; + case 0x0084: strcat(buf, "NCHITTEST"); break; + case 0x0085: strcat(buf, "NCPAINT"); break; + case 0x0086: strcat(buf, "NCACTIVATE"); break; + case 0x0087: strcat(buf, "GETDLGCODE"); break; + case 0x0088: strcat(buf, "SYNCPAINT"); break; + case 0x00A0: strcat(buf, "NCMOUSEMOVE"); break; + case 0x00A1: strcat(buf, "NCLBUTTONDOWN"); break; + case 0x00A2: strcat(buf, "NCLBUTTONUP"); break; + case 0x00A3: strcat(buf, "NCLBUTTONDBLCLK"); break; + case 0x00A4: strcat(buf, "NCRBUTTONDOWN"); break; + case 0x00A5: strcat(buf, "NCRBUTTONUP"); break; + case 0x00A6: strcat(buf, "NCRBUTTONDBLCLK"); break; + case 0x00A7: strcat(buf, "NCMBUTTONDOWN"); break; + case 0x00A8: strcat(buf, "NCMBUTTONUP"); break; + case 0x00A9: strcat(buf, "NCMBUTTONDBLCLK"); break; + case 0x0100: strcat(buf, "KEYDOWN"); break; + case 0x0101: strcat(buf, "KEYUP"); break; + case 0x0102: strcat(buf, "CHAR"); break; + case 0x0103: strcat(buf, "DEADCHAR"); break; + case 0x0104: strcat(buf, "SYSKEYDOWN"); break; + case 0x0105: strcat(buf, "SYSKEYUP"); break; + case 0x0106: strcat(buf, "SYSCHAR"); break; + case 0x0107: strcat(buf, "SYSDEADCHAR"); break; + case 0x0108: strcat(buf, "KEYLAST"); break; + + #if(WINVER >= 0x0400) + case 0x010D: strcat(buf, "IME_STARTCOMPOSITION"); break; + case 0x010E: strcat(buf, "IME_ENDCOMPOSITION"); break; + case 0x010F: strcat(buf, "IME_COMPOSITION"); break; + //case 0x010F: strcat(buf, "IME_KEYLAST"); break; + #endif + + case 0x0110: strcat(buf, "INITDIALOG"); break; + case 0x0111: strcat(buf, "COMMAND"); break; + case 0x0112: strcat(buf, "SYSCOMMAND"); break; + case 0x0113: strcat(buf, "TIMER"); break; + case 0x0114: strcat(buf, "HSCROLL"); break; + case 0x0115: strcat(buf, "VSCROLL"); break; + case 0x0116: strcat(buf, "INITMENU"); break; + case 0x0117: strcat(buf, "INITMENUPOPUP"); break; + case 0x011F: strcat(buf, "MENUSELECT"); break; + case 0x0120: strcat(buf, "MENUCHAR"); break; + case 0x0121: strcat(buf, "ENTERIDLE"); break; + #if(WINVER >= 0x0500) + case 0x0122: strcat(buf, "MENURBUTTONUP"); break; + case 0x0123: strcat(buf, "MENUDRAG"); break; + case 0x0124: strcat(buf, "MENUGETOBJECT"); break; + case 0x0125: strcat(buf, "UNINITMENUPOPUP"); break; + case 0x0126: strcat(buf, "MENUCOMMAND"); break; + #endif + + case 0x0132: strcat(buf, "CTLCOLORMSGBOX"); break; + case 0x0133: strcat(buf, "CTLCOLOREDIT"); break; + case 0x0134: strcat(buf, "CTLCOLORLISTBOX"); break; + case 0x0135: strcat(buf, "CTLCOLORBTN"); break; + case 0x0136: strcat(buf, "CTLCOLORDLG"); break; + case 0x0137: strcat(buf, "CTLCOLORSCROLLBAR"); break; + case 0x0138: strcat(buf, "CTLCOLORSTATIC"); break; + + //case 0x0200: strcat(buf, "MOUSEFIRST"); break; + case 0x0200: strcat(buf, "MOUSEMOVE"); break; + case 0x0201: strcat(buf, "LBUTTONDOWN"); break; + case 0x0202: strcat(buf, "LBUTTONUP"); break; + case 0x0203: strcat(buf, "LBUTTONDBLCLK"); break; + case 0x0204: strcat(buf, "RBUTTONDOWN"); break; + case 0x0205: strcat(buf, "RBUTTONUP"); break; + case 0x0206: strcat(buf, "RBUTTONDBLCLK"); break; + case 0x0207: strcat(buf, "MBUTTONDOWN"); break; + case 0x0208: strcat(buf, "MBUTTONUP"); break; + case 0x0209: strcat(buf, "MBUTTONDBLCLK"); break; + + #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) + case 0x020A: strcat(buf, "MOUSEWHEEL"); break; + //case 0x020A: strcat(buf, "MOUSELAST"); break; + #else + //case 0x0209: strcat(buf, "MOUSELAST"); break; + #endif + + case 0x0210: strcat(buf, "PARENTNOTIFY"); break; + case 0x0211: strcat(buf, "ENTERMENULOOP"); break; + case 0x0212: strcat(buf, "EXITMENULOOP"); break; + + #if(WINVER >= 0x0400) + case 0x0213: strcat(buf, "NEXTMENU"); break; + case 0x0214: strcat(buf, "SIZING"); break; + case 0x0215: strcat(buf, "CAPTURECHANGED"); break; + case 0x0216: strcat(buf, "MOVING"); break; + case 0x0218: strcat(buf, "POWERBROADCAST"); break; + case 0x0219: strcat(buf, "DEVICECHANGE"); break; + #endif + + /* + case 0x0220: strcat(buf, "MDICREATE"); break; + case 0x0221: strcat(buf, "MDIDESTROY"); break; + case 0x0222: strcat(buf, "MDIACTIVATE"); break; + case 0x0223: strcat(buf, "MDIRESTORE"); break; + case 0x0224: strcat(buf, "MDINEXT"); break; + case 0x0225: strcat(buf, "MDIMAXIMIZE"); break; + case 0x0226: strcat(buf, "MDITILE"); break; + case 0x0227: strcat(buf, "MDICASCADE"); break; + case 0x0228: strcat(buf, "MDIICONARRANGE"); break; + case 0x0229: strcat(buf, "MDIGETACTIVE"); break; + */ + + case 0x0230: strcat(buf, "MDISETMENU"); break; + case 0x0231: strcat(buf, "ENTERSIZEMOVE"); break; + case 0x0232: strcat(buf, "EXITSIZEMOVE"); break; + case 0x0233: strcat(buf, "DROPFILES"); break; + case 0x0234: strcat(buf, "MDIREFRESHMENU"); break; + + + /* + #if(WINVER >= 0x0400) + case 0x0281: strcat(buf, "IME_SETCONTEXT"); break; + case 0x0282: strcat(buf, "IME_NOTIFY"); break; + case 0x0283: strcat(buf, "IME_CONTROL"); break; + case 0x0284: strcat(buf, "IME_COMPOSITIONFULL"); break; + case 0x0285: strcat(buf, "IME_SELECT"); break; + case 0x0286: strcat(buf, "IME_CHAR"); break; + #endif + #if(WINVER >= 0x0500) + case 0x0288: strcat(buf, "IME_REQUEST"); break; + #endif + #if(WINVER >= 0x0400) + case 0x0290: strcat(buf, "IME_KEYDOWN"); break; + case 0x0291: strcat(buf, "IME_KEYUP"); break; + #endif + */ + + #if(_WIN32_WINNT >= 0x0400) + case 0x02A1: strcat(buf, "MOUSEHOVER"); break; + case 0x02A3: strcat(buf, "MOUSELEAVE"); break; + #endif + + case 0x0300: strcat(buf, "CUT"); break; + case 0x0301: strcat(buf, "COPY"); break; + case 0x0302: strcat(buf, "PASTE"); break; + case 0x0303: strcat(buf, "CLEAR"); break; + case 0x0304: strcat(buf, "UNDO"); break; + case 0x0305: strcat(buf, "RENDERFORMAT"); break; + case 0x0306: strcat(buf, "RENDERALLFORMATS"); break; + case 0x0307: strcat(buf, "DESTROYCLIPBOARD"); break; + case 0x0308: strcat(buf, "DRAWCLIPBOARD"); break; + case 0x0309: strcat(buf, "PAINTCLIPBOARD"); break; + case 0x030A: strcat(buf, "VSCROLLCLIPBOARD"); break; + case 0x030B: strcat(buf, "SIZECLIPBOARD"); break; + case 0x030C: strcat(buf, "ASKCBFORMATNAME"); break; + case 0x030D: strcat(buf, "CHANGECBCHAIN"); break; + case 0x030E: strcat(buf, "HSCROLLCLIPBOARD"); break; + case 0x030F: strcat(buf, "QUERYNEWPALETTE"); break; + case 0x0310: strcat(buf, "PALETTEISCHANGING"); break; + case 0x0311: strcat(buf, "PALETTECHANGED"); break; + case 0x0312: strcat(buf, "HOTKEY"); break; + + #if(WINVER >= 0x0400) + case 0x0317: strcat(buf, "PRINT"); break; + case 0x0318: strcat(buf, "PRINTCLIENT"); break; + + case 0x0358: strcat(buf, "HANDHELDFIRST"); break; + case 0x035F: strcat(buf, "HANDHELDLAST"); break; + + case 0x0360: strcat(buf, "AFXFIRST"); break; + case 0x037F: strcat(buf, "AFXLAST"); break; + #endif + + case 0x0380: strcat(buf, "PENWINFIRST"); break; + case 0x038F: strcat(buf, "PENWINLAST"); break; + + default: + sprintf(buf, "unknown"); + matched = 0; + break; + } + + int n = strlen(buf); + int desired_len = 24; + int spaces_to_append = desired_len-n; + if (spaces_to_append>0) + { + for (int i=0; i PROMPT TO GO TO WEB. + int ret = MessageBox(hwnd, + #ifndef D3D_SDK_VERSION + --- error; you need to #include --- + #endif + #if (D3D_SDK_VERSION==120) + // plugin was *built* using the DirectX 8.0 sdk, therefore, + // the dx8.0 runtime is missing or corrupt + "Failed to initialize DirectX 8.0 or later; it is either missing or corrupt.\r" + "DirectX 8.0 or later must be installed before you can run this plugin!\r" + "\r" + "Would you like to be taken to http://www.microsoft.com/windows/directx,\r" + "where you can download the latest version of DirectX?\r" + "\r" + "Please click YES to open this page in your default web browser,\r" + "or NO to simply return to Winamp." + #else + // plugin was *built* using some other version of the DirectX8 sdk, such as + // 8.1b; therefore, we don't know exactly what version to tell them they need + // to install; so we ask them to go get the *latest* version. + "Failed to initialize DirectX; it is either missing or corrupt.\r" + "The latest version of DirectX must be installed before you can run this plugin!\r" + "\r" + "Would you like to be taken to http://www.microsoft.com/windows/directx,\r" + "where you can download the latest version of DirectX?\r" + "\r" + "Please click YES to open this page in your default web browser,\r" + "or NO to simply return to Winamp." + #endif + ,"DirectX Missing or Corrupt",MB_YESNO|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL); + + if (ret==IDYES) + DownloadDirectX(hwnd); +*/ +} + +bool CheckForMMX() +{ + DWORD bMMX = 0; + DWORD *pbMMX = &bMMX; + __try { + __asm { + mov eax, 1 + cpuid + mov edi, pbMMX + mov dword ptr [edi], edx + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + bMMX = 0; + } + + if (bMMX & 0x00800000) // check bit 23 + return true; + + return false; +} + +bool CheckForSSE() +{ + /* + The SSE instruction set was introduced with the Pentium III and features: + * Additional MMX instructions such as min/max + * Prefetch and write-through instructions for optimizing data movement + from and to the L2/L3 caches and main memory + * 8 New 128 bit XMM registers (xmm0..xmm7) and corresponding 32 bit floating point + (single precision) instructions + */ + + DWORD bSSE = 0; + DWORD *pbSSE = &bSSE; + __try { + __asm + { + mov eax, 1 + cpuid + mov edi, pbSSE + mov dword ptr [edi], edx + } + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + bSSE = 0; + } + + if (bSSE & 0x02000000) // check bit 25 + return true; + + return false; +} + +void memset_MMX(void *pDest, unsigned char value, int nBytes) +{ + // NOTE #1: YOU MUST MAKE SURE MMX IS SUPPORTED BEFORE CALLING THIS ROUTINE + // NOTE #2: YOU MUST ENSURE THAT THE POINTERS ARE ALIGNED TO 8-BYTE BOUNDARIES + + int offset = ((unsigned long)pDest) % 8; + + if (nBytes < 32) + { + memset(pDest, value, nBytes); + } + else + { + if (offset != 0) + { + int prebytes = 8-offset; + memset(pDest, value, prebytes); + pDest = (void*)((unsigned long)pDest + prebytes); + nBytes -= prebytes; + } + + int nLoops = nBytes/64; + unsigned __int64 value8x = value; + value8x = value8x | (value8x<<8); + value8x = value8x | (value8x<<16); + value8x = value8x | (value8x<<32); + + if (nLoops > 0) + __asm + { + mov ecx, nLoops + mov edi, pDest + + movq mm0, qword ptr value8x + movq mm1, qword ptr value8x + movq mm2, qword ptr value8x + movq mm3, qword ptr value8x + movq mm4, qword ptr value8x + movq mm5, qword ptr value8x + movq mm6, qword ptr value8x + movq mm7, qword ptr value8x + + ALIGN 16 + MMX_memset_loop: + + MOVQ [edi], mm0 + MOVQ [edi+8], mm1 + MOVQ [edi+16], mm2 + MOVQ [edi+24], mm3 + MOVQ [edi+32], mm4 + MOVQ [edi+40], mm5 + MOVQ [edi+48], mm6 + MOVQ [edi+56], mm7 + + ADD edi, 64 + + dec ecx + jnz MMX_memset_loop + + EMMS + } + + int nBytesDone = nLoops*64; + int nBytesLeft = nBytes - nBytesDone; + if (nBytesLeft > 0) + memset((unsigned char *)pDest + nBytesDone, value, nBytesLeft); + } +} + +void memcpy_MMX(void *pDest, void *pSrc, int nBytes) +{ + // NOTE #1: YOU MUST MAKE SURE MMX IS SUPPORTED BEFORE CALLING THIS ROUTINE + // NOTE #2: YOU MUST ENSURE THAT THE POINTERS ARE ALIGNED TO 8-BYTE BOUNDARIES + + int offset = ((unsigned long)pSrc) % 8; + int offset2 = ((unsigned long)pDest) % 8; + + if (offset != offset2 || nBytes < 32) + { + // don't use MMX, since data is not aligned + memcpy(pDest, pSrc, nBytes); + } + else + { + if (offset != 0) + { + int prebytes = 8-offset; + memcpy(pDest, pSrc, prebytes); + pSrc = (void*)((unsigned long)pSrc + prebytes); + pDest = (void*)((unsigned long)pDest + prebytes); + nBytes -= prebytes; + //assert((((unsigned long)pSrc) % 8)==0); + //assert((((unsigned long)pDest) % 8)==0); + } + + int nLoops = nBytes/64; + + if (nLoops > 0) + __asm + { + mov ecx, nLoops + mov eax, pSrc + mov edi, pDest + + ALIGN 16 + MMX_memcpy_loop: + + MOVQ mm0, [eax] + MOVQ mm1, [eax+8] + MOVQ mm2, [eax+16] + MOVQ mm3, [eax+24] + MOVQ mm4, [eax+32] + MOVQ mm5, [eax+40] + MOVQ mm6, [eax+48] + MOVQ mm7, [eax+56] + + MOVQ [edi], mm0 + MOVQ [edi+8], mm1 + MOVQ [edi+16], mm2 + MOVQ [edi+24], mm3 + MOVQ [edi+32], mm4 + MOVQ [edi+40], mm5 + MOVQ [edi+48], mm6 + MOVQ [edi+56], mm7 + + ADD eax, 64 + ADD edi, 64 + + dec ecx + jnz MMX_memcpy_loop + + EMMS + } + + int nBytesDone = nLoops*64; + int nBytesLeft = nBytes - nBytesDone; + if (nBytesLeft > 0) + { + memcpy((unsigned char *)pDest + nBytesDone, (unsigned char *)pSrc + nBytesDone, nBytesLeft); + } + } +} + +void GetDesktopFolder(char *szDesktopFolder) // should be MAX_PATH len. +{ + // returns the path to the desktop folder, WITHOUT a trailing backslash. + + szDesktopFolder[0] = 0; +/* + ITEMIDLIST pidl; + ZeroMemory(&pidl, sizeof(pidl)); + if (!SHGetPathFromIDList(&pidl, szDesktopFolder)) + szDesktopFolder[0] = 0; +*/ +} +/* +void ExecutePidl(LPITEMIDLIST pidl, char *szPathAndFile, char *szWorkingDirectory, HWND hWnd) +{ + + // This function was based on code by Jeff Prosise. + + // Note: for some reason, ShellExecuteEx fails when executing + // *shortcuts* (.lnk files) from the desktop, using their PIDLs. + // So, if that fails, we try again w/the plain old text filename + // (szPathAndFile). + + char szVerb[] = "open"; + char szFilename2[MAX_PATH]; + + sprintf(szFilename2, "%s.lnk", szPathAndFile); + + // -without the "no-verb" pass, + // certain icons still don't work (like shortcuts + // to IE, VTune...) + // -without the "context menu" pass, + // certain others STILL don't work (Netscape...) + // -without the 'ntry' pass, shortcuts (to folders/files) + // don't work + for (int verb_pass=0; verb_pass<2; verb_pass++) + { + for (int ntry=0; ntry<3; ntry++) + { + for (int context_pass=0; context_pass<2; context_pass++) + { + SHELLEXECUTEINFO sei = { sizeof(sei) }; + sei.hwnd = hWnd; + sei.fMask = SEE_MASK_FLAG_NO_UI; + if (context_pass==1) + sei.fMask |= SEE_MASK_INVOKEIDLIST; + sei.lpVerb = (verb_pass) ? NULL : szVerb; + sei.lpDirectory = szWorkingDirectory; + sei.nShow = SW_SHOWNORMAL; + + if (ntry==0) + { + // this case works for most non-shortcuts + sei.fMask |= SEE_MASK_IDLIST; + sei.lpIDList = pidl; + } + else if (ntry==1) + { + // this case is required for *shortcuts to folders* to work + sei.lpFile = szPathAndFile; + } + else if (ntry==2) + { + // this case is required for *shortcuts to files* to work + sei.lpFile = szFilename2; + } + + if (ShellExecuteEx(&sei)) + return; + } + } + } + +} +*/ + +//WNDPROC g_pOldWndProc; +//LPCONTEXTMENU2 g_pIContext2or3; + +LRESULT CALLBACK HookWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) +{ +#if 0 + //UINT uItem; + //TCHAR szBuf[MAX_PATH]; + + switch (msg) + { + case WM_DRAWITEM: + case WM_MEASUREITEM: + if(wp) break; // not menu related + case WM_INITMENUPOPUP: + g_pIContext2or3->HandleMenuMsg(msg, wp, lp); + return (msg==WM_INITMENUPOPUP ? 0 : TRUE); // handled + + /*case WM_MENUSELECT: + // if this is a shell item, get its descriptive text + uItem = (UINT) LOWORD(wp); + if(0 == (MF_POPUP & HIWORD(wp)) && uItem >= 1 && uItem <= 0x7fff) + { + g_pIContext2or3->GetCommandString(uItem-1, GCS_HELPTEXT, + NULL, szBuf, sizeof(szBuf)/sizeof(szBuf[0]) ); + + // set the status bar text + ((CFrameWnd*)(AfxGetApp()->m_pMainWnd))->SetMessageText(szBuf); + return 0; + } + break;*/ + + default: + break; + } + + // for all untreated messages, call the original wndproc + return ::CallWindowProc(g_pOldWndProc, hWnd, msg, wp, lp); +#endif + return 0; +} + +#if 0 +BOOL DoExplorerMenu (HWND hwnd, LPITEMIDLIST pidlMain, POINT point) +{ + LPMALLOC pMalloc; + LPSHELLFOLDER psfFolder, psfNextFolder; + LPITEMIDLIST pidlItem, pidlNextItem, *ppidl; + LPCONTEXTMENU pContextMenu; + CMINVOKECOMMANDINFO ici; + UINT nCount, nCmd; + BOOL bResult; + HMENU hMenu; + + // + // Get pointers to the shell's IMalloc interface and the desktop's + // IShellFolder interface. + // + bResult = FALSE; + + if (!SUCCEEDED (SHGetMalloc (&pMalloc))) + return bResult; + + if (!SUCCEEDED (SHGetDesktopFolder (&psfFolder))) { + pMalloc->Release(); + return bResult; + } + + if (nCount = GetItemCount (pidlMain)) // nCount must be > 0 + { + // + // Initialize psfFolder with a pointer to the IShellFolder + // interface of the folder that contains the item whose context + // menu we're after, and initialize pidlItem with a pointer to + // the item's item ID. If nCount > 1, this requires us to walk + // the list of item IDs stored in pidlMain and bind to each + // subfolder referenced in the list. + // + pidlItem = pidlMain; + + while (--nCount) { + // + // Create a 1-item item ID list for the next item in pidlMain. + // + pidlNextItem = DuplicateItem (pMalloc, pidlItem); + if (pidlNextItem == NULL) { + psfFolder->Release(); + pMalloc->Release(); + return bResult; + } + + // + // Bind to the folder specified in the new item ID list. + // + if (!SUCCEEDED (psfFolder->BindToObject(pidlNextItem, NULL, IID_IShellFolder, (void**)&psfNextFolder))) // modified by RG + { + pMalloc->Free(pidlNextItem); + psfFolder->Release(); + pMalloc->Release(); + return bResult; + } + + // + // Release the IShellFolder pointer to the parent folder + // and set psfFolder equal to the IShellFolder pointer for + // the current folder. + // + psfFolder->Release(); + psfFolder = psfNextFolder; + + // + // Release the storage for the 1-item item ID list we created + // just a moment ago and initialize pidlItem so that it points + // to the next item in pidlMain. + // + pMalloc->Free(pidlNextItem); + pidlItem = GetNextItem (pidlItem); + } + + // + // Get a pointer to the item's IContextMenu interface and call + // IContextMenu::QueryContextMenu to initialize a context menu. + // + ppidl = &pidlItem; + if (SUCCEEDED (psfFolder->GetUIObjectOf(hwnd, 1, (LPCITEMIDLIST*)ppidl, IID_IContextMenu, NULL, (void**)&pContextMenu))) // modified by RG + { + // try to see if we can upgrade to an IContextMenu3 + // or IContextMenu2 interface pointer: + int level = 1; + void *pCM = NULL; + if (pContextMenu->QueryInterface(IID_IContextMenu3, &pCM) == NOERROR) + { + pContextMenu->Release(); + pContextMenu = (LPCONTEXTMENU)pCM; + level = 3; + } + else if (pContextMenu->QueryInterface(IID_IContextMenu2, &pCM) == NOERROR) + { + pContextMenu->Release(); + pContextMenu = (LPCONTEXTMENU)pCM; + level = 2; + } + + hMenu = CreatePopupMenu (); + if (SUCCEEDED (pContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE))) + { + ClientToScreen (hwnd, &point); + + // install the subclassing "hook", for versions 2 or 3 + if (level >= 2) + { + g_pOldWndProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)HookWndProc); + g_pIContext2or3 = (LPCONTEXTMENU2)pContextMenu; // cast ok for ICMv3 + } + else + { + g_pOldWndProc = NULL; + g_pIContext2or3 = NULL; + } + + // + // Display the context menu. + // + nCmd = TrackPopupMenu (hMenu, TPM_LEFTALIGN | + TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, + point.x, point.y, 0, hwnd, NULL); + + // restore old wndProc + if (g_pOldWndProc) + { + SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)g_pOldWndProc); + } + + // + // If a command was selected from the menu, execute it. + // + if (nCmd >= 1 && nCmd <= 0x7fff) + { + ZeroMemory(&ici, sizeof(ici)); + ici.cbSize = sizeof (CMINVOKECOMMANDINFO); + //ici.fMask = 0; + ici.hwnd = hwnd; + ici.lpVerb = MAKEINTRESOURCE (nCmd - 1); + //ici.lpParameters = NULL; + //ici.lpDirectory = NULL; + ici.nShow = SW_SHOWNORMAL; + //ici.dwHotKey = 0; + //ici.hIcon = NULL; + + if (SUCCEEDED ( pContextMenu->InvokeCommand (&ici))) + bResult = TRUE; + } + /*else if (nCmd) + { + PostMessage(hwnd, WM_COMMAND, nCmd, NULL); // our command + }*/ + + } + DestroyMenu (hMenu); + pContextMenu->Release(); + } + } + + // + // Clean up and return. + // + psfFolder->Release(); + pMalloc->Release(); + + return bResult; + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Note: a special thanks goes out to Jeff Prosise for writing & publishing +// the following code! +// +// FUNCTION: GetItemCount +// +// DESCRIPTION: Computes the number of item IDs in an item ID list. +// +// INPUT: pidl = Pointer to an item ID list. +// +// RETURNS: Number of item IDs in the list. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +UINT GetItemCount (LPITEMIDLIST pidl) +{ + USHORT nLen; + UINT nCount; + + nCount = 0; + while ((nLen = pidl->mkid.cb) != 0) { + pidl = GetNextItem (pidl); + nCount++; + } + return nCount; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Note: a special thanks goes out to Jeff Prosise for writing & publishing +// the following code! +// +// FUNCTION: GetNextItem +// +// DESCRIPTION: Finds the next item in an item ID list. +// +// INPUT: pidl = Pointer to an item ID list. +// +// RETURNS: Pointer to the next item. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LPITEMIDLIST GetNextItem (LPITEMIDLIST pidl) +{ + USHORT nLen; + + if ((nLen = pidl->mkid.cb) == 0) + return NULL; + + return (LPITEMIDLIST) (((LPBYTE) pidl) + nLen); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Note: a special thanks goes out to Jeff Prosise for writing & publishing +// the following code! +// +// FUNCTION: DuplicateItem +// +// DESCRIPTION: Makes a copy of the next item in an item ID list. +// +// INPUT: pMalloc = Pointer to an IMalloc interface. +// pidl = Pointer to an item ID list. +// +// RETURNS: Pointer to an ITEMIDLIST containing the copied item ID. +// +// NOTES: It is the caller's responsibility to free the memory +// allocated by this function when the item ID is no longer +// needed. Example: +// +// pidlItem = DuplicateItem (pMalloc, pidl); +// . +// . +// . +// pMalloc->lpVtbl->Free (pMalloc, pidlItem); +// +// Failure to free the ITEMIDLIST will result in memory +// leaks. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LPITEMIDLIST DuplicateItem (LPMALLOC pMalloc, LPITEMIDLIST pidl) +{ + USHORT nLen; + LPITEMIDLIST pidlNew; + + nLen = pidl->mkid.cb; + if (nLen == 0) + return NULL; + + pidlNew = (LPITEMIDLIST) pMalloc->Alloc ( + nLen + sizeof (USHORT)); + if (pidlNew == NULL) + return NULL; + + CopyMemory (pidlNew, pidl, nLen); + *((USHORT*) (((LPBYTE) pidlNew) + nLen)) = 0; + + return pidlNew; +} + +//---------------------------------------------------------------------- +// A special thanks goes out to Jeroen-bart Engelen (Yeep) for providing +// his source code for getting the position & label information for all +// the icons on the desktop, as found below. See his article at +// http://www.digiwar.com/scripts/renderpage.php?section=2&subsection=2 +//---------------------------------------------------------------------- + +void FindDesktopWindows(HWND *desktop_progman, HWND *desktopview_wnd, HWND *listview_wnd) +{ + *desktop_progman = NULL; + *desktopview_wnd = NULL; + *listview_wnd = NULL; + + *desktop_progman = FindWindow(NULL, ("Program Manager")); + if(*desktop_progman == NULL) + { + //MessageBox(NULL, "Unable to get the handle to the Program Manager.", "Fatal error", MB_OK|MB_ICONERROR); + return; + } + + *desktopview_wnd = FindWindowEx(*desktop_progman, NULL, "SHELLDLL_DefView", NULL); + if(*desktopview_wnd == NULL) + { + //MessageBox(NULL, "Unable to get the handle to the desktopview.", "Fatal error", MB_OK|MB_ICONERROR); + return; + } + + // Thanks ef_ef_ef@yahoo.com for pointing out this works in NT 4 and not the way I did it originally. + *listview_wnd = FindWindowEx(*desktopview_wnd, NULL, "SysListView32", NULL); + if(*listview_wnd == NULL) + { + //MessageBox(NULL, "Unable to get the handle to the folderview.", "Fatal error", MB_OK|MB_ICONERROR); + return; + } +} + +//---------------------------------------------------------------------- + +/* +int DetectWin2kOrLater() +{ +// returns 0 for win95, NT, 98, me, or error +// returns 1 for win2k, xp... + +OSVERSIONINFO osvi = { sizeof(osvi) }; +if (GetVersionEx(&osvi)) +{ +// Win95 Win98 WinNT 3.51 WinNT 4.0 Win 2000 WinXP +//dwPlatformID 1 1 2 2 2 2 +//dwMajorVersion 4 4 3 4 5 5 +//dwMinorVersion 0 10 51 0 0 1 + +if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5) +return 1; +else +return 0; +} + +// error +return 0; +} +*/ + +//---------------------------------------------------------------------- + +int GetDesktopIconSize() +{ + int ret = 32; + + // reads the key: HKEY_CURRENT_USER\Control Panel, Desktop\WindowMetrics\Shell Icon Size + unsigned char buf[64]; + unsigned long len = sizeof(buf); + DWORD type; + HKEY key; + + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", 0, KEY_READ, &key)) + { + if (ERROR_SUCCESS == RegQueryValueEx(key, "Shell Icon Size", NULL, &type, (unsigned char*)buf, &len) && + type == REG_SZ) + { + int x = atoi((char*)buf); + if (x>0 && x<=128) + ret = x; + } + + RegCloseKey(key); + } + + return ret; +} +#endif diff --git a/lib/vis_milkdrop/utility.h b/lib/vis_milkdrop/utility.h new file mode 100644 index 0000000..7c028d8 --- /dev/null +++ b/lib/vis_milkdrop/utility.h @@ -0,0 +1,95 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __NULLSOFT_DX8_PLUGIN_SHELL_UTILITY_H__ +#define __NULLSOFT_DX8_PLUGIN_SHELL_UTILITY_H__ 1 + +#include +//#include + +#define SafeRelease(x) { if (x) {x->Release(); x=NULL;} } +#define SafeDelete(x) { if (x) {delete x; x=NULL;} } +#define IsNullGuid(lpGUID) ( ((int*)lpGUID)[0]==0 && ((int*)lpGUID)[1]==0 && ((int*)lpGUID)[2]==0 && ((int*)lpGUID)[3]==0 ) +#define DlgItemIsChecked(hDlg, nIDDlgItem) ((SendDlgItemMessage(hDlg, nIDDlgItem, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED) ? true : false) +#define CosineInterp(x) (0.5f - 0.5f*cosf((x) * 3.1415926535898f)) +#define InvCosineInterp(x) (acosf(1.0f - 2.0f*(x))/3.1415926535898f) +float PowCosineInterp(float x, float pow); +float AdjustRateToFPS(float per_frame_decay_rate_at_fps1, float fps1, float actual_fps); + +//int InternalGetPrivateProfileInt - part of Win32 API +#define GetPrivateProfileBool(w,x,y,z) ((bool)(InternalGetPrivateProfileInt(w,x,y,z) != 0)) +#define GetPrivateProfileBOOL(w,x,y,z) ((BOOL)(InternalGetPrivateProfileInt(w,x,y,z) != 0)) +int InternalGetPrivateProfileString(char *szSectionName, char *szKeyName, char *szDefault, char *buffer, int size, char *szIniFile); +int InternalGetPrivateProfileInt(char *szSectionName, char *szKeyName, int iDefault, char *szIniFile); +float InternalGetPrivateProfileFloat(char *szSectionName, char *szKeyName, float fDefault, char *szIniFile); +bool WritePrivateProfileInt(int d, char *szKeyName, char *szIniFile, char *szSectionName); +bool WritePrivateProfileFloat(float f, char *szKeyName, char *szIniFile, char *szSectionName); + +void SetScrollLock(int bNewState); +void RemoveExtension(char *str); +void RemoveSingleAmpersands(char *str); +void TextToGuid(char *str, GUID *pGUID); +void GuidToText(GUID *pGUID, char *str, int nStrLen); +//int GetPentiumTimeRaw(unsigned __int64 *cpu_timestamp); +//double GetPentiumTimeAsDouble(unsigned __int64 frequency); +#ifdef _DEBUG + void OutputDebugMessage(char *szStartText, HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); // only available in RELEASE builds! +#endif +void MissingDirectX(HWND hwnd); +bool CheckForMMX(); +bool CheckForSSE(); +void memcpy_MMX(void *pDest, void *pSrc, int nBytes); // CALL CheckForMMX() FIRST!!! +void memset_MMX(void *pDest, unsigned char value, int nBytes); // CALL CheckForMMX() FIRST!!! +void GetDesktopFolder(char *szDesktopFolder); // should be MAX_PATH len. + + + +//#include "icon_t.h" +//#include +#include +/* +BOOL DoExplorerMenu (HWND hwnd, LPCTSTR pszPath, POINT point); +BOOL DoExplorerMenu (HWND hwnd, LPITEMIDLIST pidl, POINT point); +UINT GetItemCount (LPITEMIDLIST pidl); +LPITEMIDLIST GetNextItem (LPITEMIDLIST pidl); +LPITEMIDLIST DuplicateItem (LPMALLOC pMalloc, LPITEMIDLIST pidl); +void FindDesktopWindows(HWND *desktop_progman, HWND *desktopview_wnd, HWND *listview_wnd); +void ExecutePidl(LPITEMIDLIST pidl, char *szPathAndFile, char *szWorkingDirectory, HWND hWnd); +//int DetectWin2kOrLater(); +int GetDesktopIconSize(); +*/ + + + + + + + +#endif \ No newline at end of file diff --git a/src/MilkdropXBMC.cpp b/src/MilkdropXBMC.cpp new file mode 100644 index 0000000..f692211 --- /dev/null +++ b/src/MilkdropXBMC.cpp @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2004-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "vis_milkdrop/Plugin.h" +#include "kodi/xbmc_vis_dll.h" +#include "XmlDocument.h" +#include +#include + +CPlugin* g_plugin=NULL; + +bool g_UserPackFolder; + +int lastPresetIndx = 0; +char lastPresetDir[1024] = ""; +bool lastLockedStatus = false; + +char* presetsPath = NULL; + +// Sets a new preset file or directory and make it active. Also recovers last state of the preset if it is the same as last time +void SetPresetDir(const char *pack) +{ + int len = strlen(pack); + if (len >= 4 && strcmp(pack + len - 4, ".zip") == 0) + { + // Zip file + strcpy(g_plugin->m_szPresetDir, presetsPath); + strcat(g_plugin->m_szPresetDir, pack); + strcat(g_plugin->m_szPresetDir, "/"); + } + else if (len >= 4 && strcmp(pack + len - 4, ".rar") == 0) + { + // Rar file + strcpy(g_plugin->m_szPresetDir, presetsPath); + strcat(g_plugin->m_szPresetDir, pack); + strcat(g_plugin->m_szPresetDir, "/"); + } + else + { + // Normal folder + strcpy(g_plugin->m_szPresetDir, pack); + } + if (strcmp (g_plugin->m_szPresetDir, lastPresetDir) == 0) + { + // If we have a valid last preset state AND the preset file(dir) is the same as last time + g_plugin->UpdatePresetList(); + g_plugin->m_bHoldPreset = lastLockedStatus; + g_plugin->m_nCurrentPreset = lastPresetIndx; + strcpy(g_plugin->m_szCurrentPresetFile, g_plugin->m_szPresetDir); + strcat(g_plugin->m_szCurrentPresetFile, g_plugin->m_pPresetAddr[g_plugin->m_nCurrentPreset]); + g_plugin->LoadPreset(g_plugin->m_szCurrentPresetFile, g_plugin->m_fBlendTimeUser); + } + else + // If it is the first run or a newly chosen preset pack we choose a random preset as first + g_plugin->LoadRandomPreset(g_plugin->m_fBlendTimeUser); +} + +void Preinit() +{ + if(!g_plugin) + { + g_plugin = new CPlugin; + g_plugin->PluginPreInitialize(0, 0); + } +} + +extern "C" ADDON_STATUS ADDON_Create(void* hdl, void* props) +{ + if (!props) + return ADDON_STATUS_UNKNOWN; + + VIS_PROPS* visprops = (VIS_PROPS*)props; + _mkdir(visprops->profile); + + strcpy(presetsPath, visprops->presets); + + Preinit(); + if(!g_plugin || !g_plugin->PluginInitialize((LPDIRECT3DDEVICE9)visprops->device, visprops->x, visprops->y, visprops->width, visprops->height, visprops->pixelRatio)) + return ADDON_STATUS_UNKNOWN; + + return ADDON_STATUS_NEED_SAVEDSETTINGS; // We need some settings to be saved later before we quit this plugin +} + +extern "C" void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName) +{} + + +extern "C" void ADDON_Stop() +{ + if(g_plugin) + { + g_plugin->PluginQuit(); + delete g_plugin; + g_plugin = NULL; + } +} + +unsigned char waves[2][512]; + +//-- Audiodata ---------------------------------------------------------------- +// Called by XBMC to pass new audio data to the vis +//----------------------------------------------------------------------------- +extern "C" void AudioData(const float* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength) +{ + int ipos=0; + while (ipos < 512) + { + for (int i=0; i < iAudioDataLength; i+=2) + { + waves[0][ipos] = char (pAudioData[i] * 255.0f); + waves[1][ipos] = char (pAudioData[i+1] * 255.0f); + ipos++; + if (ipos >= 512) break; + } + } +} + +extern "C" void Render() +{ + g_plugin->PluginRender(waves[0], waves[1]); + +} + +extern "C" void GetInfo(VIS_INFO* pInfo) +{ + pInfo->bWantsFreq = false; + pInfo->iSyncDelay = 0; +} + +//-- OnAction ----------------------------------------------------------------- +// Handle XBMC actions such as next preset, lock preset, album art changed etc +//----------------------------------------------------------------------------- +extern "C" bool OnAction(long flags, const void *param) +{ + bool ret = false; + if (flags == VIS_ACTION_NEXT_PRESET) + { + g_plugin->LoadNextPreset(g_plugin->m_fBlendTimeUser); + ret = true; + } + else if (flags == VIS_ACTION_PREV_PRESET) + { + g_plugin->LoadPreviousPreset(g_plugin->m_fBlendTimeUser); + ret = true; + } + else if (flags == VIS_ACTION_LOAD_PRESET && param) + { + g_plugin->m_nCurrentPreset = *(int *)param; + strcpy(g_plugin->m_szCurrentPresetFile, g_plugin->m_szPresetDir); // note: m_szPresetDir always ends with '\' + strcat(g_plugin->m_szCurrentPresetFile, g_plugin->m_pPresetAddr[g_plugin->m_nCurrentPreset]); + g_plugin->LoadPreset(g_plugin->m_szCurrentPresetFile, g_plugin->m_fBlendTimeUser); + ret = true; + } + else if (flags == VIS_ACTION_LOCK_PRESET) + { + g_plugin->m_bHoldPreset = !g_plugin->m_bHoldPreset; + ret = true; + } + else if (flags == VIS_ACTION_RANDOM_PRESET) + { + g_plugin->LoadRandomPreset(g_plugin->m_fBlendTimeUser); + ret = true; + } + return ret; +} + +void LoadSettings() +{} + +//-- GetPresets --------------------------------------------------------------- +// Return a list of presets to XBMC for display +//----------------------------------------------------------------------------- +extern "C" unsigned int GetPresets(char ***presets) +{ + if (!presets || !g_plugin) return 0; + *presets = g_plugin->m_pPresetAddr; + return g_plugin->m_nPresets; +} + +//-- GetPreset ---------------------------------------------------------------- +// Return the index of the current playing preset +//----------------------------------------------------------------------------- +extern "C" unsigned GetPreset() +{ + if (g_plugin) + return g_plugin->m_nCurrentPreset; + return 0; +} + +//-- IsLocked ----------------------------------------------------------------- +// Returns true if this add-on use settings +//----------------------------------------------------------------------------- +extern "C" bool IsLocked() +{ + if(g_plugin) + return g_plugin->m_bHoldPreset; + else + return false; +} + +//-- Destroy------------------------------------------------------------------- +// Do everything before unload of this add-on +// !!! Add-on master function !!! +//----------------------------------------------------------------------------- +extern "C" void ADDON_Destroy() +{ + ADDON_Stop(); +} + +//-- HasSettings -------------------------------------------------------------- +// Returns true if this add-on use settings +// !!! Add-on master function !!! +//----------------------------------------------------------------------------- +extern "C" bool ADDON_HasSettings() +{ + return true; +} + +//-- GetStatus --------------------------------------------------------------- +// Returns the current Status of this visualisation +// !!! Add-on master function !!! +//----------------------------------------------------------------------------- +extern "C" ADDON_STATUS ADDON_GetStatus() +{ + return ADDON_STATUS_OK; +} + +//-- GetSettings -------------------------------------------------------------- +// Return the settings for XBMC to display +//----------------------------------------------------------------------------- + +extern "C" unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) +{ + return 0; +} + +//-- FreeSettings -------------------------------------------------------------- +// Free the settings struct passed from XBMC +//----------------------------------------------------------------------------- + +extern "C" void ADDON_FreeSettings() +{ +} + +//-- UpdateSetting ------------------------------------------------------------ +// Handle setting change request from XBMC +//----------------------------------------------------------------------------- +extern "C" ADDON_STATUS ADDON_SetSetting(const char* id, const void* value) +{ + if (!id || !value || !g_plugin) + return ADDON_STATUS_UNKNOWN; + + if (strcmp(id, "###GetSavedSettings") == 0) // We have some settings to be saved in the settings.xml file + { + if (strcmp((char*)value, "0") == 0) + { + strcpy((char*)id, "lastpresetfolder"); + strcpy((char*)value, g_plugin->m_szPresetDir); + } + if (strcmp((char*)value, "1") == 0) + { + strcpy((char*)id, "lastlockedstatus"); + strcpy((char*)value, (g_plugin->m_bHoldPreset ? "true" : "false")); + } + if (strcmp((char*)value, "2") == 0) + { + strcpy((char*)id, "lastpresetidx"); + sprintf ((char*)value, "%i", g_plugin->m_nCurrentPreset); + } + if (strcmp((char*)value, "3") == 0) + { + strcpy((char*)id, "###End"); + } + return ADDON_STATUS_OK; + } + // It is now time to set the settings got from xbmc + if (strcmp(id, "Use Preset") == 0) + OnAction(34, &value); + else if (strcmp(id, "Automatic Blend Time") == 0) + g_plugin->m_fBlendTimeAuto = (float)(*(int*)value + 1); + else if (strcmp(id, "Time Between Presets") == 0) + g_plugin->m_fTimeBetweenPresets = (float)(*(int*)value*5 + 5); + else if (strcmp(id, "Additional Random Time") == 0) + g_plugin->m_fTimeBetweenPresetsRand = (float)(*(int*)value*5 + 5); + else if (strcmp(id, "Enable Hard Cuts") == 0) + g_plugin->m_bHardCutsDisabled = *(bool*)value == false; + else if (strcmp(id, "Loudness Threshold For Hard Cuts") == 0) + g_plugin->m_fHardCutLoudnessThresh = (float)(*(int*)value)/5.0f + 1.25f; + else if (strcmp(id, "Average Time Between Hard Cuts") == 0) + g_plugin->m_fHardCutHalflife = (float)*(int*)value*5 + 5; + else if (strcmp(id, "Maximum Refresh Rate") == 0) + g_plugin->m_max_fps_fs = *(int*)value*5 + 20; + else if (strcmp(id, "Enable Stereo 3d") == 0) + g_plugin->m_bAlways3D = *(bool*)value; + else if (strcmp(id, "lastlockedstatus") == 0) + lastLockedStatus = *(bool*)value; + else if (strcmp(id, "lastpresetidx") == 0) + lastPresetIndx = *(int*)value; + else if (strcmp(id, "lastpresetfolder") == 0) + strcpy(lastPresetDir, (char*)value); + else if (strcmp(id, "Preset Shuffle Mode") == 0) + g_plugin->m_bSequentialPresetOrder = !*(bool*)value; + else if (strcmp(id, "Preset Pack") == 0) + { + if (*(int*)value == 0) + { + g_UserPackFolder = false;; + SetPresetDir ("WA51-presets(265).zip"); + } + else if (*(int*)value == 1) + { + g_UserPackFolder = false; + SetPresetDir ("Winamp-presets(436).zip"); + } + else if (*(int*)value == 2) + g_UserPackFolder = true; + } + else if (strcmp(id, "User Preset Folder") ==0 ) + { + if (g_UserPackFolder) SetPresetDir ((char*)value); + } + else + return ADDON_STATUS_UNKNOWN; + + return ADDON_STATUS_OK; +} + +//-- Announce ----------------------------------------------------------------- +// Receive announcements from XBMC +//----------------------------------------------------------------------------- + +extern "C" void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) +{ +} + +//-- GetSubModules ------------------------------------------------------------ +// Return any sub modules supported by this vis +//----------------------------------------------------------------------------- +extern "C" unsigned int GetSubModules(char ***names) +{ + return 0; // this vis supports 0 sub modules +} diff --git a/src/XmlDocument.cpp b/src/XmlDocument.cpp new file mode 100644 index 0000000..945056f --- /dev/null +++ b/src/XmlDocument.cpp @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2004-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +// XmlDocument.cpp: implementation of the CXmlDocument class. +// +////////////////////////////////////////////////////////////////////// +#include "XmlDocument.h" +#include + +#define strnicmp _strnicmp +#define strcmpi _strcmpi + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CXmlDocument::CXmlDocument() +{ + m_doc = 0; + m_size = 0; + m_nodes = 0; + + m_szTag[0] = 0; + m_szText[0] = 0; +} + +void CXmlDocument::Create(char* szString) +{ + m_size = strlen(szString); + m_doc = new char[m_size+1]; + memcpy(m_doc, szString, m_size+1); +} + +CXmlDocument::~CXmlDocument() +{ + if(m_doc) { + delete[] m_doc; + m_doc = NULL; + } +} + + + +////////////////////////////////////////////////////////////////////////////////// +// Function: xml_load_doc +// Opens an XML document and loads it into memory. +// +int CXmlDocument::Load(char* szFile) +{ + FILE* hFile; + + hFile = fopen(szFile,"rb"); + if (hFile==NULL) + { + return -1; + } + + fseek(hFile,0,SEEK_END); + m_size = ftell(hFile); + + fseek(hFile,0,SEEK_SET); + + m_doc = new char[m_size]; + if (!m_doc) + { + m_size = 0; + fclose(hFile); + return -2; + } + + if (fread(m_doc, m_size, 1, hFile)<=0) + { + delete[] m_doc; + m_doc = 0; + m_size = 0; + fclose(hFile); + return -3; + } + + fclose(hFile); + return 0; +} + + + + + + + + +////////////////////////////////////////////////////////////////////////////////// +// Function: xml_close_doc +// Closes XML document freeing up resources. +// +void CXmlDocument::Close() +{ + if (m_doc!=NULL) + { + delete[] m_doc; + m_doc =0; + } + + m_size =0; + m_nodes = 0; + m_szTag[0] = 0; + m_szText[0] = 0; +} + + + + +int CXmlDocument::GetNodeCount(char* szTag) +{ + m_nodes = 0; + + char* szCurrentTag; + XmlNode node; + + node = GetNextNode(XML_ROOT_NODE); + while (node>0) + { + szCurrentTag = GetNodeTag(node); + if ( !strcmpi(szCurrentTag,szTag) ) + m_nodes++; + + node = GetNextNode(node); + } + + return m_nodes; +} + + + +////////////////////////////////////////////////////////////////////////////////// +// Function: xml_next_tag +// Moves the current position to the next tag. +// +XmlNode CXmlDocument::GetNextNode(XmlNode node) +{ + int openBracket = -1; + int closeBracket = -1; + int i; + char c; + + for (i=node; i') + { + closeBracket=i; + break; + } + } + } + + if ((openBracket>=0) && (closeBracket>=0)) + { + return openBracket+1; + } + + return 0; +} + + +////////////////////////////////////////////////////////////////////////////////// +// Function: xml_get_tag_name +// Gets the tag name at the current position (max 32 chars!). +// +char* CXmlDocument::GetNodeTag(XmlNode node) +{ + int i; + char c; + + for (i=node; i') ) + { + memcpy(m_szTag,&m_doc[node],i-node); + m_szTag[i-node]=0; + return m_szTag; + } + } + + return 0; +} + + +////////////////////////////////////////////////////////////////////////////////// +// Function: xml_get_child_tag +// Gets the position of the child tag. +// +XmlNode CXmlDocument::GetChildNode(XmlNode node, char* szTag) +{ + char szCurrentTag[32]; + char* szChildTag; + + // get parent node tag + strcpy(szCurrentTag,GetNodeTag(node)); + + // get child node + node = GetNextNode(node); + while (node>0) + { + // get child node tag + szChildTag = GetNodeTag(node); + + // does the child's tag match the one we're looking for + if ( !strcmpi(szChildTag,szTag) ) + return node; + + // is this actually the parent's closing tag? + else if ( !strcmpi(&szChildTag[1],szCurrentTag) ) + return 0; + + node = GetNextNode(node); + } + + return 0; +} + + + +////////////////////////////////////////////////////////////////////////////////// +// Function: xml_get_tag_text +// Gets the text of a given tag (max limit 128 chars!!). +// +char* CXmlDocument::GetNodeText(XmlNode node) +{ + int i,text=0; + int opens=1; + int elements=0; + char c; + for (i=node;i<(m_size-1);i++) + { + c = m_doc[i]; + + switch (c) + { + case '<': + opens++; + if (m_doc[i+1]!='/') + elements++; + else + elements--; + break; + case '>' : + opens--; + break; + case ' ' : + case '\n': + case '\r': + case '\t': + break; + default: + if ((opens==0) && (elements==0)) + text = i; + break; + } + + if (text) + break; + } + + if (!text) + return 0; + + for (i=text;i0) + { + szCurrentTag = GetNodeTag(node); + if ( !strcmpi(szCurrentTag,szTag) ) + pFunc(szTag,node); + + node = GetNextNode(node); + } +} diff --git a/src/XmlDocument.h b/src/XmlDocument.h new file mode 100644 index 0000000..32b3fcb --- /dev/null +++ b/src/XmlDocument.h @@ -0,0 +1,127 @@ +#if !defined(AFX_XMLDOCUMENT_H__D68461F7_E0CE_4FA0_B1C9_0541610164E9__INCLUDED_) +#define AFX_XMLDOCUMENT_H__D68461F7_E0CE_4FA0_B1C9_0541610164E9__INCLUDED_ + +/* + * Copyright (C) 2004-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +// XmlDocument.h: interface for the CXmlDocument class. +// +////////////////////////////////////////////////////////////////////// + +#pragma once + +//#include +#include +#include + +#define XML_ROOT_NODE 0 +#define XML_MAX_TAGNAME_SIZE 32 +#define XML_MAX_INNERTEXT_SIZE 1024 + +typedef int XmlNode; +typedef void (*XmlNodeCallback) (char* szTag, XmlNode node); + + + +class CXmlDocument +{ +public: + CXmlDocument(); + virtual ~CXmlDocument(); + + void Create(char* szString); + int Load(char* szFile); + void Close(); + + int GetNodeCount(char* tag); + + void EnumerateNodes(char* szTag, XmlNodeCallback pFunc); + + XmlNode GetChildNode(XmlNode node, char* szTag); + XmlNode GetNextNode(XmlNode node); + char* GetNodeText(XmlNode node); + char* GetNodeTag(XmlNode node); + +private: + + char* m_doc; + int m_size; + int m_nodes; + char m_szTag[XML_MAX_TAGNAME_SIZE]; + char m_szText[XML_MAX_INNERTEXT_SIZE]; +}; + +class WriteXML +{ +public: + WriteXML() { m_file = NULL; m_rootTag = NULL; }; + ~WriteXML() { Close(); }; + + bool Open(const char *szFile, const char *szOpeningTag) + { + remove(szFile); + if (!szFile || !szOpeningTag) return false; + m_file = fopen(szFile, "w"); + if (!m_file) return false; + m_rootTag = new char[strlen(szOpeningTag) + 1]; + strcpy(m_rootTag, szOpeningTag); + fprintf(m_file, "<%s>\n", m_rootTag); + return true; + }; + void Close() + { + if (m_file) + { + if (m_rootTag) + fprintf(m_file, "\n", m_rootTag); + fclose(m_file); + } + delete[] m_rootTag; + m_rootTag = NULL; + m_file = NULL; + }; + void WriteTag(const char *szTag, const char *data) + { + if (!m_file || !szTag || !data) return; + fprintf(m_file, "\t<%s>%s\n", szTag, data, szTag); + }; + void WriteTag(const char *szTag, int data, const char *format = "%i") + { + char temp[10]; + sprintf(temp, format, data); + WriteTag(szTag, temp); + }; + void WriteTag(const char *szTag, float data) + { + if (!m_file || !szTag) return; + fprintf(m_file, "\t<%s>%f\n", szTag, data, szTag); + }; + void WriteTag(const char *szTag, bool data) + { + if (!m_file || !szTag) return; + fprintf(m_file, "\t<%s>%s\n", szTag, data ? "true" : "false", szTag); + }; + +private: + char *m_rootTag; + FILE *m_file; +}; + +#endif // !defined(AFX_XMLDOCUMENT_H__D68461F7_E0CE_4FA0_B1C9_0541610164E9__INCLUDED_) diff --git a/visualization.milkdrop/addon.xml b/visualization.milkdrop/addon.xml new file mode 100644 index 0000000..9ebe17a --- /dev/null +++ b/visualization.milkdrop/addon.xml @@ -0,0 +1,116 @@ + + + + + MilkDrop laat jou sweef deur die klankgolwe wat jy hoor + يحلق بك MilkDrop فوق الموجات الصوتية اللتي تسمع + MilkDrop takes you flying through the soundwaves you're hearing + "MilkDrop" ще Ви отведе на пътешествие между звуковите вълни, които чувате + MilkDrop et porta volant a través de les ones de so que escoltes + MilkDrop s Vámi proletí skrz zvukové vlny, které slyšíte + Mae MilkDrop yn eich hedeg drwy'r tannau sain rydych yn eu clywed + Milkdrop tager dig på en flyvetur gennem lydbølgerne, du lytter til + MilkDrop nimmt dich mit auf einen Flug durch deine Musik. + Το MilkDrop σας ταξιδεύει μέσα στα ηχητικά κύματα που ακούτε + MilkDrop takes you flying through the soundwaves you're hearing + MilkDrop takes you flying through the soundwaves you're hearing + MilkDrop takes you flying through the soundwaves you're hearing + MilkDrop takes you flying through the soundwaves you're hearing + MilkDrop te lleva volando a través de las ondas que estás escuchando + MilkDrop te lleva volando a través de las ondas que estás escuchando + MilkDrop the lleva volando a través de las ondas de sonido que estás escuchando + MilkDrop viib sind lennates läbi kullatavate helilainete + MilkDrop lennättää sinut ääniaaltojen läpi + MilkDrop vous fait voyager dans les ondes sonores de votre musique + MilkDrop vous fait voler au travers des ondes sonores que vous entendez + MilkDrop lévate voando a través da ondas de son que esta a ouvir + MilkDrop לוקח אותך לתעופה דרך גלי הסאונד שאתה שומע + MilkDrop vam omogućuje let kroz zvuk koji čujete + A Milkdrop végigrepít a zene hullámain + MilkDrop membawa anda terbang melalui gelombang suara yang anda dengarkan + Með MilkDrop flýgurðu í gegnum hljóðbylgjurnar sem þú heyrir + MilkDrop ti fa volare tra le onde sonore di ciò che stai ascoltando + MilkDrop - 音楽の波の上を飛ぶ + MilkDrop은 사운드웨이브 속으로 날아가는듯한 효과를 보여줍니다. + MilkDrop nukelia Jus i nuostabu skrydi virs debesu, istiesu fantastisku garsu gausa + MilkDrop paņem Jūs līdzi lidojumā cauri skaņu viļņiem, kurus dzirdat + MilkDrop ве прелетува преку брановите на музиката која ја слушате + Met MilkDrop vliegt u mee door de geluidsgolven die je hoort + MilkDrop tar deg med på en flyreise gjennom lydbølgene du hører + MilkDrop zabiera Cię w niesamowity lot w chmurach aktualnie słuchanych dźwięków + O MilkDrop leva-o num voo através das ondas sonoras que está a ouvir + O MilkDrop leva você para voar nas ondas sonoras que está ouvindo + MilkDrop vă face să zburați printre undele audio pe care le auziți + Milkdrop отправит вас в полёт через звуковые волны, которые вы слышите + MilkDrop s Vami poletí zvukovými vlnami, ktoré počúvate + MilkDrop vas popelje skozi zvočne valove, ki jih poslušate + MilkDrop të bën të fluturosh nëpër valet të tingullit që e dëgjonë + Milkdrop för dig flygande genom de ljudvågor du hör. + MilkDrop நீங்கள் கேட்கும் ஒலி அலைகளின் வடிவங்களின் மூலம் பறக்க செய்யும் + MilkDrop бо мавҷҳои садояш фораму роҳатбахш аст + MilkDrop นำคุณโบยบิน ผ่านคลื่นเสียงที่คุณกำลังรับฟัง + MilkDrop sizi duymakta olduğunuz ses dalgalarının içine çeker + MilkDrop забере вас в політ крізь хвилі музики яку ви слухаєте + MilkDrop giúp bạn bay bổng trong âm thanh bạn đang nghe + MilkDrop 带你与声波一起飞翔 + MilkDrop帶您穿越聆聽中的音樂饗宴 + MilkDrop was oorspronklik 'n musiek visualisering "plug-in" vir die Winamp musiek speler. Soos jy na jou musiek luister, laat MilkDrop jou deur die klankgolwe sweef wat jy hoor, en gebruik klop waarnemings om 'n magdom psigedeliese effekte te aktiveer, en 'n visuele reis deur klank te skep. + ميلك دروب كان أصلا عارض موسيقى لمشغل الموسيقى وين امب. عندما تستمع لموسيقاك, كيلك دروب يطير بك خلال موجات صوتية تسمعا حيقيةً, ,و يستخدم كشف الوقع الموسيقي ليؤدي إلى تأثيرات كثيرة, منشئاً رجلة صوت مرئية قيمة. + MilkDrop was originally a music visualizer "plug-in" to the Winamp music player. As you listen to your music, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger myriad psychedelic effects, creating a rich visual journey through sound. + Първоначално "MilkDrop" е замислена като приставка за музикалния плеър Winamp. Докато слушате музикалната си колекция "MilkDrop" ще Ви накара да "полетите", измежду звуковите вълни, които чувате. Ползва ритъма за да създаде безброй еуфорични ефекти. Така създава едно богато визуално пътешествие в звука. + El MilkDrop era originalment un afegitó de visualització musical pel reproductor Winamp. Mentre escoltes la música MilkDrop et porta volant a través de les ones de so que estàs escoltant al moment, i utilitza detecció de tempo per activar una munió d'efectes psicodèlics i crea un enriquidor viatge visual a través del so. + MikDrop bylo původně vizualizační rozšíření pro přehrávač hudby Winamp. Při poslechu vaší hudby s Vámi MikDrop prolétá skrze zvukové vlny, které slyšíte, a používá detekci taktů, pro spuštění spousty psychedelických efektů, vytvářejíce tak zajímavou vizuální cestu skrze zvuk. + Roedd MilkDrop yn wreiddiol yn "ategyn" delweddu cerddoriaeth ar gyfer Winamp. Wrth i chi wrando ar MilkDrop mae MilkDrop yn eich hedeg drwy'r tonnau sain rydych yn eu clywed gan ddefnyddio canfodydd trawiad i gychwyn effeithiau seicadelig amrywiol gan greu taith weledol cyfoethog drwy'r sain. + Milkdrop var oprindeligt et musikvisualisering "plug-in" til Winamp musikafspilleren. Mens du lytter til din musik, tager Milkdrop dig på en flyvetur gennem de faktiske lydbølger du hører og bruger beat-genkendelse til at udløse en myriade af psykedeliske effekter, der skaber en visuel rejse gennem lyd. + MilkDrop war ursprünglich ein Musik-Visualizer "Plug-in" für den Musik-Player Winamp.Wenn Sie Ihre Musik hören, fliegen Sie mit MilkDrop durch die aktuellen Klangwellen die Sie hören. Und die Beat-Erkennung wird genutzt um unzählige psychedelische Effekte auslösen, die Schaffung einer visuellen Reise durch den Klang. + Το MilkDrop ήταν αρχικά ένα "plug-in" μουσικών οπτικοποιήσεων του Winamp. Καθώς παίζετε τη μουσική σας, το MilkDrop σας ταξιδεύει μέσα στα πραγματικά ηχητικά κύματα που ακούτε, και χρησιμοποιεί ανίχνευση ρυθμού για να ενεργοποιήσει ένα πλήθος ψυχεδελικών εφέ, δημιουργώντας ένα πλούσιο οπτικό ταξίδι μέσα στον ήχο. + MilkDrop was originally a music visualiser "plug-in" to the Winamp music player. As you listen to your music, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger myriad psychedelic effects, creating a rich visual journey through sound. + MilkDrop was originally a music visualiser "plug-in" to the Winamp music player. As you listen to your music, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger a myriad of psychedelic effects, creating a rich visual journey through sound. + MilkDrop was originally a music visualizer "plug-in" to the Winamp music player. As you listen to your music, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger myriad psychedelic effects, creating a rich visual journey through sound. + MilkDrop era originalmente un plug-in visualizador de música para Winamp. Mientras escuchas música, MilkDrop te lleva volando a través de las ondas que estás escuchando, y utiliza la detección del ritmo para activar una gran cantidad de efectos psicodélicos, creando una rica experiencia visual a través del sonido. + MilkDrop era originalmente un plug-in visualizador de música para Winamp. Mientras escuchas música, MilkDrop te lleva volando a través de las ondas que estás escuchando, y utiliza la detección del ritmo para activar una gran cantidad de efectos psicodélicos, creando una rica experiencia visual a través del sonido. + MilkDrop originalmente fue un "plug-in" visualizador de música para el reproductor de música Winamp. Mientras escuchas tu músuca, MilkDrop te lleva volando a través de las ondas de sonido que estás escuchando en ese momento, y usa detección de ritmo para desencadenar múltiples efectos psicodélicos, creando un rico recorrido visual a través del sonido. + MilkDrop oli algselt muusika visuaal plugin Winamp'ile. Muusikat kuulates viib MilkDrop sind lennates läbi kuulatavate helilainete. MilkDrop kasutab rütmituvastust, et päästa valla tohutu hulk psühhedeelseid efekte luues visuaalidest rikka teekonna läbi heli. + MilkDrop oli alunperin Winampin visualisaattorilisäosa. Kuunnellessasi musiikkia MilkDrop lennättää sinut kuulemiesi ääniaaltojen läpi ja käyttää tahdintunnistusta lukemattomien psykedeelisten tehosteiden toistamiseen, luoden visuaalisen matkan musiikin läpi. + MilkDrop était à l'origine une extension de visualisation musicale pour le lecteur audio Winamp. Pendant que vous écoutez votre musique, Milkdrop vous fait voyager à travers les ondes sonores que vous entendez, détectant le rythme pour déclencher une myriade d'effets psychédéliques, créant ainsi une riche expérience visuelle et sonore. + MilkDrop était à l'origine un plugiciel de visualisation musicale pour le lecteur audio Winamp. Alors que vous écoutez votre musique, Milkdrop vous fait voler au travers des ondes sonores, et utilise la détection rythmique pour déclencher une myriade d'effets psychédéliques, créant un voyage visuel et sonore. + MilkDrop foi orixinalmente un plugin de Visualización para múica do reprodutor de música Winamp. Nametres vostede escoita a súa música, MilkDrop lévao voando a través das ondas de son que esta a ouvir, e emprega a detección de ritmo para activar milleiros de efectos psicodélicos, creando unha rica viaxe visual a través do son. + MilkDrop was originally a music visualizer "plug-in" to the Winamp music player. As you listen to your music, MilkDrop takes you flying through the actual soundwaves you're hearing, and uses beat detection to trigger myriad psychedelic effects, creating a rich visual journey through sound. + MilkDrop je orginalno bio zamišljen kao "dodatak" za Winamp glazbeni svirač. Dok slušate svoju glazbu, MilkDrop vam omogućuje let kroz zvuk koji čujete i koristi otkrivanje taktova da bi pokrenuo bezbroj psihodeličnih efekata, tako stvarajući bogato vizualno zvučno putovanje. + A Milkdrop eredetileg egy beépülőmodul volt a Winamp zenelejátszóhoz. Ahogy hallgatod a zenét, a Milkdrop keresztülrepít a hallható hanghullámokon, felhasználva a dobritmust pszihedelikus effektusok létrehozására gazdag látványvilág megteremtésével. + MilkDrop awalnya adalah pengaya visualisasi musik untuk Winamp. Sembari mendengarkan musik, MilkDrop akan membawa Anda terbang melalui gelombang suara yang Anda dengarkan, dan menggunakan deteksi ketukan untuk menampikan banyak sekali efek psikedelik, menciptakan suatu perjalanan visual yang kaya melalui suara. + Milkdrop var upprunalega viðbót við Winamp tónlistarspilarann. Þegar þú hlustar á tónlistina, fer Milkdrop með þig á flug í gegnum hljóðbylgjurnar sem þú heyrir og notar taktskynjun til að setja af stað allskonar effekta sem skapa myndrænt ferðalag í gegnum tónlistarupplifunina + MilkDrop era, in origine, un "plug-in" di visualizzazione per Winamp. Mentre ascolti la musica, MilkDrop ti fa volare tra le onde sonore di ciò che stai ascoltando usando la rilevazione del ritmo per sincronizzare una miriade di effetti psichedelici, creando un ricco viaggio visuale attraverso il suono. + MilkDrop は元々 Winamp 音楽プレーヤーのビジュアライザープラグインでした。音楽を再生すると、音楽にあわせた波の上を飛んでいるような視覚効果が現れ、ビート検出により無数のサイケデリックな効果が生まれ、音による視覚的体験を生み出します。 + MilkDrop는 원래 윈앰프의 음악 시각화 플러그인입니다. 음악을 들으면서 사운드 웨이브로 날아가는듯한 효과를 보여주며 비트 감지를 해서 다양한 싸이키데릭한 효과를 만들어 풍부한 시각적 경험을 하게합니다. + MilkDrop vizualizacija, gauta is Winamp. Klausantis muzikos, MilkDrop nukelia jus i nuostabu skrydi virs debesu, naudojamas ritmo aptikimas, kuris sinchronizuoja muzikos vaizdo efektus. + MilkDrop sākotnēji bija mūzikas vizualizācijas "spraudnis" Winamp mūzikas atskaņotājā. Kamēr tu klausies mūziku, MilkDrop paņem tevi līdz lidojumā cauri skaņas viļņiem, kuri skan, un izmanto ritma noteikšanu, lai palaistu myriad psihodēliskos efektus, radot bagātu vizuālo ceļojumu cauri skaņai. + MilkDrop беше визуализација допонување на Winamp music player. Како што ја слушате музиката, MilkDrop ве прелетува преку актуелните музички бранови, и користи детекција на битот за да покрене myriad психоделични ефекти, креирајќи богато визуелно патување низ звукот. + Milkdrop was oorspronkelijk een muziekvisualisatieplug-in voor de Winamp-muziekspeler. Terwijl u uw muziek beluistert vliegt Milkdrop u door de soundwaves die u op dat moment hoort. Op basis van de beat produceert het een veelvoud aan psychedelische effecten. + MilkDrop var originalt et visualiseringstillegg til musikkavspilleren Winamp. Mens du lytter til musikken din, tar MilkDrop deg med på en reise gjennom de faktiske lydbølgene du hører. Visualiseringen oppdager takten i musikken og bruker denne for å skape en rik, visuell ferd gjennom utallige, psykedeliske effekter. + MilkDrop jest wizualizacją pochodzącą z odtwarzacza Winamp. W czasie słuchania muzyki, MilkDrop zabiera użytkownika w niesamowity lot pomiędzy aktualnie odtwarzanymi falami dźwiękowymi, używając detekcji beatu, która synchronizuje efekty wizualne z muzyką. + Originalmente, o MilkDrop era uma visualização do leitor de música Winamp. Ao ouvir a sua música, o MilkDrop leva-o a voar pelas ondas sonoras que está a ouvir, detectando o ritmo da música e desencadeando uma variedade de efeitos psicadélicos. Cria, assim, uma viagem inesquecível pelo som. + MilkDrop era originalmente uma visualização do reprodutor de música Winamp. Ao ouvir a sua música, o MilkDrop leva-o a voar nas ondas sonoras que está a ouvir, usando detecção de batida para desencadear uma miríade de efeitos psicodélicos. Cria, assim, uma viagem visual inesquecível pelo som. + MilkDrop a fost original un „modul” de vizualizare pentru lectorul de muzică Winamp. În timp ce ascultați muzica, MilkDrop vă face să zburați printre undele audio actuale pe care le auziți și folosește detecția bătăii pentru a activa miriada de efecte psihedelice, creând o călătorie vizuală bogată printre sunete. + MilkDrop изначально был модулем визуализации музыки для проигрывателя Winamp. Когда вы слушаете музыку, MilkDrop создает визуальное ощущение полёта по звуковым волнам, а также использует обнаружение ритма для активации множества психоделических эффектов. + MilkDrop bol pôvodne hudobným vizualizačným rozšírením Winamp prehrávača. Pri počúvaní hudby s Vami MilkDrop letí zvukovými vlnami, ktoré počúvate a použitím detekcie rytmu spúšťa nespočetné psychodelické efekty, a vytvára bohatú vizuálnu cestu zvukom. + MilkDrop je bila prvotno vizualizacija za predvajalnik Winamp. Ko poslušate vašo glasbo, vas MilkDrop popelje skozi dejansko valovanje, ki ga slišite, in uporablja zaznavanje ritma, kar omogoči psihedelični efekt in bogato vizualno izkušnjo predvajanja glasbe. + Milkrop fillimisht ishte një "plug-in" për vizualizimin e muzikës për riprodhuesin Winamp. Ndërsa dëgjonë muzikën tënde, Milkdrop vizualizon valët që i dëgjon dhe përdor zbulimin e tingullit për efekte të ndryshme. + Milkdrop var ursprungligen ett visualiserarande ljudplug-in till Winamp. Medan du lyssnar på din musik så för dig Milkdrop flygande genom de ljudvågor du hör och använder rytmavkänning för att ge dig psykedeliska effekter som skapar en mäktig visuell resa via ljudet. + MilkDrop முதலில் Winamp இசை வாசிபானுடைய ஒரு இசை விசுவலைஸர் "செருகுநிரல்"ஆகும். நீங்கள் இசை கேட்டுக்கொண்டு இருக்குபோது, MilkDrop ஆனது உங்களை ஒலி அலைகளின் அமைப்புகேர்ப்ப உங்களை பறக்க செய்யும், மேலும் இசை துடிப்புகேர்ப்ப எண்ணற்ற சைக்டெலிக் விளைவுகளை உண்டாக்கும், ஒலி மூலம் ஒரு மறக்கமுடியாத காட்சி பயணம் உருவாக்கும். + MilkDrop аз ибтидо плагини таҷассуми мусиқие барои плеери мусиқии Winamp буд. Вақте ки шумо мусиқиро мешунавед, MilkDrop бо мавҷҳои садояш фораму роҳатбахш аст, ва муайянкуни битҳои мусиқиро барои эҷоди таъсирҳои девонагӣ истифода мекунад ва шуморо ба сайёҳии мусиқӣ мебарад. + MilkDrop แต่เดิมเป็น "ปลั๊ก-อิน" การแสดงแสงสีประกอบเพลง ของโปรแกรมเล่นเพลง Winamp. ในขณะที่คุณฟังเพลงของคุณ, MilkDrop นำคุณบินผ่านคลื่นเสียงที่เกิดขึ้นตามที่คุณได้ยิน, และใช้การจับจังหวะ ในการส่งผลต่อเอฟเฟคภาพลวงตา อันหลากหลาย, สร้างภาพอันตื่นตาในการเดินทางไปตามเสียงเพลง. + MilkDrop aslında Winamp müzik çalıcısı için görsel bir "eklenti" dir. Müziğinizi dinlerken, Milkdrop size işittiğiniz ses dalgaları arasında uçuyormuşcasına bir his ve ritm algılayıcısı ile de en çılgın efektleri yaşıyormuşçasına görsel bir şölen sunar. + MilkDrop спочатку був додатком візуалізації музики для програвача музики Winamp. MilkDrop створює багату гаму візуалізації музики, використовуючи власний механізм визначення музичних тактів. + MilkDrop ban đầu là một "plug-in" trình diễn nhạc cho Winamp. Khi bạn nghe nhạc, MilkDrop sẽ làm bạn bay bổng trong âm thanh bạn đang nghe, và sử dụng bộ dò giai điệu để kích hoạt vô số những hiệu ứng ảo, tạo ra một cuộc hành trình âm thanh qua mắt thường + MilkDrop 是来自于 Winamp 音乐播放器的可视化效果插件。在你听音乐时,MilkDrop 通过节拍检测触发的无数迷幻的效果,带你与声波一起飞翔,给你带来丰富的音乐和视觉旅程。 + MilkDrop是來自於Winamp音樂播放器的視覺效果插件。在您在聽音樂時,MilkDrop通過節奏偵測觸發的無數夢幻的效果,帶您穿越聆聽中的音樂饗宴,也給您帶來豐富的聲音和視覺效果的奇幻旅程。 + windx + + diff --git a/visualization.milkdrop/icon.png b/visualization.milkdrop/icon.png new file mode 100644 index 0000000..8014030 Binary files /dev/null and b/visualization.milkdrop/icon.png differ diff --git a/visualization.milkdrop/presets/WA51-presets(265).zip b/visualization.milkdrop/presets/WA51-presets(265).zip new file mode 100644 index 0000000..725cafc Binary files /dev/null and b/visualization.milkdrop/presets/WA51-presets(265).zip differ diff --git a/visualization.milkdrop/presets/Winamp-presets(436).zip b/visualization.milkdrop/presets/Winamp-presets(436).zip new file mode 100644 index 0000000..7670280 Binary files /dev/null and b/visualization.milkdrop/presets/Winamp-presets(436).zip differ diff --git a/visualization.milkdrop/resources/language/Afrikaans/strings.po b/visualization.milkdrop/resources/language/Afrikaans/strings.po new file mode 100644 index 0000000..1eb5d44 --- /dev/null +++ b/visualization.milkdrop/resources/language/Afrikaans/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Afrikaans (http://www.transifex.com/projects/p/xbmc-main/language/af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Outomatiese Meng Tyd" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tyd Tussen Voorafinstellings" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Addisionele Lukraak Tyd" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Stel Anisotrope Filter in staat" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Stel Harde Snye in Staat" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Luidheid Drumpel vir Harde Snye" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Gemiddelde Tyd Tussen Harde Snye" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksimum Verfris Tempo" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Aktiveer Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Voorafinstellings Pak" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Gebruiker Voorafinstellings Vouer " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Voorafinstellings Skommel Modus" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Voorafinstellings" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Voorafinstellings" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Gebruiker Gedefinieerde Voorafinstellings Vouer" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sek." + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f rps" diff --git a/visualization.milkdrop/resources/language/Albanian/strings.po b/visualization.milkdrop/resources/language/Albanian/strings.po new file mode 100644 index 0000000..ed9cf4e --- /dev/null +++ b/visualization.milkdrop/resources/language/Albanian/strings.po @@ -0,0 +1,33 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Albanian (http://www.transifex.com/projects/p/xbmc-main/language/sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Paketë e të paravendosurve" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Regjistri i paravendosurve i zgjedhur nga përdoruesi" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sekonda" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" diff --git a/visualization.milkdrop/resources/language/Amharic/strings.po b/visualization.milkdrop/resources/language/Amharic/strings.po new file mode 100644 index 0000000..33fb3ec --- /dev/null +++ b/visualization.milkdrop/resources/language/Amharic/strings.po @@ -0,0 +1,29 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Amharic (http://www.transifex.com/projects/p/xbmc-main/language/am/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: am\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Arabic/strings.po b/visualization.milkdrop/resources/language/Arabic/strings.po new file mode 100644 index 0000000..9a8598c --- /dev/null +++ b/visualization.milkdrop/resources/language/Arabic/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Arabic (http://www.transifex.com/projects/p/xbmc-main/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "مزيج وقت تلقائي" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "الزمن بين الإعدادات المسبقة" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "وقت إضافي عشوائي" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "تمكين تنقية التباين" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "تمكين التوقفات القوية" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "عتبة الضجيج للتقطعات." + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "متوسط الزمن بين الانقطاعات القوية" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "أقصى معدل التحديث" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "تمكين Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "حزمة الإعدادات المسبقة" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "مجلد الإعدادات المسبقة للمستخدم" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "الوضع العشوائي للإعدادات المسبقة" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 نغمات" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr " تغمات وين امب" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "مستخدم مجلد نغمات معرف" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Belarusian/strings.po b/visualization.milkdrop/resources/language/Belarusian/strings.po new file mode 100644 index 0000000..00e2848 --- /dev/null +++ b/visualization.milkdrop/resources/language/Belarusian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Belarusian (http://www.transifex.com/projects/p/xbmc-main/language/be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatic Blend Time" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Time Between Presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Additional Random Time" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Enable Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Enable Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudness Threshold For Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Average Time Between Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximum Refresh Rate" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Enable Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Preset Pack" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "User Preset Folder " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Shuffle Mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Presets" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Presets" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "User Defined Preset Folder" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f сэк." + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Bulgarian/strings.po b/visualization.milkdrop/resources/language/Bulgarian/strings.po new file mode 100644 index 0000000..d423145 --- /dev/null +++ b/visualization.milkdrop/resources/language/Bulgarian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Bulgarian (http://www.transifex.com/projects/p/xbmc-main/language/bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Време за автоматично сливане" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Време между отделните шаблони" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Допълнително произволно време" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Включи анизотропното филтриране" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Включи Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Прагове на усилване за Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Средно време между Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Максимум за честотата на обновяване" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Включи 3D стерео режим" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Пакет шаблони" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Папка със шаблони " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Режим за смяна на шаблоните" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Шаблони" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Шаблони от Winamp " + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Папка за шаблоните на потребителя" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f сек" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Burmese/strings.po b/visualization.milkdrop/resources/language/Burmese/strings.po new file mode 100644 index 0000000..9ff6673 --- /dev/null +++ b/visualization.milkdrop/resources/language/Burmese/strings.po @@ -0,0 +1,57 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Burmese (http://www.transifex.com/projects/p/xbmc-main/language/my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Preset များအတွင်းကြာချိန်" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Stereo 3D ဖွင့်ထားမည်" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "အသုံးပြုသူ၏ Preset ဖိုလ်ဒါလ်" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Shuffle Mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Presets" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Presets" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "အသုံးပြုသူသတ်မှတ်ထားသော Preset ဖိုလ်ဒါလ်" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Catalan/strings.po b/visualization.milkdrop/resources/language/Catalan/strings.po new file mode 100644 index 0000000..80992c1 --- /dev/null +++ b/visualization.milkdrop/resources/language/Catalan/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Catalan (http://www.transifex.com/projects/p/xbmc-main/language/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Temps de mescla automàtica" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Temps entre predefinits" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Temps Aleatori Addicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Habilita el filtre anisotròpic" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Habilita talls en sec" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Llindar de volum pels talls en sec" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Temps mig entre talls en sec" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Temps de refresc màxim" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Habilita l'estèreo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Paquet de predefinits" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Directori de predefinits de l'usuari" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Mode aleatori de predefinits" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Predefinits WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Predefinits Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Directori de predefinits establert per l'usuari" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f seg" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Chinese (Simple)/strings.po b/visualization.milkdrop/resources/language/Chinese (Simple)/strings.po new file mode 100644 index 0000000..74fc849 --- /dev/null +++ b/visualization.milkdrop/resources/language/Chinese (Simple)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Chinese (Simple) (http://www.transifex.com/projects/p/xbmc-main/language/zh/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "自动混合时间" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "预置切换时间" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "附加随机时间" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "启用各向异性过滤" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "启用硬切" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "硬切响度门限" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "硬切平均间隔" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "最大刷新率" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "启用3D立体声" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "预置包" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "用户预置文件夹" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "预置随机模式" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 预置" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp 预置" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "用户定义的预置文件夹" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f 秒" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Chinese (Traditional)/strings.po b/visualization.milkdrop/resources/language/Chinese (Traditional)/strings.po new file mode 100644 index 0000000..08e3753 --- /dev/null +++ b/visualization.milkdrop/resources/language/Chinese (Traditional)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Chinese (Traditional) (http://www.transifex.com/projects/p/xbmc-main/language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "自動混音時間" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "預置切換時間" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "附屬隨機時間" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "啟用各向異性過濾器" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "啟用 Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Hard Cuts 響度限位" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Hard Cuts平均間隔時間" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "最高更新率" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "啟用Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "預置封包" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "使用者預置資料夾" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "預置隨機撥放模式" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 預置" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp 預置" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "使用者定義的預置資料夾" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f 秒" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Croatian/strings.po b/visualization.milkdrop/resources/language/Croatian/strings.po new file mode 100644 index 0000000..f0d2cac --- /dev/null +++ b/visualization.milkdrop/resources/language/Croatian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Croatian (http://www.transifex.com/projects/p/xbmc-main/language/hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatsko vrijeme miješanja" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Vrijeme između predloška" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Dodatno naizmjenično vrijeme" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Omogućite Anizotropno filtriranje" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Omogući velike rezove" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Prag glasnoće za velike rezove" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Prosječno vrijeme između veliki rezova" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksimalna brzina osvježavanja" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Omogući Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Paket predložaka" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Mapa korisnikovih predložaka" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Način naizmjeničnih predložaka" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 predlošci" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp predlošci" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Korisnički odabrana mapa predložaka" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sekundi" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Czech/strings.po b/visualization.milkdrop/resources/language/Czech/strings.po new file mode 100644 index 0000000..0c5b976 --- /dev/null +++ b/visualization.milkdrop/resources/language/Czech/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Czech (http://www.transifex.com/projects/p/xbmc-main/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatický čas sloučení" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Čas mezi předvolbami" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Dodatečný náhodný čas" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Povolit artroskopické filtrování" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Povolit ostrá utnutí" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Hrana hlasitosti pro ostré utnutí" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Průměrný čas mezi ostrými utnutími" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximální obnovovací frekvence" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Povolit Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Balíček předvoleb" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Složka uživatelských předvoleb " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Režim náhodné předvolby" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Předvolby WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Předvolby Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Uživatelem zadaná složka předvoleb" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f s" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Danish/strings.po b/visualization.milkdrop/resources/language/Danish/strings.po new file mode 100644 index 0000000..7c29334 --- /dev/null +++ b/visualization.milkdrop/resources/language/Danish/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Danish (http://www.transifex.com/projects/p/xbmc-main/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatisk blandingstid" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tid mellem forudindstillinger" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Ekstra tilfældig tid" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Aktiver anisotropisk filtrering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Muliggør hårde skift" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Niveautærskel for hårde skift" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Gennemsnitlig tid mellem hårde skift" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksimal opdateringshastighed" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Aktiver stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Forudindstillings-pakke" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Brugermappe med forudindstillinger" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Forudindstillet blandingstilstand" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 forudindstillinger" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp forudindstillinger" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Brugerdefineret mappe med forudindstillinger" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sek" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Dutch/strings.po b/visualization.milkdrop/resources/language/Dutch/strings.po new file mode 100644 index 0000000..6355b48 --- /dev/null +++ b/visualization.milkdrop/resources/language/Dutch/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Dutch (http://www.transifex.com/projects/p/xbmc-main/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatische overgangstijd" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tijd tussen voorinstelling" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Bijkomende willekeurige tijd" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Anisotropisch filter inschakelen" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Ruwe afkappingen inschakelen" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Geluidssterktedrempel voor een ruwe afkapping" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Gemiddelde tijd tussen ruwe afkappingen" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximale verversingsfrequentie" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Stereo 3D inschakelen" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Voorinstelling pakket" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Gebruiker voorinstelling folder " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Voorinstelling shuffle mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 voorinstelling" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp voorinstelling" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Gebruiker Gedefinieerde voorinstelling folder" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sec." + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/English (Australia)/strings.po b/visualization.milkdrop/resources/language/English (Australia)/strings.po new file mode 100644 index 0000000..35db9f8 --- /dev/null +++ b/visualization.milkdrop/resources/language/English (Australia)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (Australia) (http://www.transifex.com/projects/p/xbmc-main/language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatic Blend Time" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Time Between Presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Additional Random Time" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Enable Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Enable Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudness Threshold For Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Average Time Between Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximum Refresh Rate" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Enable Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Preset Pack" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "User Preset Folder " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Shuffle Mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Presets" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Presets" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "User Defined Preset Folder" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/English (New Zealand)/strings.po b/visualization.milkdrop/resources/language/English (New Zealand)/strings.po new file mode 100644 index 0000000..065febd --- /dev/null +++ b/visualization.milkdrop/resources/language/English (New Zealand)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (New Zealand) (http://www.transifex.com/projects/p/xbmc-main/language/en_NZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_NZ\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatic Blend Time" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Time Between Presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Additional Random Time" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Enable Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Enable Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudness Threshold For Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Average Time Between Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximum Refresh Rate" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Enable Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Preset Pack" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "User Preset Folder " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Shuffle Mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Presets" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Presets" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "User Defined Preset Folder" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/English (US)/strings.po b/visualization.milkdrop/resources/language/English (US)/strings.po new file mode 100644 index 0000000..d498842 --- /dev/null +++ b/visualization.milkdrop/resources/language/English (US)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (US) (http://www.transifex.com/projects/p/xbmc-main/language/en_US/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_US\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatic Blend Time" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Time Between Presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Additional Random Time" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Enable Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Enable Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudness Threshold For Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Average Time Between Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximum Refresh Rate" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Enable Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Preset Pack" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "User Preset Folder " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Shuffle Mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Presets" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Presets" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "User Defined Preset Folder" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/English/strings.po b/visualization.milkdrop/resources/language/English/strings.po new file mode 100644 index 0000000..4613878 --- /dev/null +++ b/visualization.milkdrop/resources/language/English/strings.po @@ -0,0 +1,96 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (http://www.transifex.com/projects/p/xbmc-main/language/en/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#settings labels + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "" + +#empty strings from id 30012 to 30019 + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "" + +#empty strings from id 30023 to 30049 +#setting value formats + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "" diff --git a/visualization.milkdrop/resources/language/Estonian/strings.po b/visualization.milkdrop/resources/language/Estonian/strings.po new file mode 100644 index 0000000..5133f29 --- /dev/null +++ b/visualization.milkdrop/resources/language/Estonian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Estonian (http://www.transifex.com/projects/p/xbmc-main/language/et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automaatne sulanduse aeg" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Eelseadistuste vaheline aeg" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Juhuslik lisaaeg" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Luba anisotroopne filtreerimine" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Kasuta tugevaid kärpeid" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Helitugevuse künnis" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Keskmine intervall" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Suurim värskendussagedus" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Stereo 3D kasutusel" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Eelseadete pakett" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Kasutaja eelseade kaust" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Eelseade segamise režiim" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 eelseaded" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp eelseaded" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Kasutaja määratud eelseade kaust" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f s" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Finnish/strings.po b/visualization.milkdrop/resources/language/Finnish/strings.po new file mode 100644 index 0000000..03f17d2 --- /dev/null +++ b/visualization.milkdrop/resources/language/Finnish/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Finnish (http://www.transifex.com/projects/p/xbmc-main/language/fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automaattinen pehmennysaika" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Esiasetusten välinen aika" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Satunnainen lisäaika" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Anisotrooppinen suodatus käytössä" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Voimakkaat leikkaukset käytössä" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr " - Äänenvoimakkuuden kynnys" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr " - Keskimääräinen väli" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Suurin ruudunpäivitysnopeus" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Stereo 3D käytössä" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Esiasetuspaketti" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Käyttäjän esiasetuskansio " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Esiasetuksen sekoitustila" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51-esiasetukset" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp-esiasetukset" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Käyttäjän määrittämä esiasetuskansio" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f s" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/French (Canada)/strings.po b/visualization.milkdrop/resources/language/French (Canada)/strings.po new file mode 100644 index 0000000..ac6f094 --- /dev/null +++ b/visualization.milkdrop/resources/language/French (Canada)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: French (Canada) (http://www.transifex.com/projects/p/xbmc-main/language/fr_CA/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr_CA\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Durée de mélange automatique" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Intervalle entre les préréglages" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Ajout aléatoire de temps" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activer le filtrage anisotropique" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Activer les coupures brusques" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Seuil de volume pour les coupures brusques" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Temps moyen entre les coupures brusques" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Fréquence de rafraîchissement maximum " + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Activer la stéréo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Jeu de préréglages" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Dossier de préréglages de l'utilisateur " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Mode de préréglages aléatoire" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Préréglages WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Préréglages Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Dossier de préréglages de l'utilisateur" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f s" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f images-par-seconde" diff --git a/visualization.milkdrop/resources/language/French/strings.po b/visualization.milkdrop/resources/language/French/strings.po new file mode 100644 index 0000000..34cd108 --- /dev/null +++ b/visualization.milkdrop/resources/language/French/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: French (http://www.transifex.com/projects/p/xbmc-main/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Durée des combinaisons" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Intervalle des présélections" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Ajout aléatoire de temps" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activer le filtre anisotropique" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Permettre les changements brusques" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Seuil de volume pour les changements brusques" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Temps moyen entre les coupures" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Taux de rafraichissement maximum " + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Activer la Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Pack de présélections" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Dossier de présélections de l'utilisateur " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Mode de présélections aléatoires" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Présélections WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Présélections Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Dossier de présélections de l'utilisateur" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Galician/strings.po b/visualization.milkdrop/resources/language/Galician/strings.po new file mode 100644 index 0000000..eaf7cc6 --- /dev/null +++ b/visualization.milkdrop/resources/language/Galician/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Galician (http://www.transifex.com/projects/p/xbmc-main/language/gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Tempo de mistura automática" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tempo entre preconfiguracións" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tempo ó chou adicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activar filtro anisotrópico" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Activar cortes abruptos" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Umbral de volume alto para cortes abruptos" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tempo medio entre cortes abruptos" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Máximo ratio de refresco" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Activar 3D Stereo" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Pack de preconfiguracións" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Cartafol de preconfiguracións do usuario" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modo aleatorio de preconfiguracións" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Preconfiguracións de WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Preconfiguracións de Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Cartafol de preconfiguracións definido polo usuario" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f seg" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/German/strings.po b/visualization.milkdrop/resources/language/German/strings.po new file mode 100644 index 0000000..8c3c151 --- /dev/null +++ b/visualization.milkdrop/resources/language/German/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: German (http://www.transifex.com/projects/p/xbmc-main/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatische Überblendezeit" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Zeit zwischen den Presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Zusätzliche zufällige Zeit" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Anisotropischen Filter aktivieren" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Hard Cuts aktivieren" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Lautstärken-Grenzwert für Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Durchschnittszeit zwischen Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximale Wiederholrate" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Stereo 3D aktivieren" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Preset Pack" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Benutzer Vorlagen Ordner" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Zufallsvorlagen" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Vorlagen" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Vorlagen" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "benutzerdefinierter Vorlagen Ordner" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sec" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Greek/strings.po b/visualization.milkdrop/resources/language/Greek/strings.po new file mode 100644 index 0000000..a1489a0 --- /dev/null +++ b/visualization.milkdrop/resources/language/Greek/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Greek (http://www.transifex.com/projects/p/xbmc-main/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Χρόνος Αυτόματης Μίξης" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Χρόνος Μεταξύ Προρυθμίσεων" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Επιπλέον Χρόνος Τυχαίων" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Ενεργοποίηση Ανισοτροπικού Φιλτραρίσματος" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Ενεργοποίηση Απότομων Μεταβάσεων" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Κατώφλι Έντασης για τις Απότομες Μεταβάσεις" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Μέσος Χρόνος Μεταξύ Απότομων Μεταβάσεων" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Μέγιστος Ρυθμός Ανανέωσης" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Ενεργοποίηση Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Πακέτο Προρυθμίσεων" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Φάκελος Προρυθμίσεων Χρήστη " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Λειτουργία Ανάμιξης Προρυθμίσεων" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Προρυθμίσεις του WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Προρυθμίσεις του Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Φάκελος Προρυθμίσεων Επιλογής Χρήστη" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f δευτερόλεπτα" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Hebrew/strings.po b/visualization.milkdrop/resources/language/Hebrew/strings.po new file mode 100644 index 0000000..5001abd --- /dev/null +++ b/visualization.milkdrop/resources/language/Hebrew/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Hebrew (http://www.transifex.com/projects/p/xbmc-main/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatic Blend Time" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "זמן בין קביעונים" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Additional Random Time" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Enable Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Enable Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudness Threshold For Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Average Time Between Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "קצב רענון מקסימאלי" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "הפעל סטריאו 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "חבילת קביעונים" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "תיקית קביעוני משתמש" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "קביעון מצב מעורבב" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "קביעוני WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "קביעוני Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "תיקית קביעוני הגדרת משתמש" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f שניות" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Hungarian/strings.po b/visualization.milkdrop/resources/language/Hungarian/strings.po new file mode 100644 index 0000000..80c4174 --- /dev/null +++ b/visualization.milkdrop/resources/language/Hungarian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Hungarian (http://www.transifex.com/projects/p/xbmc-main/language/hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatikus keverési idő" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Idő a beállításkészletek között" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Többlet véletlen idő" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Anisotropic szűrés bekapcsolása" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Éles váltások engedélyezése" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Hangerőküszöb az éles váltásokhoz" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Átlagos idő az éles váltások között" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximális frissítési frekvencia" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Sztereó 3D engedélyezése" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Beállításkészlet-csomag" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Saját-készlet mappa " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Keverési mód" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 beállításkészlet" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp beállításkészlet" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Felhasználói készlet" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f mp" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Icelandic/strings.po b/visualization.milkdrop/resources/language/Icelandic/strings.po new file mode 100644 index 0000000..1de498c --- /dev/null +++ b/visualization.milkdrop/resources/language/Icelandic/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Icelandic (http://www.transifex.com/projects/p/xbmc-main/language/is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Sjálfvirkur blöndunartími" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tími á milli forstillinga" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Aukalegur slembitími" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Virkja Anisotropic filter" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Virkja snöggar skiptingar" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Hljóðstyrks þröskuldur fyrir snöggar skiptingar" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Meðal tími á milli snöggra skiptinga" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Hámarks uppfærslu tími" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Virkja Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Forstillinga pakki" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Mappa fyrir forstillingar notenda" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Slembi hamur forstillinga" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 forstilling" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp forstillingar" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Mappa fyrir forstillingar skilgreindar af notanda" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sekúndur" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Indonesian/strings.po b/visualization.milkdrop/resources/language/Indonesian/strings.po new file mode 100644 index 0000000..d1b8f18 --- /dev/null +++ b/visualization.milkdrop/resources/language/Indonesian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Indonesian (http://www.transifex.com/projects/p/xbmc-main/language/id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Waktu Aduk otomatis" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Waktu Antara Presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tambahan Waktu Acak" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Aktifkan Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Aktifkan Hard Cuts" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Ambang kekerasan untuk Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Waktu rata-rata antara Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Refresh Rate maksimum" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Aktifkan Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Paket Preset" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Folder Preset Pengguna" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Modus Acak " + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Preset WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Preset Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Folder Preset yang ditentukan Pengguna" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f detik" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Italian/strings.po b/visualization.milkdrop/resources/language/Italian/strings.po new file mode 100644 index 0000000..f6ca9d1 --- /dev/null +++ b/visualization.milkdrop/resources/language/Italian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Italian (http://www.transifex.com/projects/p/xbmc-main/language/it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Durata transizione automatica" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tempo tra i preset" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tempo aggiuntivo casuale" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Abilita il filtro anisotropico" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Abilita tagli netti" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Soglia di rumorosità per i tagli netti" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tempo medio tra i tagli netti" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Frequenza di aggiornamento massima" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Abilita effetto 3D anaglifo" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Raccolta preset" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Cartella preset dell'utente " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modalità preset casuale" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Preset WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Preset di Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Cartella personale dei preset" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secondi" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Japanese/strings.po b/visualization.milkdrop/resources/language/Japanese/strings.po new file mode 100644 index 0000000..9009899 --- /dev/null +++ b/visualization.milkdrop/resources/language/Japanese/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Japanese (http://www.transifex.com/projects/p/xbmc-main/language/ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "自動ブレンド時間" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "各プリセットの間隔" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "追加ランダム時間" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "異方性フィルタリングを有効" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "ハードカットを有効" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "ハードカットのラウドネス閾値" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "ハードカット間の平均時間" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "最大リフレッシュレート" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "ステレオ3Dを有効にする" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "プリセットパック" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "ユーザープリセットフォルダ" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "プリセットシャッフルモード" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 プリセット" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp プリセット" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "ユーザー設定プリセットフォルダ" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f 秒" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Korean/strings.po b/visualization.milkdrop/resources/language/Korean/strings.po new file mode 100644 index 0000000..2f3c631 --- /dev/null +++ b/visualization.milkdrop/resources/language/Korean/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Korean (http://www.transifex.com/projects/p/xbmc-main/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "자동 블렌드 시간" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "프리셋사이 간격" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "추가적 랜덤 간격" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "비등방성 필터링 활성화" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "하드컷 활성화" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "하드컷을 위한 음량 임계치" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "하드컷 사이의 평균 시간" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "최대 리프레쉬 레이트" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "스테레오 3D 활성화" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "프리셋 팩" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "사용자 프리셋 폴더" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "무작위 프리셋 모드" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 프리셋" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp 프리셋" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "사용자 정의 프리셋 폴더" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f 초" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Latvian/strings.po b/visualization.milkdrop/resources/language/Latvian/strings.po new file mode 100644 index 0000000..38051d3 --- /dev/null +++ b/visualization.milkdrop/resources/language/Latvian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Latvian (http://www.transifex.com/projects/p/xbmc-main/language/lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automātisks samaisīšanas laiks" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Laiks starp sagatavēm" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Papildus nejaušs laiks" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Ieslēgt anizotropo filtrēšanu" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Ieslēgt ciešo griezšanu" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Skaļuma slieksnis ciešai griezšanai" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Vidējais laiks starp ciešajiem griezieniem" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksimālais pārzīmēšanās biežums" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Ieslēgt Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Sagatavju paka" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Lietotāja sagatavju mape" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Sagatavju jaukšanas režīms" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 sagataves" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp sagataves" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Lietotāja norādīta sagatavju mape" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sekundes" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Lithuanian/strings.po b/visualization.milkdrop/resources/language/Lithuanian/strings.po new file mode 100644 index 0000000..acb22e5 --- /dev/null +++ b/visualization.milkdrop/resources/language/Lithuanian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Lithuanian (http://www.transifex.com/projects/p/xbmc-main/language/lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatinio Perejimo Laikas" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Laikas Tarp Nustatymu" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Papildomas Atsitiktinis Laikas" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Ijungti Anizotropini Filtravima" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Ijungti Staigu Perejima" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Minimalus Garsas del Staigaus Perejimo" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Vidutinis Laikas tarp Staigiu Perejimu" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksimalus Daznui Naujinimas" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Ijungti Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Nustatymu Komplektas" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Vartotojo Nustatymu Aplankas " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Isankstinis Atsitiktinis Rezimas" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Profiliai" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "WinAmp Profiliai" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Apibreztas Vartotojo Aplankas" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Macedonian/strings.po b/visualization.milkdrop/resources/language/Macedonian/strings.po new file mode 100644 index 0000000..efb5b0a --- /dev/null +++ b/visualization.milkdrop/resources/language/Macedonian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Macedonian (http://www.transifex.com/projects/p/xbmc-main/language/mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Автоматско време на блендирање" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Време помеѓу подесувањата" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Дополнително случајно време" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Овозможи Анисотропично филтрирање" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Овозможи јаки пресеци" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudness Threshold For Hard Cuts" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Average Time Between Hard Cuts" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Максимална рата на освежување" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Овозможи Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Preset Pack" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "User Preset Folder " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Preset Shuffle Mode" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Presets" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Presets" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "User Defined Preset Folder" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f сек." + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Norwegian/strings.po b/visualization.milkdrop/resources/language/Norwegian/strings.po new file mode 100644 index 0000000..2c7a9b2 --- /dev/null +++ b/visualization.milkdrop/resources/language/Norwegian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Norwegian (http://www.transifex.com/projects/p/xbmc-main/language/no/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: no\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatisk tid for sammensmelting" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tid mellom forvalg" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Ytterligere tilfeldig tid" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Aktiver anisotropisk filtrering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Aktiver umiddelbare overganger" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Lydgrense for umiddelbare overganger" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Gjennomsnittlig tid mellom umiddelbare overganger" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Høyeste oppdateringsfrekvens" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Aktiver Sterio 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Forhåndsinnstillingspakke" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Mappe for egendefinertee forhåndsinnstillinger" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Blandingsmodus for forhåndsinnstillinger" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 forhåndsinnstillinger" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp forhåndsinnstillinger" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Brukerdefinert forhåndsinnstillingsmappe" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sek" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Polish/strings.po b/visualization.milkdrop/resources/language/Polish/strings.po new file mode 100644 index 0000000..f675680 --- /dev/null +++ b/visualization.milkdrop/resources/language/Polish/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Polish (http://www.transifex.com/projects/p/xbmc-main/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Interwał automatycznego mieszania" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Interwał zdefiniowanych ustawień" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Dodatkowy czas losowy" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Aktywuj filtrowanie anizotropowe" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Aktywuj \"ostre cięcia\"" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Próg głośności dla \"ostrych cięć\"" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Średni czas pomiędzy \"ostrymi cięciami\"" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksymalna częstotliwość odświeżania" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Aktywuj stereofoniczny tryb 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Pakiet zdefiniowanych ustawień" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Folder ustawień użytkownika" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Tryb losowych ustawień" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Ustawienia WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Ustawienia Winampa" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Folder zdefiniowanych ustawień użytkownika" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sek." + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Portuguese (Brazil)/strings.po b/visualization.milkdrop/resources/language/Portuguese (Brazil)/strings.po new file mode 100644 index 0000000..ae2c798 --- /dev/null +++ b/visualization.milkdrop/resources/language/Portuguese (Brazil)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/xbmc-main/language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Tempo de mistura automático" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tempo entre as predefinições" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tempo aleatório adicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Ativar filtragem anisotrópica" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Habilitar cortes rígidos" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Limite de volume para cortes rígidos" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tempo médio entre cortes rígidos" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Taxa máxima de atualização" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Ativar Estéreo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Pacote de predefinições" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Pasta de predefinições do usuário" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modo Aleatório predefinido" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Predefinições WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Predefinições Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Pasta de predefinições definida pelo usuário" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f segundos" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Portuguese/strings.po b/visualization.milkdrop/resources/language/Portuguese/strings.po new file mode 100644 index 0000000..2e42f8f --- /dev/null +++ b/visualization.milkdrop/resources/language/Portuguese/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Portuguese (http://www.transifex.com/projects/p/xbmc-main/language/pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Mistura automática de tempo" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tempo entre Pré-Selecções" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tempo Aleatório Adicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activar Filtro Anisotrópico" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Ligar cortes" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Limiar de som para cortes" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tempo médio entre cortes" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Taxa máxima de actualização" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Activar Estéreo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Conjunto de Pré-Selecções" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Pasta de Pré-Selecções do Utilizador" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modo de Pré-Selecção aleatória" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Pré-Selecções WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Pré-Selecções do Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Pasta personalizada de Pré-Selecções do utilizador" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f segundos" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Romanian/strings.po b/visualization.milkdrop/resources/language/Romanian/strings.po new file mode 100644 index 0000000..f832712 --- /dev/null +++ b/visualization.milkdrop/resources/language/Romanian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Romanian (http://www.transifex.com/projects/p/xbmc-main/language/ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Durată de contopire automată" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Durată între vizualizări predefinite" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Timp aleatoriu adițional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activează filtrare anisotropică" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Activează schimbări rapide" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Prag de intensitate pentru schimbări rapide" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Durată medie între schimbări rapide" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Rată maximă de reîmprospătare" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Activează 3D stereo" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Pachet vizualizări predefinite" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Folder Preferinte Utilizator" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Mod Amestec Preferinte " + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Preferinte WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Preferinte Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Dosar presetări definite de utilizator" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sec" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Russian/strings.po b/visualization.milkdrop/resources/language/Russian/strings.po new file mode 100644 index 0000000..a236756 --- /dev/null +++ b/visualization.milkdrop/resources/language/Russian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Russian (http://www.transifex.com/projects/p/xbmc-main/language/ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Время автоматического перехода" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Время между настройками" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Дополнительное случайное время" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Включить анизотропную фильтрацию" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Включить жёсткие переходы" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Минимальная громкость для жёсткого перехода" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Среднее время между жёсткими переходами" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Максимальная частота обновления" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Включить стерео 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Набор настроек" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Папка настроек пользователя " + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Режим перемешивания настроек" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Настройки WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Настройки Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Папка для пользовательских настроек" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f с" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f кадр/с" diff --git a/visualization.milkdrop/resources/language/Serbian/strings.po b/visualization.milkdrop/resources/language/Serbian/strings.po new file mode 100644 index 0000000..d0653a1 --- /dev/null +++ b/visualization.milkdrop/resources/language/Serbian/strings.po @@ -0,0 +1,21 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Serbian (http://www.transifex.com/projects/p/xbmc-main/language/sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Dodatno Neodredjeno Vreme" diff --git a/visualization.milkdrop/resources/language/Slovak/strings.po b/visualization.milkdrop/resources/language/Slovak/strings.po new file mode 100644 index 0000000..0e02b5a --- /dev/null +++ b/visualization.milkdrop/resources/language/Slovak/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Slovak (http://www.transifex.com/projects/p/xbmc-main/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatický čas prelínania" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Čas medzi Predvoľbami" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Pridaný náhodná čas" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Povoliť anizotropné filtrovanie" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Povoliť tvrdé useknutia" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Úroveň hlasitosti pre tvrdé useknutia" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Priemerný čas medzi tvrdými useknutiami" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximálna obnovovacia frekvencia" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Povoliť Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Balík Predvilieb" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Užívateľský adresár Predvolieb" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Náhodný výber Predvolieb" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Predvoľby" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Predvoľby" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Užívateľom nastavený adresár Predvolieb" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f secs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Slovenian/strings.po b/visualization.milkdrop/resources/language/Slovenian/strings.po new file mode 100644 index 0000000..5fbe8d3 --- /dev/null +++ b/visualization.milkdrop/resources/language/Slovenian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Slovenian (http://www.transifex.com/projects/p/xbmc-main/language/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Samodejen čas prelivanja" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Čas med prednastavitvami" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Dodaten naključen čas" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Vključi anizotropno filtriranje" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Vključi ostre prehode" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Glasnost za ostre prehode" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Povprečen čas med ostrimi prehodi" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Največja stopnja osveževanja" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Vključi stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Paket prednastavitev" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Uporabniška mapa s prednastavitvami" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Način mešanja prednastavitev" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Prednastavitve WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Prednastavitve Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Uporabniško določena mapa s prednastavitvami" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sekund" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Spanish (Argentina)/strings.po b/visualization.milkdrop/resources/language/Spanish (Argentina)/strings.po new file mode 100644 index 0000000..87af21b --- /dev/null +++ b/visualization.milkdrop/resources/language/Spanish (Argentina)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/xbmc-main/language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Tiempo de mezcla automático" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tiempo entre presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tiempo aleatorio adicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activar el filtro Anisotrópico" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Habilitar cortes" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Umbral de volumen para cortes" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tiempo medio entre cortes" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Frecuencia de actualización máxima" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Habilitar Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Conjunto de presets" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Carpeta de presets del usuario" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modo aleatorio de presets" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Presets WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Presets Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Carpeta de presets definida por el usuario" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f seg" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Spanish (Mexico)/strings.po b/visualization.milkdrop/resources/language/Spanish (Mexico)/strings.po new file mode 100644 index 0000000..5da877f --- /dev/null +++ b/visualization.milkdrop/resources/language/Spanish (Mexico)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/xbmc-main/language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Tiempo de Mezcla Automático" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tiempo Entre Preajustes" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tiempo Aleatorio Adicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Habilitar Filtrado Anisotrópico" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Habilitar Cortes en Seco" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Umbral de Intensidad para Cortes en Seco" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tiempo Promedio Entre Cortes en Seco" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Máxima Frecuencia de Actualización" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Habilitar Estéreo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Paquete de Preajustes" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Carpeta de Usuario de Preajustes" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modo Aleatorio de Preajustes" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Preajustes WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Preajustes de Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Carpeta de Preajustes Definidos por Usuario" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f segs" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Spanish/strings.po b/visualization.milkdrop/resources/language/Spanish/strings.po new file mode 100644 index 0000000..f3b9b65 --- /dev/null +++ b/visualization.milkdrop/resources/language/Spanish/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Spanish (http://www.transifex.com/projects/p/xbmc-main/language/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Tiempo de mezcla automático" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tiempo entre presets" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Tiempo aleatorio adicional" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Activar el filtro Anisotrópico" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Habilitar cortes" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Umbral de volumen para cortes" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Tiempo medio entre cortes" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Frecuencia de actualización máxima" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Habilitar Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Conjunto de presets" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Carpeta de presets de usuario" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modo aleatorio de presets" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Presets WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Presets Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Carpeta de presets definida por el usuario" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f seg" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Swedish/strings.po b/visualization.milkdrop/resources/language/Swedish/strings.po new file mode 100644 index 0000000..06c3c5f --- /dev/null +++ b/visualization.milkdrop/resources/language/Swedish/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Swedish (http://www.transifex.com/projects/p/xbmc-main/language/sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Automatisk bländningstid" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Tid mellan förval" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Extra slumpmässig tid" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Aktivera anisotropicfilter" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Aktivera hårda brytningar" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Loudnessgräns för hårda beskärningar" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Medeltid mellan hårda brytningar" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maximal uppdateringsfrekvens" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Aktivera stereo-3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Förvalspaket" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Användarförvalsmapp" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Förvalsslumpningsläge" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51-förval" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp-förval" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Användardefineradförvalsmapp" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f sek" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Tajik/strings.po b/visualization.milkdrop/resources/language/Tajik/strings.po new file mode 100644 index 0000000..8e09715 --- /dev/null +++ b/visualization.milkdrop/resources/language/Tajik/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Tajik (http://www.transifex.com/projects/p/xbmc-main/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Вақти омезиши худкор" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Вақт байни интихобҳо" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Вақти тасодуфии иловагӣ" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Фаъол кардани филтри антизотропӣ" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Фаъол кардани буришҳои ноҳамвор" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Ҳудуди баландии садо барои буришҳои ноҳамвор" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Вақти миёна байни буришҳои ноҳамвор" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Суръати зиёдтарини навсозӣ" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Фаъол кардани стереои 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Бастаи интихобшуда" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Ҷузвдони интихобшудаи корбарӣ" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Ҳолати тасодуфии интихобшуда" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51-и танзимшуда" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp-и танзимшуда" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Ҷузвдони интихобшудаи корбари муайяншуда" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f сония" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f кадр/с" diff --git a/visualization.milkdrop/resources/language/Tamil (India)/strings.po b/visualization.milkdrop/resources/language/Tamil (India)/strings.po new file mode 100644 index 0000000..80ed809 --- /dev/null +++ b/visualization.milkdrop/resources/language/Tamil (India)/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Tamil (India) (http://www.transifex.com/projects/p/xbmc-main/language/ta_IN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta_IN\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "தானியங்கி கலப்பு நேரம்" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "அடுக்கு குணங்கலுக்கு இடையேயான நேரம்" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "கூடுதல் குறிப்பிலாத நேரம்" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "திசையற்ற வடித்தல் செயல்படுத்த" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "கடின குறைப்புக்கள் செயல்படுத்த" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "கடின குறைப்புக்கள் உரத்தல் எல்லையளவு" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "கடின குறைப்புக்கள் இடையே சராசரி நேரம்" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "அதிகபட்ச புதுப்பிக்கும் வீதம்" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "ஸ்டீரியோ 3D செயல்படுத்த" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "முன்னமைவு தொகுப்பு" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "பயனர் முன்னமைவு கோப்புறை" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "முன்னமைவு குலை முறை" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 முன்னமைவுகள்" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp முன்னமைவுகள்" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "பயனர் வரையறுக்கப்பட்ட முன்னமைவு கோப்புறை" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f நொடிகள்" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Thai/strings.po b/visualization.milkdrop/resources/language/Thai/strings.po new file mode 100644 index 0000000..1cccbea --- /dev/null +++ b/visualization.milkdrop/resources/language/Thai/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Thai (http://www.transifex.com/projects/p/xbmc-main/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "ระยะเวลาการผสานแบบอัตโนมัติ" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "ระยะเวลาระหว่างชุดรูปแบบ" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "เวลาสุ่มเพิ่มเติม" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "เปิดใช้ ตัวกรอง Anisotropic" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "เปิดใช้งาน การตัดแบบแข็ง" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "ช่วงระดับความดัง สำหรับการตัดแบบแข็ง" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "เวลาเฉลี่ยระหว่างการตัดแบบแข็ง" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "อัตราการรีเฟรชสูงสุด" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "เปิดใช้งาน 3D สเตอริโอ" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "แพ็ค ชุดรูปแบบ" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "โฟลเดอร์ ชุดรูปแบบของผู้ใช้" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "โหมด สุ่มลำดับชุดรูปแบบ" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "ชุดรูปแบบ WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "ชุดรูปแบบ Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "โฟลเดอร์ ชุดรูปแบบที่กำหนดโดยผู้ใช้" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f วินาที" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f เฟรมต่อวิ." diff --git a/visualization.milkdrop/resources/language/Turkish/strings.po b/visualization.milkdrop/resources/language/Turkish/strings.po new file mode 100644 index 0000000..525596a --- /dev/null +++ b/visualization.milkdrop/resources/language/Turkish/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Turkish (http://www.transifex.com/projects/p/xbmc-main/language/tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Otomatik Karıştırma Zamanı" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Önayarlar Arasındaki Zaman" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "İlave Rasgele Zaman" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Anizotropik Filtrelemeyi Etkin Kıl" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Sert Kesimler Etkin" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Sert Kesimler İçin Gürültülü Eşik" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Sert Kesimler İçin Ortalama Zaman" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Maksimum Tazeleme Oranı" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Stereo 3D yi Etkinleştir" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Önayar Paketi" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Kullanıcı Önayar Klasörü" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Karıştırma Modunu Önayarla" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 Önayarları" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Winamp Önayarları" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Kullanıcı Tanımlı Önayar Klasörü" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f saniye" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f fps" diff --git a/visualization.milkdrop/resources/language/Ukrainian/strings.po b/visualization.milkdrop/resources/language/Ukrainian/strings.po new file mode 100644 index 0000000..04462ea --- /dev/null +++ b/visualization.milkdrop/resources/language/Ukrainian/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Ukrainian (http://www.transifex.com/projects/p/xbmc-main/language/uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Тривалість автоматичного змішування" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Тривалість показу одного ефекту" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Додатковий час випадкової тривалості" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Увімкнути анізотропну фільтрацію" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Ввімкнути різку зміну" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Межа гучності для різкої зміни" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Середній час між різкими змінами" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Максимальна частота кадрів" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Увімкнути стерео 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Набір ефектів" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Тека з типовими налаштуваннями користувача" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Перемішати ефекти" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "WA51 ефекти" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Ефекти з Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Користувацька папка з ефектами" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f сек" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f кадр/с" diff --git a/visualization.milkdrop/resources/language/Vietnamese/strings.po b/visualization.milkdrop/resources/language/Vietnamese/strings.po new file mode 100644 index 0000000..ba096c3 --- /dev/null +++ b/visualization.milkdrop/resources/language/Vietnamese/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Vietnamese (http://www.transifex.com/projects/p/xbmc-main/language/vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Tự động điều chỉnh Blend Time" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Thời gian đổi Preset" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Thời gian random thêm vào" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Sử dụng Anisotropic Filtering" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Sử dụng các đoạn Hard Cut" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Giới hạn âm lượng cho các đoạn Hard Cut" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Thời gian trung bình giữa các đoạn Hard Cut" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Giá trị độ làm tươi Max" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Sử dụng Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Các gói Preset" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Thư mục Preset" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Chế độ tự nhảy Preset" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Preset từ WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Preset từ Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Đặt thư mục Preset" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f giây" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f hình/s" diff --git a/visualization.milkdrop/resources/language/Welsh/strings.po b/visualization.milkdrop/resources/language/Welsh/strings.po new file mode 100644 index 0000000..06f2431 --- /dev/null +++ b/visualization.milkdrop/resources/language/Welsh/strings.po @@ -0,0 +1,89 @@ +# Kodi Media Center language file +# Addon Name: MilkDrop +# Addon id: visualization.milkdrop +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Main\n" +"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Welsh (http://www.transifex.com/projects/p/xbmc-main/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n" + +msgctxt "#30000" +msgid "Automatic Blend Time" +msgstr "Amser Cymysgu Awtomatig" + +msgctxt "#30001" +msgid "Time Between Presets" +msgstr "Amse Rhwg Rhagosodiadau" + +msgctxt "#30002" +msgid "Additional Random Time" +msgstr "Amser Hap Ychwanegol" + +msgctxt "#30003" +msgid "Enable Anisotropic Filtering" +msgstr "Galluogi Hidlo Anisotropig" + +msgctxt "#30004" +msgid "Enable Hard Cuts" +msgstr "Galluogi Toriadau Caled" + +msgctxt "#30005" +msgid "Loudness Threshold For Hard Cuts" +msgstr "Trothwy Sain ar gyfer Toriadau Caled" + +msgctxt "#30006" +msgid "Average Time Between Hard Cuts" +msgstr "Amser Cyfartalog Rhwng Toriadau Caled" + +msgctxt "#30007" +msgid "Maximum Refresh Rate" +msgstr "Cyfradd Adnewyddu Uchaf" + +msgctxt "#30008" +msgid "Enable Stereo 3D" +msgstr "Galluogi Stereo 3D" + +msgctxt "#30009" +msgid "Preset Pack" +msgstr "Pac Rhagosodiad" + +msgctxt "#30010" +msgid "User Preset Folder " +msgstr "Defnyddio Ffolder Rhagosodiaid" + +msgctxt "#30011" +msgid "Preset Shuffle Mode" +msgstr "Modd Rjhagosodiaid Hap" + +msgctxt "#30020" +msgid "WA51 Presets" +msgstr "Rhagosodiaid WA51" + +msgctxt "#30021" +msgid "Winamp Presets" +msgstr "Rhagosodiaid Winamp" + +msgctxt "#30022" +msgid "User Defined Preset Folder" +msgstr "Ffolder Rhagosodiad Defnyddiwr Diffinedig" + +msgctxt "#30050" +msgid "%2.0f secs" +msgstr "%2.0f eil" + +msgctxt "#30051" +msgid "%2.0f %%" +msgstr "%2.0f %%" + +msgctxt "#30052" +msgid "%2.0f fps" +msgstr "%2.0f ye" diff --git a/visualization.milkdrop/resources/settings.xml b/visualization.milkdrop/resources/settings.xml new file mode 100644 index 0000000..0f5ed26 --- /dev/null +++ b/visualization.milkdrop/resources/settings.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + +