diff options
Diffstat (limited to 'Src/Plugins/Input/in_mod/mikamp')
19 files changed, 5190 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_mod/mikamp/in_mod.rc b/Src/Plugins/Input/in_mod/mikamp/in_mod.rc new file mode 100644 index 00000000..16d37864 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/in_mod.rc @@ -0,0 +1,391 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PREFS DIALOGEX 0, 0, 293, 205 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Tab1",MM_PREFTAB,"SysTabControl32",WS_TABSTOP,4,3,285,180 + DEFPUSHBUTTON "OK",IDOK,185,188,50,13 + PUSHBUTTON "Cancel",IDCANCEL,239,188,50,13 +END + +IDD_ID3EDIT DIALOGEX 0, 0, 273, 239 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Module Info" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_ID3_FN,4,4,265,12,ES_AUTOHSCROLL | ES_READONLY + RTEXT "Title",IDC_STATIC,4,22,14,8 + EDITTEXT IDC_TITLE,22,21,133,12,ES_AUTOHSCROLL | ES_READONLY + RTEXT "Type",IDC_STATIC,160,22,15,8 + EDITTEXT IDC_TYPE,180,21,89,12,ES_AUTOHSCROLL | ES_READONLY + GROUPBOX "Header Info",IDC_STATIC,4,38,130,57 + LTEXT "File Size:\nLength:\nChannels:\nSamples:\nInstruments:",IDC_STATIC,8,49,45,40 + LTEXT "",IDC_INFOLEFT,61,49,70,40 + GROUPBOX "Player Info",IDC_STATIC,139,38,130,57 + LTEXT "BPM:\nSong Spd:\nPosition:\nRow:\nVoices:",IDC_STATIC,142,49,45,40 + LTEXT "",IDC_INFORIGHT,195,49,70,40 + CONTROL "Tab1",IDC_TAB,"SysTabControl32",WS_TABSTOP,4,99,265,120 + CONTROL "Track song",IDC_TRACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,224,52,10 + DEFPUSHBUTTON "Close",IDOK,227,223,42,13 +END + +IDD_INSTRUMENTS DIALOGEX 0, 0, 262, 103 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LISTBOX IDC_INSTLIST,2,3,128,98,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Instrument Header",IDC_STATIC,134,0,125,101 + LTEXT "Def. Volume:\nAuto-Vibrato:\nFade out:",IDC_STATIC,138,9,44,24 + LTEXT "",IDC_INSTHEAD,190,9,64,24 + GROUPBOX "Envelopes",IDC_STATIC,134,34,125,67 + LTEXT "Volume:\nPanning:\nPitch:",IDC_STATIC,138,42,44,24 + LTEXT "",IDC_INSTENV,190,42,64,24 + GROUPBOX "Samples Used",IDC_STATIC,134,67,125,34 + EDITTEXT TB_SAMPLELIST,137,77,119,21,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL +END + +IDD_SAMPLES DIALOGEX 0, 0, 262, 103 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + LISTBOX IDC_SAMPLIST,2,3,128,98,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Sample Header",IDC_STATIC,134,0,125,68 + LTEXT "Length:\nFormat:\nQuality:\nLooping:\nAuto-Vibrato:\nVolume:\nPanning:",IDC_STATIC,139,8,45,56 + LTEXT "",IDC_SAMPINFO,190,8,66,56 +END + +IDD_COMMENT DIALOGEX 0, 0, 262, 103 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + EDITTEXT CEMENT_BOX,2,3,258,98,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL +END + +IDD_PREFTAB_DECODER DIALOGEX 0, 0, 282, 163 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "Song Looping",IDC_STATIC,4,1,273,64 + CONTROL "Slider1",IDC_LOOPS,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,7,15,127,12 + LTEXT "",IDC_LOOPTEXT,141,15,129,12 + CONTROL "Unconditional Looping\n(Forces all songs to loop even if they lack specific loop information)",IDC_LOOPALL, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,9,32,126,27 + CONTROL "Continue Play After Loop\n(useful for some games' modules, that contain several songs indeed)",IDC_CONT_LOOP, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,144,32,127,27 + CONTROL "Play Unlisted Patterns\n(Otherwise-unplayed pattern data is tacked onto the end of the song)",IDC_PLAYALL, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_DISABLED | WS_TABSTOP,9,69,130,27 + CONTROL "Use Resonant Lowpass Filters\n(Used by some Impulse Tracker songs; CPU intensive)",IDC_RESONANCE, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,144,69,131,27 + CONTROL "Strip Trailing Silence\n(May cause some songs to end or loop a few seconds prematurely)",IDC_STRIPSILENCE, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,8,100,130,26 + CONTROL "Seek by orders (as opposed to seek by seconds; song length will be displayed in orders, too)",IDC_SEEKBYORDERS, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,144,100,131,27 + LTEXT "Stereo Separation",IDC_STATIC,4,140,42,18 + LTEXT "0%",IDC_STATIC,48,132,17,9 + LTEXT "100%",IDC_STATIC,102,132,21,9 + LTEXT "400%",IDC_STATIC,159,132,22,9 + CONTROL "Slider1",IDC_PANSEP,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,48,145,123,9 + CONTROL "Fadeout for...",IDC_FADECHECK,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,205,132,69,10 + EDITTEXT IDC_FADEOUT,205,145,49,12,ES_RIGHT | ES_AUTOHSCROLL | WS_DISABLED + CONTROL "Spin1",IDC_FADESPIN,"msctls_updown32",UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,248,145,8,13 + LTEXT "sec.",IDC_FADESEC,260,148,14,10,WS_DISABLED +END + +IDD_PREFTAB_MIXER DIALOGEX 0, 0, 282, 163 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_TRANSPARENT | WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Output Mode",IDC_STATIC,4,1,134,47 + CONTROL "Reverse Stereo",OUTMODE_REVERSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,15,72,10 + LTEXT "Max voices:",IDC_STATIC,12,31,39,8 + COMBOBOX IDC_VOICES,60,29,42,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Streaming",IDC_STATIC,4,49,134,29 + CONTROL "Prompt to save to disk",IDC_SAVESTR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,61,85,11 + GROUPBOX "Output Quality",IDC_STATIC,143,1,134,149 + LTEXT "Mixing Rate:",IDC_STATIC,149,17,41,9 + COMBOBOX OQ_QUALITY,195,15,66,76,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Interpolation\n(Disable for lower-quality sound and 20% improvement in mixer efficiency)",OQ_INTERP, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,149,33,121,35 + CONTROL "FIR interpolation (high quality)",OQ_CUBIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,149,71,109,10 + CONTROL "Micro Volume-Ramping\n(Helps remove clicks and pops from interpolated sound)",OQ_NOCLICK, + "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,149,86,124,27 + LTEXT "Note: Try lower sample rates before disabling interpolation for slower machines. It sounds better that way.",IDC_STATIC,150,116,121,30 +END + +IDD_PREFTAB_LOADER DIALOGEX 0, 0, 282, 163 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_TRANSPARENT | WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "Available Loaders:",IDC_STATIC,4,2,80,9 + LISTBOX IDLDR_LIST,4,11,118,59,LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Default Panning",IDC_STATIC,4,72,118,88 + LTEXT "Mono",IDC_STATIC,8,81,19,8 + LTEXT "Full Stereo",IDC_STATIC,83,81,34,9 + CONTROL "Slider1",IDLDR_PANPOS,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,14,92,96,12 + CTEXT "Default panning is only set at load-time and can be overridden by the song during replay",IDC_STATIC,8,111,108,25 + PUSHBUTTON "Reset",IDC_DEFPAN,30,141,65,13 + LTEXT "",IDLDR_DESCRIPTION,133,4,143,34 + CONTROL "Enabled\n(When disabled, this filetype is ignored by Mikamp)",IDLDR_ENABLED, + "Button",BS_3STATE | BS_TOP | BS_MULTILINE | WS_TABSTOP,133,42,137,27 + GROUPBOX "Advanced Effects Options",IDC_STATIC,128,72,149,88 + CONTROL "Disable DMP Panning Effects (8xx)\n(Select this for songs that seem to incorrectly pan to the left speaker)",IDLDR_EFFOPT1, + "Button",BS_3STATE | BS_TOP | BS_MULTILINE | WS_TABSTOP,133,84,137,25 + CONTROL "Disable Resonance Filter Effects (Zxx)",IDLDR_EFFOPT2, + "Button",BS_3STATE | BS_TOP | WS_TABSTOP,133,113,138,10 + CTEXT "It is not recommended to change the advanced options unless you really\nknow what you are doing",IDC_ADV_TEXT_INFO,132,129,138,25,WS_DISABLED +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#include ""version.rc2""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_PREFS, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 289 + TOPMARGIN, 3 + BOTTOMMARGIN, 201 + END + + IDD_ID3EDIT, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 269 + TOPMARGIN, 2 + BOTTOMMARGIN, 236 + END + + IDD_INSTRUMENTS, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 259 + TOPMARGIN, 3 + BOTTOMMARGIN, 101 + END + + IDD_SAMPLES, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 259 + TOPMARGIN, 3 + BOTTOMMARGIN, 101 + END + + IDD_COMMENT, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 260 + TOPMARGIN, 3 + BOTTOMMARGIN, 100 + END + + IDD_PREFTAB_DECODER, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 278 + TOPMARGIN, 1 + BOTTOMMARGIN, 159 + END + + IDD_PREFTAB_MIXER, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 278 + BOTTOMMARGIN, 159 + END + + IDD_PREFTAB_LOADER, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 277 + TOPMARGIN, 2 + BOTTOMMARGIN, 160 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_NULLSOFT_MODULE_DECODER "Nullsoft Module Decoder v%s" + 65535 "{A1A39D49-671A-4c2f-AE42-BEA134EAF6A9}" +END + +STRINGTABLE +BEGIN + IDS_NULLSOFT_MODULE_DECODER_OLD "Nullsoft Module Decoder" + IDS_PROTRACKER_AND_CLONES + "Protracker and clones [mod]:\nIncludes Protracker, Fasttracker 1, Taketracker, Startrekker. Limited to 31 samples." + IDS_OLD_SKOOL_AMIGA_MODULES + "Old-skool Amiga Modules [mod]:\nSoundtracker, Ultimate Soundtracker. Very old and extremely limited in many ways (4 channels, 15 samples)" + IDS_SCREAM_TRACKER_2XX "Scream Tracker 2.xx [stm]:\nSimilar to ST3 modules, but limited to 4 channels; Various format quirks." + IDS_SCREAM_TRACKER_3XX "Scream Tracker 3.xx [s3m]:\nUp to 32 channels; Features a wavetable/FM combo (albeit rarely used)." + IDS_IMPULSE_TRACKER "Impulse Tracker (all versions) [it]:\nSupports 64 channels, new note actions, and resonance filters." + IDS_FASTTRACKER_2XX "Fasttracker 2.xx [xm]:\nSupports 32 channels, 128 instruments, and volume/panning envelopes." + IDS_MULTITRACKER "Multitracker [mtm]:\nA ""superfied"" Protracker-based format, features std effects /w 32 channels." + IDS_ULTRA_TRACKER "Ultra Tracker [ult]:\nDesigned specifically for the Gravis Ultrasound, features 32 channels and two effects per row." + IDS_COMPOSER_669 "Composer 669/UNIS 669 [669]:\nOne of the first PC trackers. 8 channels, up to 64 samples, few effects." + IDS_FARANDOLE_COMPOSER "Farandole Composer [far]:\nYet another composer. The 16 channel version of the Composer 669, but with more messy effects." + IDS_DIGITAL_SOUND_AND_MUSIC_INTERFACE + "Digital Sound and Music Interface [amf]:\nAdvanced Module Format... May be even too advanced to support it... Anyway, here it goes." + IDS_AMIGA_OKTALYZER "Amiga Oktalyzer [okt]:\n4-8 voices, 36 samples (usually), rather strange effects. The source code is about 20000 lines!" + IDS_POLYTRACKER "PolyTracker [ptm]:\nA Scream Tracker 3 clone (with ""protrac- kerized"" effects and some extra features), created by Lone Ranger / AcmE." + IDS_MULTIPLE_ITEMS_SELECTED "Multiple items selected..." + IDS_MUSIC_MODULES "Music Modules" +END + +STRINGTABLE +BEGIN + IDS_MIXER "Mixer" + IDS_PLAYER "Player" + IDS_LOADERS "Loaders" + IDS_DEFAULT " (default)" + IDS_SELECT_ANY_LOADER "Select any loader(s) to edit their properties..." + IDS_DO_NOT_LOOP "Do not loop" + IDS_LOOP_FOREVER "Loop forever" + IDS_LOOP_X_TIMES "Loop %d times" + IDS_PREFERENCES_TITLE "%s Preferences" + IDS_SAMPLES "Samples" + IDS_INSTRUMENTS "Instruments" + IDS_COMMENT "Comment" + IDS_YES "Yes" + IDS_NO "No" + IDS_SUSTAIN "Sustain" +END + +STRINGTABLE +BEGIN + IDS_FINETUNE "(finetune)" + IDS_HZ_SIGNED "Hz signed" + IDS_HZ_UNSIGNED "Hz unsigned" + IDS_PING_PONG "Ping-Pong" + IDS_REVERSE "Reverse" + IDS_FORWARD "Forward" + IDS_SUSTAIN_PING_PONG "Sustain Ping-Pong" + IDS_NONE "None" + IDS_X_X_X_OF_X_NOT_PLAYING "%d\n%d\n0 of %d\n\nNot Playing..." + IDS_X_X_X_OF_X_X_OF_X_X_OF_X "%d\n%d\n%d of %d (%d)\n%d of %d\n%d (%d)" + IDS_X_BTYES_X_OF_X_MINUTES "%d bytes\n%d:%02d minutes\n%d\n%d\n%d" + IDS_URLS_ONLY_SUPPORTED_IN_2_10_PLUS "URLs only supported in Winamp 2.10+" + IDS_MOD_PLUGIN_ERROR "Module Plug-in Error" + IDS_SAVE_MODULE "Save Module" + IDS_ALL_FILES "All files" + IDS_RETRIEVING_MODULE "Retrieving Module" +END + +STRINGTABLE +BEGIN + IDS_ERROR_KILLING_DECODING_THREAD "Error killing decoding thread." + IDS_LOOP "Loop" + IDS_ON "On" + IDS_OFF "Off" + IDS_BYTES "bytes" + IDS_BITS "bits" + IDS_FAMILY_STRING_COMPOSER_669 "Composer 669" + IDS_FAMILY_STRING_DSMI_AMF "DSMI AMF" + IDS_FAMILY_STRING_FARANDOLE_COMPOSER "Farandole Composer" + IDS_FAMILY_STRING_IMPULSETRACKER "Impulsetracker" + IDS_FAMILY_STRING_SOUNDTRACKER "Soundtracker (15-inst)" + IDS_FAMILY_STRING_PROTRACKER "Protracker" + IDS_FAMILY_STRING_MULTITRACKER "Multitracker" + IDS_FAMILY_STRING_AMIGA_OKTALYZER "Amiga Oktalyzer" + IDS_FAMILY_STRING_POLYTRACKER "PolyTracker" + IDS_FAMILY_STRING_SCREAMTRACKER3 "Screamtracker 3" +END + +STRINGTABLE +BEGIN + IDS_FAMILY_STRING_SCREAMTRACKER2 "Screamtracker 2" + IDS_FAMILY_STRING_ULTRATRACKER "Ultratracker" + IDS_FAMILY_STRING_FASTRACKER2 "Fasttracker 2" + IDS_FAMILY_STRING_NOISETRACKER "NoiseTracker Module" + IDS_X_MODULE "%s Module" + IDS_X_COMPRESSED_MODULE "%s Compressed Module" + IDS_ABOUT_TEXT "%s\n© 1998-2014 Winamp SA\nWritten by: Justin Frankel & Jake Stine\nBuild date: %hs\n\nMikamp - Nullsoft Module Decoder plug-in\nbased on the Mikmod Sound System\n\nModule loading & rendering by: Jake Stine\nThanks to Jeffrey Lim for additional Impulse Tracker info.\nAdditional code by: Peter Pawlowski & X-Fixer" + IDS_CORRUPT_UNSUPPORTED_TYPE "Corrupt file or unsupported module type." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "version.rc2" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Src/Plugins/Input/in_mod/mikamp/include/Main.h b/Src/Plugins/Input/in_mod/mikamp/include/Main.h new file mode 100644 index 00000000..9f9b9171 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/include/Main.h @@ -0,0 +1,106 @@ +#ifndef __MIKAMP_MAIN_H__ +#define __MIKAMP_MAIN_H__ + +#include <windows.h> +#include <stdio.h> +#include "mikmod.h" +#include "mplayer.h" +#include "resource.h" +#include "in2.h" + +#define INFO_CPAGES 3 + +#define CPLAYFLG_LOOPALL (1ul<<0) // disables selective looping - loop everything! +#define CPLAYFLG_PLAYALL (1ul<<1) // plays hidden patterns (tack onto end of the song) +#define CPLAYFLG_FADEOUT (1ul<<2) // Fadeout the song before the end cometh? +#define CPLAYFLG_STRIPSILENCE (1ul<<3) // Strip silence at the end of the song? +#define CPLAYFLG_SEEKBYORDERS (1ul<<4) // Seek by orders instead of seconds +#define CPLAYFLG_CONT_LOOP (1ul<<5) // continue after loop + +typedef struct tag_dlghdr +{ + HWND hwndTab; // tab control + HWND hwndDisplay; // current child dialog box + int left,top; + HWND apRes[INFO_CPAGES]; + + UNIMOD *module; + MPLAYER *seeker; + int maxv; + + BOOL inUse, ownModule; + BOOL *suse; + +} DLGHDR; + + +typedef struct INFOBOX +{ + HWND hwnd; + DLGHDR dlg; + struct INFOBOX *next; +} INFOBOX; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern UBYTE config_nopan, config_savestr; +extern MD_DEVICE drv_amp; +extern MD_DEVICE drv_buffer; +extern In_Module mikmod; +extern UNIMOD *mf; +extern MPLAYER *mp; + +// Defined in INFO.C +// ----------------- +extern INFOBOX *infobox_list; +extern void infoDlg(HWND hwnd, UNIMOD *m, BOOL activate, BOOL primiary); +extern int config_info_x, config_info_y, config_track; + + +// Defined in INFO.C +// ----------------- +// defined in config.c + +extern UBYTE config_interp; +extern UBYTE config_panrev; +extern UBYTE config_cpu; +extern uint config_srate, config_voices, config_playflag; +extern int config_pansep, config_loopcount; +extern UBYTE config_samplesize; + +extern UBYTE config_resonance; +extern int config_fadeout; +extern int config_tsel; + +extern int paused; + + +// config.c shizat +// --------------- +extern void set_priority(void); + +extern void __cdecl config(HWND hwndParent); +extern void __cdecl about(HWND hwndParent); + +extern void config_read(); +extern void config_write(); + +extern void info_killseeker(HWND hwnd); + +int GetNumChannels(); +int AllowSurround(); +int GetThreadPriorityConfig(); + +BOOL GetTypeInfo(LPCWSTR pszType, LPWSTR pszDest, INT cchDest); + +#ifdef __cplusplus +}; +#endif + +//#define PLUGIN_NAME "Nullsoft Module Decoder" +#define PLUGIN_VER L"2.94" + +#endif diff --git a/Src/Plugins/Input/in_mod/mikamp/include/in2.h b/Src/Plugins/Input/in_mod/mikamp/include/in2.h new file mode 100644 index 00000000..2c045b84 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/include/in2.h @@ -0,0 +1 @@ +#include "../../../Winamp/in2.h"
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/int64.lib b/Src/Plugins/Input/in_mod/mikamp/int64.lib Binary files differnew file mode 100644 index 00000000..92201d43 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/int64.lib diff --git a/Src/Plugins/Input/in_mod/mikamp/mikamp.dsp b/Src/Plugins/Input/in_mod/mikamp/mikamp.dsp new file mode 100644 index 00000000..5107ca40 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/mikamp.dsp @@ -0,0 +1,167 @@ +# Microsoft Developer Studio Project File - Name="mikamp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mikamp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mikamp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mikamp.mak" CFG="mikamp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mikamp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mikamp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mikamp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /Z7 /Ox /Ow /Og /Oi /Os /Gf /Gy /I "." /I "include" /I "..\lib\mikmod\include" /I "..\lib\mmio\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /Gs0 /FD /c +# SUBTRACT CPP /Ot /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib int64.lib /nologo /dll /machine:I386 /out:"c:\program files\winamp\plugins\in_mod.dll" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none /nodefaultlib + +!ELSEIF "$(CFG)" == "mikamp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "include" /I "..\lib\mikmod\include" /I "..\lib\mmio\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /debug /machine:I386 /out:"c:\program files\winamp\plugins\in_mod.dll" /pdbtype:sept +# SUBTRACT LINK32 /nodefaultlib + +!ENDIF + +# Begin Target + +# Name "mikamp - Win32 Release" +# Name "mikamp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\config.c +# End Source File +# Begin Source File + +SOURCE=.\src\drv_amp.c +# End Source File +# Begin Source File + +SOURCE=.\src\info.c +# End Source File +# Begin Source File + +SOURCE=.\src\main.c +# End Source File +# Begin Source File + +SOURCE=.\src\rf_wrapper.c +# End Source File +# Begin Source File + +SOURCE=.\src\tagz.cpp + +!IF "$(CFG)" == "mikamp - Win32 Release" + +# ADD CPP /GX- + +!ELSEIF "$(CFG)" == "mikamp - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\src\tagz.h +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\include\in2.h +# End Source File +# Begin Source File + +SOURCE=.\include\main.h +# End Source File +# Begin Source File + +SOURCE=.\include\out.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\Winamp\wa_ipc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\script1.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/Src/Plugins/Input/in_mod/mikamp/mikamp.sln b/Src/Plugins/Input/in_mod/mikamp/mikamp.sln new file mode 100644 index 00000000..b782d75b --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/mikamp.sln @@ -0,0 +1,31 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_mod (mikamp)", "mikamp.vcproj", "{3580EE92-4F7B-4322-A04C-B2B7B5578879}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_mod (mikmod)", "..\lib\mikmod\mikmod.vcproj", "{47FCA4AF-1F6B-4A1A-8AF2-1BD9E11672DD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_mod (mmio)", "..\lib\mmio\mmio.vcproj", "{BE408A85-4302-4EB8-8DE3-E3F9A5B25715}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3580EE92-4F7B-4322-A04C-B2B7B5578879}.Debug|Win32.ActiveCfg = Debug|Win32 + {3580EE92-4F7B-4322-A04C-B2B7B5578879}.Debug|Win32.Build.0 = Debug|Win32 + {3580EE92-4F7B-4322-A04C-B2B7B5578879}.Release|Win32.ActiveCfg = Release|Win32 + {3580EE92-4F7B-4322-A04C-B2B7B5578879}.Release|Win32.Build.0 = Release|Win32 + {47FCA4AF-1F6B-4A1A-8AF2-1BD9E11672DD}.Debug|Win32.ActiveCfg = Debug|Win32 + {47FCA4AF-1F6B-4A1A-8AF2-1BD9E11672DD}.Debug|Win32.Build.0 = Debug|Win32 + {47FCA4AF-1F6B-4A1A-8AF2-1BD9E11672DD}.Release|Win32.ActiveCfg = Release|Win32 + {47FCA4AF-1F6B-4A1A-8AF2-1BD9E11672DD}.Release|Win32.Build.0 = Release|Win32 + {BE408A85-4302-4EB8-8DE3-E3F9A5B25715}.Debug|Win32.ActiveCfg = Debug|Win32 + {BE408A85-4302-4EB8-8DE3-E3F9A5B25715}.Debug|Win32.Build.0 = Debug|Win32 + {BE408A85-4302-4EB8-8DE3-E3F9A5B25715}.Release|Win32.ActiveCfg = Release|Win32 + {BE408A85-4302-4EB8-8DE3-E3F9A5B25715}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Src/Plugins/Input/in_mod/mikamp/mikamp.vcproj b/Src/Plugins/Input/in_mod/mikamp/mikamp.vcproj new file mode 100644 index 00000000..3186535b --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/mikamp.vcproj @@ -0,0 +1,416 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="in_mod (mikamp)" + ProjectGUID="{3580EE92-4F7B-4322-A04C-B2B7B5578879}" + RootNamespace="in_mod (mikamp)" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName=".\Debug/mikamp.tlb" + HeaderFileName="" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="../../Wasabi;.;include;..\lib\mikmod\include;..\lib\mmio\include" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + UsePrecompiledHeader="0" + PrecompiledHeaderFile=".\Debug/mikamp.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + BrowseInformation="1" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="4" + CompileAs="0" + DisableSpecificWarnings="4996" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="comctl32.lib int64.lib shlwapi.lib ../../nsutil/nsutil.lib" + OutputFile="$(ProgramFiles)\winamp\plugins\in_mod.dll" + LinkIncremental="1" + SuppressStartupBanner="true" + GenerateDebugInformation="true" + ProgramDatabaseFile=".\Debug/in_mod.pdb" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + ImportLibrary=".\Debug/in_mod.lib" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="NDEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName=".\Release/mikamp.tlb" + HeaderFileName="" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="1" + InlineFunctionExpansion="1" + EnableIntrinsicFunctions="true" + FavorSizeOrSpeed="2" + AdditionalIncludeDirectories="../../Wasabi;.;include;..\lib\mikmod\include;..\lib\mmio\include" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS" + StringPooling="true" + ExceptionHandling="0" + RuntimeLibrary="2" + BufferSecurityCheck="false" + UsePrecompiledHeader="0" + PrecompiledHeaderFile=".\Release/mikamp.pch" + AssemblerListingLocation=".\Release/" + ObjectFile="$(IntDir)/" + ProgramDataBaseFileName=".\Release/" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="1033" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + IgnoreImportLibrary="true" + AdditionalDependencies="comctl32.lib int64.lib shlwapi.lib ../../nsutil/nsutil.lib" + OutputFile="$(ProgramFiles)\winamp\plugins\in_mod.dll" + LinkIncremental="1" + SuppressStartupBanner="true" + GenerateManifest="false" + IgnoreDefaultLibraryNames="msvcprt.lib" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb" + OptimizeReferences="2" + EnableCOMDATFolding="2" + RandomizedBaseAddress="1" + ImportLibrary=".\Release/in_mod.lib" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + <ProjectReference + ReferencedProjectIdentifier="{47FCA4AF-1F6B-4A1A-8AF2-1BD9E11672DD}" + RelativePathToProject="..\in_mod\lib\mikmod\mikmod.vcproj" + /> + <ProjectReference + ReferencedProjectIdentifier="{BE408A85-4302-4EB8-8DE3-E3F9A5B25715}" + RelativePathToProject="..\in_mod\lib\mmio\mmio.vcproj" + /> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" + > + <File + RelativePath="src\config.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;$(NoInherit)" + BasicRuntimeChecks="3" + BrowseInformation="1" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="src\drv_amp.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;$(NoInherit)" + BasicRuntimeChecks="3" + BrowseInformation="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\src\drv_buffer.cpp" + > + </File> + <File + RelativePath=".\src\drv_buffer.h" + > + </File> + <File + RelativePath=".\src\ExtendedRead.cpp" + > + </File> + <File + RelativePath="src\info.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;$(NoInherit)" + BasicRuntimeChecks="3" + BrowseInformation="1" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="src\main.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;$(NoInherit)" + BasicRuntimeChecks="3" + BrowseInformation="1" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\playbackconfig.cpp" + > + </File> + <File + RelativePath="src\rf_wrapper.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;$(NoInherit)" + BasicRuntimeChecks="3" + BrowseInformation="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="" + /> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl" + > + <File + RelativePath=".\src\api.h" + > + </File> + <File + RelativePath="include\in2.h" + > + </File> + <File + RelativePath="include\main.h" + > + </File> + <File + RelativePath="include\out.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" + > + <File + RelativePath=".\in_mod.rc" + > + </File> + <File + RelativePath="resource.h" + > + </File> + </Filter> + <File + RelativePath=".\int64.lib" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/Src/Plugins/Input/in_mod/mikamp/playbackconfig.cpp b/Src/Plugins/Input/in_mod/mikamp/playbackconfig.cpp new file mode 100644 index 00000000..24e7d16f --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/playbackconfig.cpp @@ -0,0 +1,78 @@ +#include "main.h" +#include "../winamp/wa_ipc.h" +#include <api/service/waServiceFactory.h> +#include "../../Agave/Config/api_config.h" + +// {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F} +static const GUID playbackConfigGroupGUID = +{ 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } }; + +static api_config *configApi=0; + +api_config *GetConfigAPI() +{ + if (mikmod.service && !configApi) + { + waServiceFactory *sf = (waServiceFactory *)mikmod.service->service_getServiceByGuid(AgaveConfigGUID); + configApi = (api_config *)sf->getInterface(); + } + + return configApi; +} +extern "C" +int GetSampleSizeFlag() +{ + api_config *config = GetConfigAPI(); + int bits=16; + if (config) + bits = config->GetUnsigned(playbackConfigGroupGUID, L"bits", 16); + + switch(bits) + { + case 8: + return 0; + case 24: + return DMODE_24BITS; + case 16: + default: + return DMODE_16BITS; + } + +} + +extern "C" +int GetNumChannels() +{ + api_config *config = GetConfigAPI(); + bool mono=false; + if (config) + mono = config->GetBool(playbackConfigGroupGUID, L"mono", false); + + if (mono) + return 1; + else + return 2; + +} + +extern "C" +int AllowSurround() +{ + api_config *config = GetConfigAPI(); + bool surround=true; + if (config) + surround= config->GetBool(playbackConfigGroupGUID, L"surround", true); + + return surround?1:0; +} + +extern "C" +int GetThreadPriorityConfig() +{ + api_config *config = GetConfigAPI(); + int priority=THREAD_PRIORITY_HIGHEST; + if (config) + priority = config->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST); + + return priority; +}
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/resource.h b/Src/Plugins/Input/in_mod/mikamp/resource.h new file mode 100644 index 00000000..d5f5721a --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/resource.h @@ -0,0 +1,149 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by script1.rc +// +#define IDS_NULLSOFT_MODULE_DECODER_OLD 0 +#define IDS_PROTRACKER_AND_CLONES 1 +#define IDS_OLD_SKOOL_AMIGA_MODULES 2 +#define IDS_SCREAM_TRACKER_2XX 3 +#define IDS_SCREAM_TRACKER_3XX 4 +#define IDS_IMPULSE_TRACKER 5 +#define IDS_FASTTRACKER_2XX 6 +#define IDS_MULTITRACKER 7 +#define IDS_ULTRA_TRACKER 8 +#define IDS_COMPOSER_669 9 +#define IDS_FARANDOLE_COMPOSER 10 +#define IDS_DIGITAL_SOUND_AND_MUSIC_INTERFACE 11 +#define IDS_AMIGA_OKTALYZER 12 +#define IDS_POLYTRACKER 13 +#define IDS_MULTIPLE_ITEMS_SELECTED 14 +#define IDS_MUSIC_MODULES 15 +#define IDS_MIXER 16 +#define IDS_PLAYER 17 +#define IDS_LOADERS 18 +#define IDS_DEFAULT 19 +#define IDS_SELECT_ANY_LOADER 20 +#define IDS_DO_NOT_LOOP 21 +#define IDS_LOOP_FOREVER 22 +#define IDS_LOOP_X_TIMES 23 +#define IDS_PREFERENCES_TITLE 24 +#define IDS_SAMPLES 26 +#define IDS_INSTRUMENTS 27 +#define IDS_COMMENT 28 +#define IDS_YES 29 +#define IDS_NO 30 +#define IDS_SUSTAIN 31 +#define IDS_FINETUNE 32 +#define IDS_HZ_SIGNED 33 +#define IDS_HZ_UNSIGNED 34 +#define IDS_PING_PONG 35 +#define IDS_REVERSE 36 +#define IDS_FORWARD 37 +#define IDS_SUSTAIN_PING_PONG 38 +#define IDS_NONE 39 +#define IDS_X_X_X_OF_X_NOT_PLAYING 40 +#define IDS_X_X_X_OF_X_X_OF_X_X_OF_X 41 +#define IDS_X_BTYES_X_OF_X_MINUTES 42 +#define IDS_URLS_ONLY_SUPPORTED_IN_2_10_PLUS 43 +#define IDS_MOD_PLUGIN_ERROR 44 +#define IDS_SAVE_MODULE 45 +#define IDS_ALL_FILES 46 +#define IDS_RETRIEVING_MODULE 47 +#define IDS_ERROR_KILLING_DECODING_THREAD 48 +#define IDS_LOOP 49 +#define IDS_ON 50 +#define IDS_OFF 51 +#define IDS_BYTES 52 +#define IDS_BYTES2 53 +#define IDS_BITS 53 +#define IDS_FAMILY_STRING_COMPOSER_669 54 +#define IDS_FAMILY_STRING_DSMI_AMF 55 +#define IDS_FAMILY_STRING_FARANDOLE_COMPOSER 56 +#define IDS_FAMILY_STRING_IMPULSETRACKER 57 +#define IDS_FAMILY_STRING_SOUNDTRACKER 58 +#define IDS_FAMILY_STRING_PROTRACKER 59 +#define IDS_FAMILY_STRING_MULTITRACKER 60 +#define IDS_FAMILY_STRING_AMIGA_OKTALYZER 61 +#define IDS_FAMILY_STRING_POLYTRACKER 62 +#define IDS_FAMILY_STRING_SCREAMTRACKER3 63 +#define IDS_FAMILY_STRING_SCREAMTRACKER2 64 +#define IDS_FAMILY_STRING_ULTRATRACKER 65 +#define IDS_FAMILY_STRING_FASTRACKER2 66 +#define IDS_FAMILY_STRING_NOISETRACKER 67 +#define IDS_X_MODULE 68 +#define IDS_X_COMPRESSED_MODULE 69 +#define IDS_ABOUT_TEXT 70 +#define IDS_CORRUPT_UNSUPPORTED_TYPE 71 +#define IDS_NULLSOFT_DS_OUTPUT 72 +#define IDD_ID3EDIT 101 +#define IDD_SAMPLES 108 +#define IDD_COMMENT 109 +#define IDD_INSTRUMENTS 111 +#define IDD_PREFS 116 +#define IDD_PREFTAB_DECODER 118 +#define IDD_PREFTAB_MIXER 119 +#define IDD_PREFTAB_LOADER 123 +#define IDC_PREFS_PRIORITY_DECODE 1076 +#define IDC_TYPE 1078 +#define IDC_TITLE 1079 +#define IDC_ID3_FN 1090 +#define OQ_INTERP 1100 +#define IDLDR_EFFOPT1 1102 +#define OQ_NOCLICK 1103 +#define IDC_SAVESTR 1105 +#define IDC_VOICES 1106 +#define IDC_INSTLIST 1108 +#define TB_SAMPLELIST 1109 +#define IDC_SAMPLIST 1110 +#define IDC_INFORIGHT 1111 +#define IDC_INFOLEFT 1112 +#define IDC_TAB 1113 +#define IDC_SAMPINFO 1115 +#define CEMENT_BOX 1116 +#define IDC_INSTENV 1118 +#define IDC_INSTHEAD 1120 +#define IDC_ID3FORMAT 1127 +#define MM_PREFTAB 1132 +#define IDC_PANSEP 1132 +#define IDC_DEFPAN 1137 +#define OQ_QUALITY 1139 +#define IDLDR_LIST 1140 +#define IDLDR_PANPOS 1141 +#define IDLDR_ENABLED 1142 +#define IDLDR_EFFOPT2 1144 +#define IDLDR_DESCRIPTION 1145 +#define IDC_LOOPALL 1146 +#define IDC_CONT_LOOP 1147 +#define IDC_FADEOUT 1148 +#define IDC_FADESPIN 1149 +#define IDC_PLAYALL 1150 +#define IDC_RESONANCE 1151 +#define IDC_FADECHECK 1152 +#define IDC_FADESEC 1153 +#define IDC_STRIPSILENCE 1154 +#define IDC_SEEKBYORDERS 1155 +#define IDC_TITLE_FORMAT 1156 +#define IDC_TAGZ_HELP 1157 +#define OQ_CUBIC 1158 +#define IDC_TAGZ_DEF 1158 +#define IDC_SAMPLESIZE 1159 +#define IDC_TITLE_FORMAT2 1159 +#define IDC_LOOPTEXT 1160 +#define IDC_LOOPS 1161 +#define IDC_TRACK 1162 +#define IDC_ADV_TEXT_INFO 1163 +#define OUTMODE_STEREO 1201 +#define OUTMODE_SURROUND 1202 +#define OUTMODE_REVERSE 1203 +#define IDS_NULLSOFT_MODULE_DECODER 65534 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1164 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Src/Plugins/Input/in_mod/mikamp/src/Config.c b/Src/Plugins/Input/in_mod/mikamp/src/Config.c new file mode 100644 index 00000000..75ba79e4 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/Config.c @@ -0,0 +1,1320 @@ +/* + Mikmod for Winamp + + By Jake Stine and Justin Frankel. Really. + + Done in 1998, 1999. The millenium cometh! + Done more in 2000. The millenium passeth by! + Redone lots in 2001. The REAL millenium cometh! haha. +*/ + +#include "api.h" +extern "C" { +#include "main.h" +} +#include <shlobj.h> +#include <commctrl.h> +#include "../../winamp/wa_ipc.h" +#include <strsafe.h> +#include "../nu/AutoWide.h" + +#define TabCtrl_InsertItemW(hwnd, iItem, pitem) \ + (int)SNDMSG((hwnd), TCM_INSERTITEMW, (WPARAM)(int)(iItem), (LPARAM)(const TC_ITEMW *)(pitem)) + +#define C_PAGES 4 + +#define CFG_UNCHANGED (-1) + +#define EFFECT_8XX (1ul<<0) +#define EFFECT_ZXX (1ul<<1) + +#define CPUTBL_COUNT 23 +#define MIXTBL_COUNT 7 +#define VOICETBL_COUNT 8 +#define DEF_SRATE 44100 + + +typedef struct tag_cdlghdr +{ + HWND hwndTab; // tab control + HWND hwndDisplay; // current child dialog box + int left,top; + HWND apRes[C_PAGES]; + +} CFG_DLGHDR; + + +// Winamp Stuff +UBYTE config_savestr = 0; // save stream to disk + +// Output Settings +UBYTE config_nch = 2; +UBYTE config_cpu; + +// Player Settings... +// ------------------ + +int config_loopcount = 0; // Auto-looping count, if the song has a natural loop. +uint config_playflag = 0; // See CPLAYFLG_* defines above for flags +int config_pansep = 128; // master panning separation (0 == mono, 128 == stereo, 512 = way-separate) +UBYTE config_resonance = 1; +int config_fadeout = 1000; // fadeout when the song is ending last loop (in ms) + +// Mixer Settings... +// ----------------- + +UBYTE config_panrev = 0, // Reverse panning (left<->right) + config_interp = 3; // interpolation (bit 0) / noclick (bit 1) / cubic (bit 2) +uint config_srate = DEF_SRATE; +uint config_voices = 96; // maximum voices player can use. + + +// Local Crud... +// ------------- + +static const char *INI_FILE; +static const char app_name[] = "Nullsoft Module Decoder"; + +static int l_quality, l_srate, // l_quality indexes mixertbl. l_srate is the actual number. + l_voices; +static BOOL l_useres, l_nch, + l_iflags; +int config_tsel = 0; + + +static uint voicetable[VOICETBL_COUNT] = { 24, 32, 48, 64, 96, 128, 256, 512 }; +static uint mixertbl[MIXTBL_COUNT] = +{ + 48000, + 44100, + 33075, + 22050, + 16000, + 11025, + 8000, +}; + + +// Define Extended Loader Details/Options +// -------------------------------------- + +typedef struct _MLCONF +{ + CHAR *cfgname; // configuration name prefix. + INT desc_id; // long-style multi-line description! + CHAR *exts; + MLOADER *loader; // mikmod loader to register + BOOL enabled; + uint defpan, // default panning separation \ range 0 - 128 + pan; // current panning separation / (mono to stereo) + uint optavail, // available advanced effects options + optset; // current settings for those options. +} MLCONF; + + +static MLCONF c_mod[] = +{ + "mod", + IDS_PROTRACKER_AND_CLONES, + "mod;mdz;nst", + &load_mod, + TRUE, + + 0,0, + EFFECT_8XX, 0, + + "m15", + IDS_OLD_SKOOL_AMIGA_MODULES, + "mod;mdz", + &load_m15, + TRUE, + + 0,0, + EFFECT_8XX, 0, + + "stm", + IDS_SCREAM_TRACKER_2XX, + "stm;stz", + &load_stm, + TRUE, + + 0,0, + EFFECT_8XX | EFFECT_ZXX, 0, + + "st3", + IDS_SCREAM_TRACKER_3XX, + "s3m;s3z", + &load_s3m, + TRUE, + + 32,32, + EFFECT_8XX | EFFECT_ZXX, 0, + + + "it", + IDS_IMPULSE_TRACKER, + "it;itz", + &load_it, + TRUE, + + 0,0, + EFFECT_ZXX, 0, + + "ft2", + IDS_FASTTRACKER_2XX, + "xm;xmz", + &load_xm, + TRUE, + + 0,0, + 0, 0, + + "mtm", + IDS_MULTITRACKER, + "mtm", + &load_mtm, + TRUE, + + 0,0, + EFFECT_8XX, 0, + + "ult", + IDS_ULTRA_TRACKER, + "ult", + &load_ult, + TRUE, + + 0,0, + EFFECT_8XX, 0, + + "669", + IDS_COMPOSER_669, + "669", + &load_669, + TRUE, + + 0,0, + 0, 0, + + "far", + IDS_FARANDOLE_COMPOSER, + "far", + &load_far, + TRUE, + + 0,0, + 0, 0, + + "amf", + IDS_DIGITAL_SOUND_AND_MUSIC_INTERFACE, + "amf", + &load_amf, + TRUE, + + 0,0, + 0, 0, + + "okt", + IDS_AMIGA_OKTALYZER, + "okt", + &load_okt, + TRUE, + + 0, 0, + 0, 0, + + "ptm", + IDS_POLYTRACKER, + "ptm", + &load_ptm, + TRUE, + + 0, 0, + EFFECT_8XX, 0, +}; + +#define C_NUMLOADERS (sizeof(c_mod)/sizeof(c_mod[0])) + +static MLCONF l_mod[C_NUMLOADERS]; // local copy, for cancelability + + +// ===================================================================================== + static int _r_i(char *name, int def) +// ===================================================================================== +{ + name += 7; + return GetPrivateProfileInt(app_name,name,def,INI_FILE); +} +#define RI(x) (( x ) = _r_i(#x,( x ))) + + +// ===================================================================================== + static void _w_i(char *name, int d) +// ===================================================================================== +{ + char str[120] = {0}; + StringCchPrintf(str,100,"%d",d); + name += 7; + WritePrivateProfileString(app_name,name,str,INI_FILE); +} +#define WI(x) _w_i(#x,( x )) + + +// ===================================================================================== + static void config_buildbindings(CHAR *datext) +// ===================================================================================== +// Creates the binding string. +{ +#define SEP_CHAR ';' + + uint i; + char *base = datext; + + base[0] = 0; + + for (i=0; i<C_NUMLOADERS; i++) + if (c_mod[i].enabled) + { + char *ext = c_mod[i].exts; + + for (;;) + { + char temp[64] = {0}; + int len; + // find next + char *next = strchr(ext, SEP_CHAR), *s; + + if (next) + len = next - ext; + else len = strlen(ext); + memcpy(temp, ext, len); + temp[len++] = SEP_CHAR; + temp[len] = 0; + // check for duplicate exts + s = strstr(base, temp); + if (!s || (s!=base && *(s-1)!=SEP_CHAR)) + { + memcpy(datext, temp, len); + datext += len; + *datext = 0; // prevent using old content + } + // advance + if (!next) + break; + ext = next + 1; + } + } + + if (datext > base) + { + *(datext-1) = 0; + StringCchCopy(datext,4096,WASABI_API_LNGSTRING(IDS_MUSIC_MODULES)); + } +} + + +// ===================================================================================== + static void config_init(void) +// ===================================================================================== +{ + INI_FILE = (const char *)SendMessage(mikmod.hMainWindow, WM_WA_IPC, 0, IPC_GETINIFILE); +} + + +// ===================================================================================== + void config_read(void) +// ===================================================================================== +{ + uint t; + + config_init(); + + + RI(config_savestr); + + RI(config_nch); + RI(config_srate); + RI(config_interp); + + RI(config_voices); + + RI(config_loopcount); + RI(config_playflag); + RI(config_resonance); + RI(config_fadeout); + + RI(config_pansep); + RI(config_panrev); + + RI(config_info_x); + RI(config_info_y); + RI(config_track); + RI(config_tsel); + + config_cpu = _mm_cpudetect(); + + // Load settings for each of the individual loaders + // ------------------------------------------------ + + for(t=0; t<C_NUMLOADERS; t++) + { + CHAR stmp[72] = {0}; + + StringCchPrintf(stmp,72,"%s%s",c_mod[t].cfgname,"enabled"); + c_mod[t].enabled = GetPrivateProfileInt(app_name,stmp,c_mod[t].enabled,INI_FILE); + + StringCchPrintf(stmp,72,"%s%s",c_mod[t].cfgname,"panning"); + c_mod[t].pan = GetPrivateProfileInt(app_name, stmp, c_mod[t].defpan, INI_FILE); + c_mod[t].pan = _mm_boundscheck(c_mod[t].pan, 0, 128); + + StringCchPrintf(stmp,72,"%s%s",c_mod[t].cfgname,"effects"); + c_mod[t].optset = GetPrivateProfileInt(app_name,stmp,c_mod[t].optset,INI_FILE); + + // configure the loaders + c_mod[t].loader->enabled = c_mod[t].enabled; + c_mod[t].loader->defpan = c_mod[t].pan; + c_mod[t].loader->nopaneff = (c_mod[t].optset | EFFECT_8XX) ? FALSE : TRUE; + c_mod[t].loader->noreseff = (c_mod[t].optset | EFFECT_ZXX) ? FALSE : TRUE; + } + + config_buildbindings(mikmod.FileExtensions); + + // Bounds checking! + // ---------------- + // This is important to ensure stability of the product in case some + // doof goes and starts hacking the ini values carelessly - or if some sort + // of version conflict or corruption causes skewed readings. + + config_pansep = _mm_boundscheck(config_pansep, 0, 512); + config_voices = _mm_boundscheck(config_voices, 2, 1024); + + config_fadeout = _mm_boundscheck(config_fadeout, 0, 1000l*1000l); + config_loopcount = _mm_boundscheck(config_loopcount, -1, 63); +} + + +// ===================================================================================== + void config_write(void) +// ===================================================================================== +{ + uint t = 0; + + WI(config_savestr); + + WI(config_nch); + WI(config_srate); + WI(config_interp); + WI(config_voices); + + WI(config_loopcount); + WI(config_playflag); + WI(config_resonance); + WI(config_fadeout); + + WI(config_pansep); + WI(config_panrev); + + WI(config_info_x); + WI(config_info_y); + WI(config_track); + WI(config_tsel); + + // Save settings for each of the individual loaders + // ------------------------------------------------ + + for(; t < C_NUMLOADERS; t++) + { + CHAR stmp[72] = {0}, sint[12] = {0}; + + StringCchPrintf(stmp,72,"%s%s",c_mod[t].cfgname,"enabled"); + StringCchPrintf(sint,12,"%d",c_mod[t].enabled); + WritePrivateProfileString(app_name,stmp,sint,INI_FILE); + + StringCchPrintf(stmp,72,"%s%s",c_mod[t].cfgname,"panning"); + StringCchPrintf(sint,12,"%d",c_mod[t].pan); + WritePrivateProfileString(app_name,stmp,sint,INI_FILE); + + StringCchPrintf(stmp,72,"%s%s",c_mod[t].cfgname,"effects"); + StringCchPrintf(sint,12,"%d",c_mod[t].optset); + WritePrivateProfileString(app_name,stmp,sint,INI_FILE); + + // configure the loaders + c_mod[t].loader->enabled = c_mod[t].enabled; + c_mod[t].loader->nopaneff = (c_mod[t].optset | EFFECT_8XX) ? FALSE : TRUE; + c_mod[t].loader->noreseff = (c_mod[t].optset | EFFECT_ZXX) ? FALSE : TRUE; + } + + config_buildbindings(mikmod.FileExtensions); +} + + +static BOOL CALLBACK prefsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); + + +// ===================================================================================== + void __cdecl config(HWND hwndParent) +// ===================================================================================== +{ + WASABI_API_DIALOGBOXW(IDD_PREFS,hwndParent,prefsProc); + config_write(); +} + + +static BOOL CALLBACK tabProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK mixerProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK loaderProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static void OnSelChanged(HWND hwndDlg, int initonly); + +// ===================================================================================== + static void prefsTabInit(HWND hwndDlg, CFG_DLGHDR *pHdr) +// ===================================================================================== +{ + DWORD dwDlgBase = GetDialogBaseUnits(); + int cxMargin = LOWORD(dwDlgBase) / 4, + cyMargin = HIWORD(dwDlgBase) / 8; + TC_ITEMW tie; + int tabCounter; + + tie.mask = TCIF_TEXT | TCIF_IMAGE; + tie.iImage = -1; + + tabCounter = 0; + + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->hwndTab,IPC_USE_UXTHEME_FUNC); + + tie.pszText = WASABI_API_LNGSTRINGW(IDS_MIXER); + TabCtrl_InsertItemW(pHdr->hwndTab, tabCounter, &tie); + pHdr->apRes[tabCounter] = WASABI_API_CREATEDIALOGPARAMW(IDD_PREFTAB_MIXER, hwndDlg, mixerProc, IDD_PREFTAB_MIXER); + SetWindowPos(pHdr->apRes[tabCounter], HWND_TOP, pHdr->left, pHdr->top, 0, 0, SWP_NOSIZE); + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->apRes[tabCounter],IPC_USE_UXTHEME_FUNC); + ShowWindow(pHdr->apRes[tabCounter++], SW_HIDE); + + tie.pszText = WASABI_API_LNGSTRINGW(IDS_PLAYER); + TabCtrl_InsertItemW(pHdr->hwndTab, tabCounter, &tie); + pHdr->apRes[tabCounter] = WASABI_API_CREATEDIALOGPARAMW(IDD_PREFTAB_DECODER, hwndDlg, tabProc, IDD_PREFTAB_DECODER); + SetWindowPos(pHdr->apRes[tabCounter], HWND_TOP, pHdr->left, pHdr->top, 0, 0, SWP_NOSIZE); + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->apRes[tabCounter],IPC_USE_UXTHEME_FUNC); + ShowWindow(pHdr->apRes[tabCounter++], SW_HIDE); + + tie.pszText = WASABI_API_LNGSTRINGW(IDS_LOADERS); + TabCtrl_InsertItemW(pHdr->hwndTab, tabCounter, &tie); + pHdr->apRes[tabCounter] = WASABI_API_CREATEDIALOGPARAMW(IDD_PREFTAB_LOADER, hwndDlg, loaderProc, IDD_PREFTAB_LOADER); + SetWindowPos(pHdr->apRes[tabCounter], HWND_TOP, pHdr->left, pHdr->top, 0, 0, SWP_NOSIZE); + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->apRes[tabCounter],IPC_USE_UXTHEME_FUNC); + ShowWindow(pHdr->apRes[tabCounter++], SW_HIDE); + + // Simulate selection of the first item. + OnSelChanged(hwndDlg,1); +} + + +// ===================================================================================== + static void OnSelChanged(HWND hwndDlg, int initonly) +// ===================================================================================== +{ + CFG_DLGHDR *pHdr = (CFG_DLGHDR *) GetWindowLong(hwndDlg, GWL_USERDATA); + if(!initonly) + config_tsel = TabCtrl_GetCurSel(pHdr->hwndTab); + else + TabCtrl_SetCurSel(pHdr->hwndTab,config_tsel); + + if(pHdr->hwndDisplay) ShowWindow(pHdr->hwndDisplay,SW_HIDE); + ShowWindow(pHdr->apRes[config_tsel],SW_SHOW); + pHdr->hwndDisplay = pHdr->apRes[config_tsel]; + +} + + +// ===================================================================================== + static void FadeOutSetup(HWND hwndDlg, BOOL enabled) +// ===================================================================================== +{ + EnableWindow(GetDlgItem(hwndDlg, IDC_FADEOUT), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_FADESEC), enabled); +} + + +// ===================================================================================== + static void Stereo_Dependencies(HWND hwndDlg) +// ===================================================================================== +// Enable or Disable the options which are dependant on stereo being enabled +{ + BOOL val = (l_nch==1) ? 0 : 1; + EnableWindow(GetDlgItem(hwndDlg,OUTMODE_REVERSE), val); + EnableWindow(GetDlgItem(hwndDlg,OUTMODE_SURROUND),val); +} + + +// ===================================================================================== + static void SetVoiceList(HWND hwndMisc) +// ===================================================================================== +// erg is the current quality mode (indexes mixertbl). +{ + uint i,k; + BOOL picked = FALSE; + uint cfgv; + + cfgv = (l_voices==CFG_UNCHANGED) ? config_voices : voicetable[l_voices]; + + SendMessage(hwndMisc,CB_RESETCONTENT,0,0); + + for(i=0; i<VOICETBL_COUNT; i++) + { CHAR buf[24] = {0}; + + // Find the appropriate megaherz, by doing a pretty wacky little logic snippet + // which matches up the multipled mhz with the closet legit CPU bracket (as + // listed in cputable). + + StringCchPrintf(buf,24,"%s%d",(voicetable[i]<100) ? " " : "", voicetable[i]); + + SendMessage(hwndMisc,CB_ADDSTRING,0,(LPARAM)buf); + if(!picked && (voicetable[i] >= cfgv)) + { k = i; picked = TRUE; } + } + + // If picked is false, then set to 96 (default) + + if(!picked) k = 4; + + SendMessage(hwndMisc,CB_SETCURSEL,k,0); +} + + +// ===================================================================================== + static BOOL cmod_and_the_moo(HWND dagnergit, int *moo, int count, uint flag) +// ===================================================================================== +{ + int l; + BOOL oneway, otherway, thisway, thatway; + + oneway = otherway = thisway = thatway = FALSE; + + // Set oneway/otherway true for selected/unselected options. + // Set thisway/thatway true for avail/nonawail options. + + for(l=0; l<count; l++) + { if(l_mod[moo[l]].optavail & flag) + { thisway = TRUE; + if(l_mod[moo[l]].optset & flag) oneway = TRUE; else otherway = TRUE; + } else thatway = TRUE; + } + + EnableWindow(dagnergit, thisway); + SendMessage(dagnergit, BM_SETCHECK, (!thisway || (oneway != otherway)) ? (oneway ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE, 0); + return thisway; +} + + +// ===================================================================================== + static BOOL CALLBACK mixerProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +// ===================================================================================== +{ + + switch (uMsg) + { + // ============================================================================= + case WM_INITDIALOG: + // ============================================================================= + // Windows dialog box startup message. This is messaged for each tab form created. + // Initialize all of the controls on each of those forms! + { + HWND hwndMisc; + CFG_DLGHDR *pHdr = (CFG_DLGHDR *)GetWindowLong(GetParent(hwndDlg), GWL_USERDATA); + + CheckDlgButton(hwndDlg, IDC_SAVESTR, config_savestr ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,OQ_INTERP, (config_interp & 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,OQ_NOCLICK, (config_interp & 2) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,OQ_CUBIC, (config_interp & 4) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,OUTMODE_REVERSE, config_panrev ? BST_CHECKED : BST_UNCHECKED); + + l_voices = CFG_UNCHANGED; + l_srate = config_srate; + l_iflags = config_interp; + l_nch = GetNumChannels(); + l_useres = config_resonance; + + hwndMisc = GetDlgItem(hwndDlg,OQ_QUALITY); + + { + uint erg, i, def=0; + BOOL picked = FALSE; + + for(i=0; i<MIXTBL_COUNT; i++) + { + wchar_t buf[24] = {0}; + StringCchPrintfW(buf,24,L"%d%s", mixertbl[i], mixertbl[i]==DEF_SRATE ? (def=i, WASABI_API_LNGSTRINGW(IDS_DEFAULT)) : L""); + SendMessageW(hwndMisc,CB_ADDSTRING,0,(LPARAM)buf); + if (!picked && mixertbl[i]<config_srate) + { + erg = i ? (i-1) : 0; + picked = TRUE; + } + } + // If picked is false, then set to default + if(!picked) erg = def; + SendMessage(hwndMisc,CB_SETCURSEL,erg,0); + l_quality = erg; + } + + SetVoiceList(GetDlgItem(hwndDlg,IDC_VOICES)); + Stereo_Dependencies(hwndDlg); + + return TRUE; + } + break; + + // ============================================================================= + case WM_COMMAND: + // ============================================================================= + // Process commands and notification messages recieved from our child controls. + + switch(LOWORD(wParam)) + { case IDOK: + { + + if(l_voices != CFG_UNCHANGED) config_voices = voicetable[l_voices]; + + config_srate = l_srate; + config_interp = l_iflags; + config_resonance = l_useres; + + config_panrev = IsDlgButtonChecked(hwndDlg,OUTMODE_REVERSE) ? 1 : 0; + + config_voices = _mm_boundscheck(config_voices, 2,1024); + + config_savestr = IsDlgButtonChecked(hwndDlg,IDC_SAVESTR) ? 1 : 0; + } + break; + + // Output Quality / Mixing Performance + // ----------------------------------- + // From here on down we handle the messages from those controls which affect + // the performance (and therefore the cpu requirements) of the module decoder. + // Each one assigns values into a temp variable (l_*) so that if the user + // cancels the changes are not saved. + + + case OQ_INTERP: + case OQ_CUBIC: + case OQ_NOCLICK: + if(HIWORD(wParam) == BN_CLICKED) + { l_iflags = IsDlgButtonChecked(hwndDlg,OQ_INTERP) ? 1 : 0; + l_iflags |= IsDlgButtonChecked(hwndDlg,OQ_NOCLICK) ? 2 : 0; + l_iflags |= IsDlgButtonChecked(hwndDlg,OQ_CUBIC) ? 4 : 0; + SetVoiceList(GetDlgItem(hwndDlg,IDC_VOICES)); + } + break; + + case IDC_VOICES: + if(HIWORD(wParam) == CBN_SELCHANGE) + { int taxi = SendMessage((HWND)lParam,CB_GETCURSEL,0,0); + l_voices = taxi; + } + break; + + case OQ_QUALITY: + if(HIWORD(wParam) == CBN_SELCHANGE) + { int taxi = SendMessage((HWND)lParam,CB_GETCURSEL,0,0); + l_quality = taxi; + l_srate = mixertbl[l_quality]; + SetVoiceList(GetDlgItem(hwndDlg,IDC_VOICES)); + } + break; + } + break; + } + return 0; +} + + +// ===================================================================================== + static BOOL CALLBACK loaderProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +// ===================================================================================== +// This is the callback procedure used by each of the three forms under the tab control +// on the Preferences dialog box. It handles all the messages for all of the controls +// within those dialog boxes. +{ + switch (uMsg) + { + // ============================================================================= + case WM_INITDIALOG: + // ============================================================================= + // Windows dialog box startup message. This is messaged for each tab form created. + // Initialize all of the controls on each of those forms! + { + HWND hwndMisc; + CFG_DLGHDR *pHdr = (CFG_DLGHDR *)GetWindowLong(GetParent(hwndDlg), GWL_USERDATA); + + uint i; + + // Set the range on the panning slider (0 to 16) + + hwndMisc = GetDlgItem(hwndDlg,IDLDR_PANPOS); + SendMessage(hwndMisc,TBM_SETRANGEMAX,0,16); + SendMessage(hwndMisc,TBM_SETRANGEMIN,0,0); + SendMessage(hwndMisc,TBM_SETPOS, 1, 16); + + // Build our list of loaders in the loader box + // ------------------------------------------- + // TODO: eventually I would like to display little checkmarks (or llamas or + // something) in this list to indicate (at a glance) which are enabled and + // which are not. + + hwndMisc = GetDlgItem(hwndDlg,IDLDR_LIST); + + for (i=0; i<C_NUMLOADERS; i++) + { + l_mod[i] = c_mod[i]; + SendMessageW(hwndMisc, LB_ADDSTRING, 0, (LPARAM)WASABI_API_LNGSTRINGW(c_mod[i].loader->DescStrID)); + } + + SendMessage(hwndMisc, LB_SETCURSEL, 0, 0); + loaderProc(hwndDlg, WM_COMMAND, (WPARAM)((LBN_SELCHANGE << 16) + IDLDR_LIST), (LPARAM)hwndMisc); + + if (NULL != WASABI_API_APP) + WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(hwndMisc, TRUE); + } + return TRUE; + + case WM_DESTROY: + { + HWND hwndMisc = GetDlgItem(hwndDlg, IDLDR_LIST); + if (NULL != WASABI_API_APP) + WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(hwndMisc, FALSE); + } + break; + + // ============================================================================= + case WM_COMMAND: + // ============================================================================= + // Process commands and notification messages recieved from our child controls. + + switch(LOWORD(wParam)) + { + case IDOK: + { uint i; + for (i=0; i<C_NUMLOADERS; i++) + { + c_mod[i] = l_mod[i]; + c_mod[i].loader->defpan = c_mod[i].pan; + } + } + break; + + case IDLDR_LIST: + + // The Loader Box Update Balloofie + // ------------------------------- + // Updates the various controls on the 'loader tab' dialog box. Involves + // enabling/disabling advanced-effects boxes, checking the Enabled box, and + // setting the panning position. Also: extra care is taken to allow proper + // and intuitive support for multiple selections! + + if(HIWORD(wParam) == LBN_SELCHANGE) + { int moo[C_NUMLOADERS], count,l; + BOOL oneway, otherway, opt1, opt2; + HWND beiownd; + + // Fetch the array of selected items! + + count = SendMessage((HWND)lParam, LB_GETSELITEMS, C_NUMLOADERS, (LPARAM)moo); + if(!count || (count == LB_ERR)) + { + // Something's not right, so just disable all the controls. + + SetWindowTextW(GetDlgItem(hwndDlg, IDLDR_DESCRIPTION), WASABI_API_LNGSTRINGW(IDS_SELECT_ANY_LOADER)); + EnableWindow(beiownd = GetDlgItem(hwndDlg, IDLDR_PANPOS), FALSE); + EnableWindow(beiownd = GetDlgItem(hwndDlg, IDLDR_ENABLED), FALSE); + SendMessage(hwndDlg, BM_GETCHECK, BST_UNCHECKED,0); + EnableWindow(beiownd = GetDlgItem(hwndDlg, IDLDR_EFFOPT1), FALSE); + SendMessage(hwndDlg, BM_GETCHECK, BST_UNCHECKED,0); + EnableWindow(beiownd = GetDlgItem(hwndDlg, IDLDR_EFFOPT2), FALSE); + SendMessage(hwndDlg, BM_GETCHECK, BST_UNCHECKED,0); + EnableWindow(beiownd = GetDlgItem(hwndDlg, IDC_DEFPAN), FALSE); + + break; + } + + SetWindowTextW(GetDlgItem(hwndDlg, IDLDR_DESCRIPTION), + WASABI_API_LNGSTRINGW( + (count==1) ? l_mod[moo[0]].desc_id : IDS_MULTIPLE_ITEMS_SELECTED)); + + // Enabled Box : First of Many + // --------------------------- + + oneway = otherway = FALSE; + for(l=0; l<count; l++) + if(l_mod[moo[l]].enabled) oneway = TRUE; else otherway = TRUE; + + EnableWindow(beiownd = GetDlgItem(hwndDlg, IDLDR_ENABLED), TRUE); + SendMessage(beiownd, BM_SETCHECK, (oneway != otherway) ? (oneway ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE, 0); + + + // The PanningPos : Second in Command + // ---------------------------------- + // Only set it if we have a single format selected, otherwise... erm.. + // do something (to be determined!) + + beiownd = GetDlgItem(hwndDlg, IDC_DEFPAN); + EnableWindow(beiownd, TRUE); + beiownd = GetDlgItem(hwndDlg, IDLDR_PANPOS); + EnableWindow(beiownd, TRUE); + if(count==1) + SendMessage(beiownd, TBM_SETPOS, TRUE, 16-((l_mod[moo[0]].pan+1)>>3)); + + + // 8xx Panning Disable: Third of Four + // Zxx Resonance: All the Duckies are in a Row! + // -------------------------------------------- + + opt1 = cmod_and_the_moo(GetDlgItem(hwndDlg, IDLDR_EFFOPT1), moo, count, EFFECT_8XX); + opt2 = cmod_and_the_moo(GetDlgItem(hwndDlg, IDLDR_EFFOPT2), moo, count, EFFECT_ZXX); + EnableWindow(GetDlgItem(hwndDlg, IDC_ADV_TEXT_INFO), opt1 || opt2); + } + break; + + case IDLDR_ENABLED: + case IDC_DEFPAN: + case IDLDR_EFFOPT1: + case IDLDR_EFFOPT2: + + if(HIWORD(wParam) == BN_CLICKED) + { int moo[C_NUMLOADERS],count; + int res = SendMessage((HWND)lParam,BM_GETCHECK,0,0); + + count = SendMessage(GetDlgItem(hwndDlg, IDLDR_LIST), LB_GETSELITEMS, C_NUMLOADERS, (LPARAM)moo); + + + switch(res) + { + case BST_CHECKED: + SendMessage((HWND)lParam,BM_SETCHECK,BST_UNCHECKED,0); + res = 0; + break; + + case BST_INDETERMINATE: + case BST_UNCHECKED: + SendMessage((HWND)lParam,BM_SETCHECK,BST_CHECKED,0); + res = 1; + break; + } + + if (LOWORD(wParam) == IDLDR_ENABLED) + { int l; + for(l=0; l<count; l++) l_mod[moo[l]].enabled = res; + } + else if (LOWORD(wParam) == IDC_DEFPAN) + { + int l; + + for (l=0; l<count; l++) + l_mod[moo[l]].pan = l_mod[moo[l]].defpan; + + if (count==1) + SendMessage(GetDlgItem(hwndDlg, IDLDR_PANPOS), TBM_SETPOS, TRUE, 16-((l_mod[moo[0]].pan+1)>>3)); + } + else + { + uint flag = (LOWORD(wParam) == IDLDR_EFFOPT1) ? EFFECT_8XX : EFFECT_ZXX; + int l; + + for(l=0; l<count; l++) + { if(l_mod[moo[l]].optavail & flag) + { if(res) + l_mod[moo[l]].optset |= flag; + else + l_mod[moo[l]].optset &= ~flag; + } + } + } + } + break; + } + break; + + // ============================================================================= + case WM_HSCROLL: + // ============================================================================= + // Whitness Stupidness! + // Microsoft decides it would be this "brilliant move' to make trackbars send + // WM_HSCROLL and WM_VSCROLL messages only! Like, who the hell uses a trackbar + // as a scroller anyway? Whatever happened to the 'standard' system of command/ + // notify messages? Grrr. + + // Oh look, the LOWORD is the command this time, as opposed to notifies, where the + // HIWORD is the command. Jesus fucking Christ I'm in loonyland around here. + + if(LOWORD(wParam) == TB_THUMBPOSITION) + { + int moo[C_NUMLOADERS],count,l; + count = SendMessage(GetDlgItem(hwndDlg, IDLDR_LIST), LB_GETSELITEMS, C_NUMLOADERS, (LPARAM)moo); + + for(l=0; l<count; l++) + { l_mod[moo[l]].pan = (16 - HIWORD(wParam)) << 3; + l_mod[moo[l]].pan = _mm_boundscheck(l_mod[moo[l]].pan,0,128); + } + } + } + + const int controls[] = + { + IDC_LOOPS, + IDC_PANSEP, + IDLDR_PANPOS, + }; + if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam, controls, ARRAYSIZE(controls))) + { + return TRUE; + } + + return 0; +} + + +// ===================================================================================== + static void FadeoutSetText(HWND hwndDlg) +// ===================================================================================== +{ + CHAR work[32] = {0}; + StringCchPrintf(work, 32, "%.02f",config_fadeout/1000.0f); + SetDlgItemText(hwndDlg, IDC_FADEOUT, work); +} + + +// ===================================================================================== + static BOOL CALLBACK tabProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +// ===================================================================================== +{ + switch (uMsg) + { + // ============================================================================= + case WM_INITDIALOG: + // ============================================================================= + // Windows dialog box startup message. This is messaged for each tab form created. + // Initialize all of the controls on each of those forms! + { + HWND hwndMisc; + CFG_DLGHDR *pHdr = (CFG_DLGHDR *)GetWindowLong(GetParent(hwndDlg), GWL_USERDATA); + SetWindowLong(hwndDlg,DWL_USER,lParam); + + switch(lParam) + { + case IDD_PREFTAB_DECODER: + SendMessage(GetDlgItem(hwndDlg,IDC_FADEOUT), EM_SETLIMITTEXT, 10,0); + FadeoutSetText(hwndDlg); + + hwndMisc = GetDlgItem(hwndDlg,IDC_PANSEP); + SendMessage(hwndMisc,TBM_SETRANGEMIN,0,0); + SendMessage(hwndMisc,TBM_SETRANGEMAX,0,32); + + { + int erg = config_pansep; + + if (erg <= 128) + erg *= 2; + else erg = 256 + ((erg - 128) * 256) / 384; + + SendMessage(hwndMisc,TBM_SETPOS,1, (erg>>4)&31); + } + + hwndMisc = GetDlgItem(hwndDlg, IDC_LOOPS); + SendMessage(hwndMisc, TBM_SETRANGEMIN, 0, 0); + SendMessage(hwndMisc, TBM_SETRANGEMAX, 0, 64); + SendMessage(hwndMisc, TBM_SETTICFREQ, 4, 0); + SendMessage(hwndMisc, TBM_SETPOS, 1, config_loopcount>=0 ? config_loopcount : 64); + SendMessage(hwndDlg, WM_HSCROLL, 0, (LPARAM)hwndMisc); + + CheckDlgButton(hwndDlg,IDC_LOOPALL, (config_playflag & CPLAYFLG_LOOPALL) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_CONT_LOOP, (config_playflag & CPLAYFLG_CONT_LOOP) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_PLAYALL, (config_playflag & CPLAYFLG_PLAYALL) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_FADECHECK, (config_playflag & CPLAYFLG_FADEOUT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_STRIPSILENCE,(config_playflag & CPLAYFLG_STRIPSILENCE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_SEEKBYORDERS,(config_playflag & CPLAYFLG_SEEKBYORDERS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg,IDC_RESONANCE,config_resonance ? BST_CHECKED : BST_UNCHECKED); + + FadeOutSetup(hwndDlg, config_playflag & CPLAYFLG_FADEOUT); + return TRUE; + + } + } + break; + + // ============================================================================= + case WM_COMMAND: + // ============================================================================= + // Process commands and notification messages recieved from our child controls. + + switch(LOWORD(wParam)) + { + case IDOK: + { + + switch(lParam) + { + case IDD_PREFTAB_DECODER: + { + CHAR stmp[32] = {0}; + double ftmp; + config_loopcount = SendMessage(GetDlgItem(hwndDlg, IDC_LOOPS), TBM_GETPOS, 0, 0); + if (config_loopcount == 64) config_loopcount = -1; + + GetDlgItemText(hwndDlg, IDC_FADEOUT, stmp, 12); + ftmp = atof(stmp); + config_fadeout = (int)(ftmp * 1000l); + config_fadeout = _mm_boundscheck(config_fadeout, 0, 1000l*1000l); // bound to 1000 seconds. + + { + int erg = SendMessage(GetDlgItem(hwndDlg,IDC_PANSEP),TBM_GETPOS,0,0)<<4; + + if (erg <= 256) + erg /= 2; + else erg = 128 + ((erg - 256) * 384) / 256; + + config_pansep = erg; + } + + config_playflag = IsDlgButtonChecked(hwndDlg,IDC_LOOPALL) ? CPLAYFLG_LOOPALL : 0; + config_playflag |= IsDlgButtonChecked(hwndDlg,IDC_CONT_LOOP) ? CPLAYFLG_CONT_LOOP : 0; + config_playflag |= IsDlgButtonChecked(hwndDlg,IDC_PLAYALL) ? CPLAYFLG_PLAYALL : 0; + config_playflag |= IsDlgButtonChecked(hwndDlg,IDC_FADECHECK) ? CPLAYFLG_FADEOUT : 0; + config_playflag |= IsDlgButtonChecked(hwndDlg,IDC_STRIPSILENCE) ? CPLAYFLG_STRIPSILENCE : 0; + config_playflag |= IsDlgButtonChecked(hwndDlg,IDC_SEEKBYORDERS) ? CPLAYFLG_SEEKBYORDERS : 0; + config_resonance = IsDlgButtonChecked(hwndDlg,IDC_RESONANCE) ? 1 : 0; + } + break; + } + } + break; + + case IDC_FADECHECK: // hide/unhide fadeout controls + if(HIWORD(wParam) == BN_CLICKED) + { int res = SendMessage((HWND)lParam,BM_GETCHECK,0,0); + FadeOutSetup(hwndDlg, res); + } + break; + } + break; + + // ============================================================================= + case WM_HSCROLL: + // ============================================================================= + switch (GetDlgCtrlID((HWND)lParam)) + { + case IDC_LOOPS: + { + wchar_t foo[64] = {0}; + int pos = SendMessage((HWND)lParam, TBM_GETPOS, 0, 0); + HWND hText = GetDlgItem(hwndDlg, IDC_LOOPTEXT); + + if (!pos) + WASABI_API_LNGSTRINGW_BUF(IDS_DO_NOT_LOOP,foo,64); + else if (pos == 64) + WASABI_API_LNGSTRINGW_BUF(IDS_LOOP_FOREVER,foo,64); + else + StringCchPrintfW(foo, 64, WASABI_API_LNGSTRINGW(IDS_LOOP_X_TIMES), pos + 1); + + SetWindowTextW(hText, foo); + } + break; + } + break; + + // ============================================================================= + case WM_NOTIFY: + // ============================================================================= + + switch(LOWORD(wParam)) + { + case IDC_FADESPIN: + { + NMUPDOWN *mud = (NMUPDOWN *) lParam; + + if(mud->hdr.code == UDN_DELTAPOS) + { + // bounds check things between 0-1000secs (added in 2.2.6) + if(mud->iDelta > 0) + { + if(config_fadeout > 0) + config_fadeout -= 250; + } + else + { + if(config_fadeout < 1000l*1000l) + config_fadeout += 250; + } + FadeoutSetText(hwndDlg); + } + } + return TRUE; + } + break; + } + + const int controls[] = + { + IDC_LOOPS, + IDC_PANSEP, + IDLDR_PANPOS, + }; + if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam, controls, ARRAYSIZE(controls))) + { + return TRUE; + } + + return 0; +} + + +// ===================================================================================== + static BOOL CALLBACK prefsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +// ===================================================================================== +// This is the procedure which initializes the various forms that make up the tabs in +// our preferences box! This also contains the message handler for the OK and Cancel +// buttons. After that, all messaging is handled by the tab forms themselves in tabProc(); +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + CFG_DLGHDR *pHdr = (CFG_DLGHDR*)calloc(1, sizeof(CFG_DLGHDR)); + SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) pHdr); + pHdr->hwndTab = GetDlgItem(hwndDlg,MM_PREFTAB); + pHdr->left = 8; + pHdr->top = 30; + + prefsTabInit(hwndDlg, pHdr); + + { + wchar_t title[128] = {0}, temp[128] = {0}; + StringCchPrintfW(title, 128, WASABI_API_LNGSTRINGW(IDS_PREFERENCES_TITLE),WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_MODULE_DECODER_OLD,temp,128)); + SetWindowTextW(hwndDlg,title); + } + } + return FALSE; + + + case WM_COMMAND: + switch (LOWORD(wParam)) + { case IDOK: + { + // Send an IDOK command to both tabcontrol children to let them know + // that the world is about to end! + CFG_DLGHDR *pHdr = (CFG_DLGHDR*)GetWindowLong(hwndDlg, GWL_USERDATA); + + SendMessage(pHdr->apRes[0], WM_COMMAND, (WPARAM)IDOK, (LPARAM)IDD_PREFTAB_MIXER); + SendMessage(pHdr->apRes[1], WM_COMMAND, (WPARAM)IDOK, (LPARAM)IDD_PREFTAB_DECODER); + SendMessage(pHdr->apRes[2], WM_COMMAND, (WPARAM)IDOK, (LPARAM)IDD_PREFTAB_LOADER); + + EndDialog(hwndDlg,0); + return 0; + } + + case IDCANCEL: + EndDialog(hwndDlg,0); + return FALSE; + + case OQ_QUALITY: + uMsg = 8; + break; + } + break; + + case WM_NOTIFY: + { NMHDR *notice = (NMHDR *) lParam; + + NMHDR *ack; + uint k; + ack = (NMHDR *)lParam; + + if(ack->hwndFrom == GetDlgItem(hwndDlg,OQ_QUALITY)) + { + switch(ack->code) + { + case CBEN_GETDISPINFO: + k = 1; + break; + } + } + + switch(notice->code) + { case TCN_SELCHANGE: + OnSelChanged(hwndDlg,0); + return TRUE; + } + } + return FALSE; + + case WM_DESTROY: + { + // free local data + free((CFG_DLGHDR*)GetWindowLong(hwndDlg, GWL_USERDATA)); + } + break; + } + return FALSE; +} + + +static int DoAboutMessageBox(HWND parent, wchar_t* title, wchar_t* message) +{ + MSGBOXPARAMSW msgbx = {sizeof(MSGBOXPARAMSW),0}; + msgbx.lpszText = message; + msgbx.lpszCaption = title; + msgbx.lpszIcon = MAKEINTRESOURCEW(102); + msgbx.hInstance = GetModuleHandle(0); + msgbx.dwStyle = MB_USERICON; + msgbx.hwndOwner = parent; + return MessageBoxIndirectW(&msgbx); +} + + +// ===================================================================================== + void __cdecl about(HWND hwndParent) +// ===================================================================================== +{ + wchar_t message[1024] = {0}, text[1024] = {0}; + WASABI_API_LNGSTRINGW_BUF(IDS_NULLSOFT_MODULE_DECODER_OLD,text,1024); + StringCchPrintfW(message, 1024, WASABI_API_LNGSTRINGW(IDS_ABOUT_TEXT), + mikmod.description, TEXT(__DATE__)); + DoAboutMessageBox(hwndParent,text,message); +} + + +static const wchar_t *pExtCompress[] = { L"ITZ", L"MDZ", L"S3Z", L"STZ", L"XMZ" }; +static const wchar_t *pExtReplace[] = { L"IT", L"MOD", L"S3M", L"STM", L"XM" }; + +BOOL GetTypeInfo(LPCWSTR pszType, LPWSTR pszDest, INT cchDest) // return TRUE if typ was found ok +{ + DWORD lcid; + LPCWSTR p(NULL); + wchar_t buf[128]={0}; + int i; + BOOL bCompressed(FALSE); + + lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + for (i = sizeof(pExtCompress)/sizeof(wchar_t*) - 1; i >= 0 && CSTR_EQUAL != CompareStringW(lcid, NORM_IGNORECASE, pszType, -1,pExtCompress[i], -1); i--); + if (-1 != i) + { + pszType = pExtReplace[i]; + bCompressed = TRUE; + } + + for (i = 0; i < C_NUMLOADERS && !p; i++) + { + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszType, -1, AutoWide(c_mod[i].loader->Type), -1)) + { + p = WASABI_API_LNGSTRINGW_BUF(c_mod[i].loader->DescStrID, buf, 128); + } + } + + if (!p) + { + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszType, -1, L"NST", -1)) + { + p = WASABI_API_LNGSTRINGW_BUF(IDS_FAMILY_STRING_NOISETRACKER, buf, 128); + } + } + + if (p) return (S_OK == StringCchPrintfW(pszDest, cchDest, WASABI_API_LNGSTRINGW((bCompressed?IDS_X_COMPRESSED_MODULE:IDS_X_MODULE)), p)); + return FALSE; +}
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/src/ExtendedRead.cpp b/Src/Plugins/Input/in_mod/mikamp/src/ExtendedRead.cpp new file mode 100644 index 00000000..71db9ea4 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/ExtendedRead.cpp @@ -0,0 +1,123 @@ +extern "C" +{ +#include "main.h" +} +#include "drv_buffer.h" +#include <bfc/platform/types.h> + +typedef struct +{ + const char *cmd; + const char *file; + const char *title; + int titleLength; + int start; + int startUnit; + int loops; + int flags; +} PlayParams; +extern "C" int GetSampleSizeFlag(); +extern "C" MMSTREAM *_mm_fopen_rf(const CHAR *fname); //rf_wrapper.c +BOOL GetPlayParams(const char *fileName, BOOL open, PlayParams *params); +BOOL InitPlayer(UNIMOD *mf, MPLAYER **ps, const PlayParams *params, BOOL quick); +// TODO; is there a way to get floating point out of this stuff? +extern "C" +{ + __declspec(dllexport) intptr_t winampGetExtendedRead_open(const char *fn, int *size, int *bps, int *nch, int *srate) + { + PlayParams params; + if (!GetPlayParams(fn, FALSE, ¶ms)) + return 0; + + int requested_channels = *nch; + int requested_bits = *bps; + int requested_srate = *srate; + + uint md_mode = 0; + if (config_interp & 1) md_mode |= DMODE_INTERP; + if (config_interp & 2) md_mode |= DMODE_NOCLICK; + if (config_interp & 4) md_mode |= DMODE_FIR; + switch(requested_bits) + { + case 0: + md_mode |= GetSampleSizeFlag(); + break; + case 16: + md_mode |= DMODE_16BITS; + break; + case 24: + md_mode |= DMODE_24BITS; + break; + } + + + if (requested_channels != 1 && requested_channels != 2) md_mode |= DMODE_SURROUND; + if (config_panrev) md_mode |= DMODE_REVERSE; + if (config_resonance) md_mode |= DMODE_RESONANCE; + + MDRIVER *md = Mikmod_Init(requested_srate?requested_srate:config_srate, 0, 0, MD_STEREO, config_cpu, md_mode, &drv_buffer); + MPLAYER *mp; + + MMSTREAM *fp; + fp = _mm_fopen_rf(params.file); + if (!fp) + { + Mikmod_Exit(md); + //CleanupTemp(); + return 0; + } + UNIMOD *mf=Unimod_Load_FP(md, params.file,fp); + _mm_fclose(fp); + if (mf==NULL) + { + Mikmod_Exit(md); + // CleanupTemp(); + return 0; + } + + if (!InitPlayer(mf, &mp, ¶ms, FALSE)) + { + //CleanupTemp(); + Unimod_Free(mf); + Mikmod_Exit(md); + return 0; + } + + Player_Start(mp); + DecodeInfo *hwdata = (DecodeInfo *)md->device.local; + *bps = hwdata->bits; + *srate = hwdata->mixspeed; + *nch = hwdata->channels; + if (mf->songlen) + *size = MulDiv(mf->songlen, hwdata->mixspeed * hwdata->channels *hwdata->bits, 8*1000); + else + *size = -1; + return (intptr_t)mp; + } + + __declspec(dllexport) size_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch) + { + MPLAYER *mp = (MPLAYER *)handle; + DecodeInfo *hwdata = (DecodeInfo *)mp->mf->md->device.local; + + if (!Player_Active(mp)) // check if we're done + return 0; + + hwdata->buffer = dest; + hwdata->buffersize = len; + hwdata->bytesWritten = 0; + Mikmod_Update(mp->mf->md); + return hwdata->bytesWritten; + } + + + __declspec(dllexport) void winampGetExtendedRead_close(intptr_t handle) + { + MPLAYER *mp = (MPLAYER *)handle; + MDRIVER *md = mp->mf->md; + UNIMOD *mf = (UNIMOD *)mp->mf; + Player_Free(mp); + Unimod_Free(mf); + Mikmod_Exit(md); + } +}
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/src/Info.c b/Src/Plugins/Input/in_mod/mikamp/src/Info.c new file mode 100644 index 00000000..75fdb40c --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/Info.c @@ -0,0 +1,602 @@ +#include "api.h" +#include "main.h" +#include "resource.h" +#include <commctrl.h> +#include "../../winamp/wa_ipc.h" +#include <strsafe.h> + +static BOOL CALLBACK infoProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static BOOL CALLBACK tabProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static void OnSelChanged(HWND hwndDlg); + +INFOBOX *infobox_list = NULL; + +int config_info_x = 0, config_info_y = 0; +BOOL config_track = FALSE; + +// ===================================================================================== +void infobox_delete(HWND hwnd) +// ===================================================================================== +// This function is called with the handle of the infobox to destroy. It unloads the +// module if appropriate (care must be take not to unload a module which is in use!). +{ + INFOBOX *cruise, *old; + + old = cruise = infobox_list; + + while(cruise) + { + if(cruise->hwnd == hwnd) + { + if(cruise == infobox_list) + infobox_list = cruise->next; + else old->next = cruise->next; + + // Destroy the info box window, then unload the module, *if* + // the module is not actively playing! + + info_killseeker(hwnd); + DestroyWindow(hwnd); + + if (cruise->dlg.module!=mf && cruise->dlg.ownModule) + Unimod_Free(cruise->dlg.module); + + free(cruise->dlg.suse); + free(cruise); + return; + } + old = cruise; + cruise = cruise->next; + } +} + + +// ===================================================================================== +MPLAYER *get_player(UNIMOD *othermf) +// ===================================================================================== +// Checks the current module against the one given. if they match the MP is returned, +// else it returns NULL. +{ + if (mf == othermf) + return mp; + return NULL; +} + + +// ===================================================================================== +static void infoTabInit(HWND hwndDlg, UNIMOD *m, DLGHDR *pHdr) +// ===================================================================================== +{ + DWORD dwDlgBase = GetDialogBaseUnits(); + int cxMargin = LOWORD(dwDlgBase) / 4, + cyMargin = HIWORD(dwDlgBase) / 8; + TC_ITEM tie; + int tabCounter; + + // Add a tab for each of the three child dialog boxes. + // and lock the resources for the child frames that appear within. + + tie.mask = TCIF_TEXT | TCIF_IMAGE; + tie.iImage = -1; + tabCounter = 0; + + if(m->numsmp) + { + tie.pszText = WASABI_API_LNGSTRING(IDS_SAMPLES); + TabCtrl_InsertItem(pHdr->hwndTab, tabCounter, &tie); + pHdr->apRes[tabCounter] = WASABI_API_CREATEDIALOGPARAM(IDD_SAMPLES, hwndDlg, tabProc, IDD_SAMPLES); + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->apRes[tabCounter],IPC_USE_UXTHEME_FUNC); + SetWindowPos(pHdr->apRes[tabCounter], HWND_TOP, pHdr->left+1, pHdr->top+15, 0, 0, SWP_NOSIZE); + ShowWindow(pHdr->apRes[tabCounter++], SW_HIDE); + } + + if(m->numins) + { + tie.pszText = WASABI_API_LNGSTRING(IDS_INSTRUMENTS); + TabCtrl_InsertItem(pHdr->hwndTab, tabCounter, &tie); + pHdr->apRes[tabCounter] = WASABI_API_CREATEDIALOGPARAM(IDD_INSTRUMENTS, hwndDlg, tabProc, IDD_INSTRUMENTS); + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->apRes[tabCounter],IPC_USE_UXTHEME_FUNC); + SetWindowPos(pHdr->apRes[tabCounter], HWND_TOP, pHdr->left+1, pHdr->top+15, 0, 0, SWP_NOSIZE); + ShowWindow(pHdr->apRes[tabCounter++], SW_HIDE); + } + + if(m->comment && m->comment[0]) + { + tie.pszText = WASABI_API_LNGSTRING(IDS_COMMENT); + TabCtrl_InsertItem(pHdr->hwndTab, tabCounter, &tie); + pHdr->apRes[tabCounter] = WASABI_API_CREATEDIALOGPARAM(IDD_COMMENT, hwndDlg, tabProc, CEMENT_BOX); + SendMessage(mikmod.hMainWindow,WM_WA_IPC,(WPARAM)pHdr->apRes[tabCounter],IPC_USE_UXTHEME_FUNC); + SetWindowPos(pHdr->apRes[tabCounter], HWND_TOP, pHdr->left+1, pHdr->top+15, 0, 0, SWP_NOSIZE); + ShowWindow(pHdr->apRes[tabCounter++], SW_HIDE); + } + + // Simulate selection of the LAST item + TabCtrl_SetCurSel(pHdr->hwndTab, tabCounter-1); + OnSelChanged(hwndDlg); +} + + +// ===================================================================================== +static BOOL CALLBACK tabProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +// ===================================================================================== +// This is the callback procedure used by each of the three forms under the +// tab control on the Module info dialog box (sample, instrument, comment +// info forms). +{ + switch (uMsg) + { case WM_INITDIALOG: + { + HWND hwndLB; + DLGHDR *pHdr = (DLGHDR *)GetWindowLong(GetParent(hwndDlg), GWL_USERDATA); + UNIMOD *m = pHdr->module; + char sbuf[10280] = {0}; + + switch(lParam) + { case IDD_SAMPLES: + { + uint x; + + hwndLB = GetDlgItem(hwndDlg, IDC_SAMPLIST); + for (x=0; x<m->numsmp; x++) + { + StringCbPrintfA(sbuf, sizeof(sbuf), "%02d: %s",x+1, m->samples[x].samplename ? m->samples[x].samplename : ""); + SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM) sbuf); + } + SendMessage(hwndLB, LB_SETCURSEL, 0, 0); + tabProc(hwndDlg, WM_COMMAND, (WPARAM)((LBN_SELCHANGE << 16) + IDC_SAMPLIST), (LPARAM)hwndLB); + } + return TRUE; + + case IDD_INSTRUMENTS: + { + uint x; + + hwndLB = GetDlgItem(hwndDlg, IDC_INSTLIST); + for (x=0; x<m->numins; x++) + { + StringCbPrintfA(sbuf, sizeof(sbuf), "%02d: %s",x+1, m->instruments[x].insname ? m->instruments[x].insname : ""); + SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM) sbuf); + } + SendMessage(hwndLB, LB_SETCURSEL, 0, 0); + tabProc(hwndDlg, WM_COMMAND, (WPARAM)((LBN_SELCHANGE << 16) + IDC_INSTLIST), (LPARAM)hwndLB); + } + return TRUE; + + case CEMENT_BOX: + if(m->comment && m->comment[0]) + { + uint x,i; + + hwndLB = GetDlgItem(hwndDlg, CEMENT_BOX); + // convert all CRs to CR/LF pairs. That's the way the edit box likes them! + + for(x=0, i=0; x<strlen(m->comment) && i < sizeof(sbuf)-1; x++) + { + sbuf[i++] = m->comment[x]; + if(m->comment[x]==0x0d && m->comment[x+1]!=0x0a) + sbuf[i++] = 0x0a; + } + sbuf[i] = 0; + + SetWindowText(hwndLB, sbuf); + } + return TRUE; + } + } + break; + + case WM_COMMAND: + if(HIWORD(wParam) == LBN_SELCHANGE) + { // Processes the events for the sample and instrument list boxes, namely updating + // the samp/inst info upon a WM_COMMAND issuing a listbox selection change. + + int moo = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0); + char sbuf[1024] = {0}, st1[128] = {0}, st2[64] = {0}, st3[64] = {0}; + char tmp1[32] = {0}, tmp2[32] = {0}, tmp3[32] = {0}; + DLGHDR *pHdr = (DLGHDR *)GetWindowLong(GetParent(hwndDlg), GWL_USERDATA); + UNIMOD *m = pHdr->module; + + switch (LOWORD(wParam)) + { case IDC_INSTLIST: + { INSTRUMENT *inst = &m->instruments[moo]; + uint x; + size_t cnt; + char *sbuf_p; + + // -------------------- + // Part 1: General instrument header info + // default volume, auto-vibrato, fadeout (in that order). + + { + StringCbPrintfA(sbuf, sizeof(sbuf), "%d%%\n%s\n%s", (inst->globvol * 400) / 256, + WASABI_API_LNGSTRING_BUF((inst->vibdepth ? IDS_YES : IDS_NO),tmp1,sizeof(tmp1)/sizeof(*tmp1)), + WASABI_API_LNGSTRING_BUF((inst->volfade ? IDS_YES : IDS_NO),tmp2,sizeof(tmp2)/sizeof(*tmp2))); + SetWindowText(GetDlgItem(hwndDlg, IDC_INSTHEAD), sbuf); + } + //(inst->nnatype == NNA_CONTINUE) ? "Continue" : (inst->nnatype == NNA_OFF) ? "Off" : (inst->nnatype == NNA_FADE) ? "Fade" : "Cut"); + + // -------------------- + // Part 2: The instrument envelope info (vol/pan/pitch) + + // Wow this is ugly, but it works: Make a set of strings that have the + // '(loop / sustain)' string. Tricky, cuz the '/' is only added if it + // is needed of course. + + if(inst->volflg & (EF_LOOP | EF_SUSTAIN)) + { + StringCbPrintfA(st1, sizeof(st1), "(%s%s%s)", + (inst->volflg & EF_LOOP) ? WASABI_API_LNGSTRING(IDS_LOOP) : "", + ((inst->volflg & EF_LOOP) && (inst->volflg & EF_SUSTAIN)) ? " / " : "", + (inst->volflg & EF_SUSTAIN) ? WASABI_API_LNGSTRING_BUF(IDS_SUSTAIN,tmp1,sizeof(tmp1)/sizeof(*tmp1)) : ""); + } else st1[0] = 0; + + if(inst->panflg & (EF_LOOP | EF_SUSTAIN)) + { + + StringCbPrintfA(st2, sizeof(st2), "(%s%s%s)", + (inst->panflg & EF_LOOP) ? WASABI_API_LNGSTRING(IDS_LOOP) : "", + ((inst->panflg & EF_LOOP) && (inst->panflg & EF_SUSTAIN)) ? " / " : "", + (inst->panflg & EF_SUSTAIN) ? WASABI_API_LNGSTRING_BUF(IDS_SUSTAIN,tmp1,sizeof(tmp1)/sizeof(*tmp1)) : ""); + } else st2[0] = 0; + + if(inst->pitflg & (EF_LOOP | EF_SUSTAIN)) + { + StringCchPrintfA(st3,sizeof(st3), "(%s%s%s)", + (inst->pitflg & EF_LOOP) ? WASABI_API_LNGSTRING(IDS_LOOP) : "", + ((inst->pitflg & EF_LOOP) && (inst->pitflg & EF_SUSTAIN)) ? " / " : "", + (inst->pitflg & EF_SUSTAIN) ? WASABI_API_LNGSTRING_BUF(IDS_SUSTAIN,tmp1,sizeof(tmp1)/sizeof(*tmp1)) : ""); + } else st3[0] = 0; + + { + StringCbPrintfA(sbuf, sizeof(sbuf), "%s %s\n%s %s\n%s %s", + WASABI_API_LNGSTRING_BUF(((inst->volflg & EF_ON) ? IDS_ON : IDS_OFF),tmp1,sizeof(tmp1)/sizeof(*tmp1)), + st1[0] ? st1 : "", + WASABI_API_LNGSTRING_BUF(((inst->panflg & EF_ON) ? IDS_ON : IDS_OFF),tmp2,sizeof(tmp2)/sizeof(*tmp2)), + st2[0] ? st2 : "", + WASABI_API_LNGSTRING_BUF(((inst->pitflg & EF_ON) ? IDS_ON : IDS_OFF),tmp3,sizeof(tmp3)/sizeof(*tmp3)), + st3[0] ? st3 : ""); + + } + SetWindowText(GetDlgItem(hwndDlg, IDC_INSTENV), sbuf); + + // -------------------- + // Part 3: List of samples used by this instrument! + // the trick here is that that we have to figure out what samples are used from the + // sample index table in inst->samplenumber. + + memset(pHdr->suse,0,m->numsmp*sizeof(BOOL)); + for(x=0; x<120; x++) + if(inst->samplenumber[x] != 65535) + pHdr->suse[inst->samplenumber[x]] = 1; + + sbuf[0] = 0; cnt = sizeof(sbuf)/sizeof(*sbuf); + sbuf_p = sbuf; + for (x=0; x<m->numsmp; x++) + { + if(pHdr->suse[x]) + { + StringCbPrintfExA(sbuf_p, cnt, &sbuf_p, &cnt, 0, "%02d: %s\r\n",x+1, m->samples[x].samplename); + } + } + if (cnt < sizeof(sbuf)/sizeof(*sbuf)) + { + sbuf[sizeof(sbuf)/sizeof(*sbuf) - cnt - 2] = 0; // cut off the final CR/LF set + } + SetWindowText(GetDlgItem(hwndDlg, TB_SAMPLELIST), sbuf); + + } + break; + + case IDC_SAMPLIST: + { UNISAMPLE *samp = &m->samples[moo]; + EXTSAMPLE *es = NULL; + + if(m->extsamples) es = &m->extsamples[moo]; + + // Display sampe header info... + // Length, Format, Quality, Looping, Auto-vibrato, Volume, Panning (in that order). + + { + char yn[64] = {0}, pp[64] = {0}; + StringCbPrintfA(sbuf, sizeof(sbuf), "%d %s\n%d %s\n%s %s\n%s\n%s\n%d\n%d", + samp->length * (samp->format&SF_16BITS ? 2 : 1), WASABI_API_LNGSTRING_BUF(IDS_BYTES, tmp1, sizeof(tmp1)/sizeof(*tmp1)), + samp->speed, WASABI_API_LNGSTRING_BUF((m->flags&UF_XMPERIODS ? IDS_FINETUNE : (samp->format&SF_SIGNED ? IDS_HZ_SIGNED : IDS_HZ_UNSIGNED)),tmp2,sizeof(tmp2)/sizeof(*tmp2)), + samp->format & SF_16BITS ? "16" : "8", WASABI_API_LNGSTRING_BUF(IDS_BITS, tmp3, sizeof(tmp3)/sizeof(*tmp3)), + WASABI_API_LNGSTRING_BUF((samp->flags&SL_LOOP ? ( samp->flags&SL_BIDI ? IDS_PING_PONG : (samp->flags&SL_REVERSE ? IDS_REVERSE : IDS_FORWARD )) : samp->flags&SL_SUSTAIN_LOOP ? ( samp->flags&SL_SUSTAIN_BIDI ? IDS_SUSTAIN_PING_PONG : IDS_SUSTAIN ) : IDS_NONE),pp,sizeof(pp)/sizeof(*pp)), + WASABI_API_LNGSTRING_BUF(((es && es->vibdepth) ? IDS_YES : IDS_NO),yn,sizeof(yn)/sizeof(*yn)), + samp->volume, samp->panning); + } + + SetWindowText(GetDlgItem(hwndDlg, IDC_SAMPINFO), sbuf); + } + break; + } + } + break; + } + return 0; +} + + +// ===================================================================================== +static void OnSelChanged(HWND hwndDlg) +// ===================================================================================== +{ + DLGHDR *pHdr = (DLGHDR *) GetWindowLong(hwndDlg, GWL_USERDATA); + int iSel = TabCtrl_GetCurSel(pHdr->hwndTab); + + if(pHdr->hwndDisplay) ShowWindow(pHdr->hwndDisplay,SW_HIDE); + ShowWindow(pHdr->apRes[iSel],SW_SHOW); + pHdr->hwndDisplay = pHdr->apRes[iSel]; + + // Note to self: Despite their inhernet use in interfaces, coding tab controls + // apparently REALLY sucks, and it should never ever be done again by myself + // or anyone else whom I respect as a sane individual and I would like to have + // remain that way. As for me, it is too late. Bruhahahaha!K!J!lkjgkljASBfkJBdglkn. + +} + +// ===================================================================================== +static void CALLBACK UpdateInfoRight(HWND hwnd, UINT uMsg, UINT ident, DWORD systime) +// ===================================================================================== +{ + char str[256] = {0}; + DLGHDR *pHdr = (DLGHDR *)GetWindowLong(hwnd, GWL_USERDATA); + MPLAYER *mp; + + // Player info update .. BPM, sngspeed, position, row, voices. + // Only update if our mf struct is the same as the one currently loaded into the player. + + if ((mp = get_player(pHdr->module)) == NULL) + { + // clean up + if (pHdr->inUse) + { + UNIMOD *m = pHdr->module; + pHdr->inUse = FALSE; + + StringCbPrintfA(str, sizeof(str), WASABI_API_LNGSTRING(IDS_X_X_X_OF_X_NOT_PLAYING), + m->inittempo, m->initspeed, m->numpos); + SetDlgItemText(hwnd, IDC_INFORIGHT, str); + + if (pHdr->seeker) + { + if (pHdr->seeker != mp) + Player_Free(pHdr->seeker); + pHdr->seeker = NULL; + } + } + + // "track song" mode + if (mf && IsDlgButtonChecked(hwnd, IDC_TRACK)==BST_CHECKED) + { + SendMessage(hwnd, WM_USER+10, 0, 0); + infoDlg(GetParent(hwnd), mf, GetActiveWindow()==hwnd, FALSE); + PostMessage(hwnd, WM_CLOSE, 0, 0); + } + } + else + { + MPLAYER *seeker; + long acv; + + if (!pHdr->inUse) + { + assert(pHdr->seeker == NULL); + pHdr->inUse = TRUE; + + // create our new player instance specifically for seeking + if (!(config_playflag & CPLAYFLG_SEEKBYORDERS)) + { + if ((pHdr->seeker = Player_Dup(mp)) == NULL) + return; + + // steal statelist from the original player + // (this will not require special handling, + // because of a smart allocation system) + + pHdr->seeker->statelist = mp->statelist; + pHdr->seeker->statecount = mp->statecount; + } + else pHdr->seeker = NULL; + } + + // Seek to our new song time, using a bastardized version of Player_SetPosTime code: + if (pHdr->seeker) + { + long curtime = mikmod.GetOutputTime() * 64; + seeker = pHdr->seeker; + + if (seeker->statelist) + { + int t = 0; + + while (t<seeker->statecount && + seeker->statelist[t].curtime && + curtime>=seeker->statelist[t].curtime) + t++; + + if (t) + Player_Restore(seeker, t - 1); + else Player_Cleaner(seeker); + } + else Player_Cleaner(seeker); + + while(!seeker->ended && seeker->state.curtime<curtime) + Player_PreProcessRow(seeker, NULL); + } + else seeker = mp; + + // Display all the goodie info we have collected: + // --------------------------------------------- + + acv = Mikmod_GetActiveVoices(mp->vs->md); + if (acv > pHdr->maxv) pHdr->maxv = acv; + + StringCbPrintfA(str, sizeof(str), WASABI_API_LNGSTRING(IDS_X_X_X_OF_X_X_OF_X_X_OF_X), + seeker->state.bpm, seeker->state.sngspd, seeker->state.sngpos, + seeker->mf->numpos, seeker->mf->positions[seeker->state.sngpos], + seeker->state.patpos, seeker->state.numrow, acv, pHdr->maxv); + SetWindowText(GetDlgItem(hwnd,IDC_INFORIGHT), str); + } +} + +// ===================================================================================== +void infoDlg(HWND hwnd, UNIMOD *m, BOOL activate, BOOL primiary) +// ===================================================================================== +{ + INFOBOX *box; + HWND dialog, hwndPrev; + char str[256] = {0}; + + if (!m) return; + + // + // create local dataplace + // + + box = (INFOBOX*)calloc(1, sizeof(INFOBOX)); + if (!box) return; + + box->dlg.left = 7; + box->dlg.top = 168; + box->dlg.module = m; + box->dlg.ownModule = primiary; + + box->next = infobox_list; + infobox_list = box; + + // + // create dialog + // + + hwndPrev = GetActiveWindow(); + box->hwnd = dialog = WASABI_API_CREATEDIALOG(IDD_ID3EDIT, hwnd, infoProc); + box->dlg.hwndTab = GetDlgItem(dialog, IDC_TAB); + + SetWindowLong(dialog, GWL_USERDATA, (LONG)&box->dlg); + SetDlgItemText(dialog, IDC_ID3_FN, m->filename); + + // IDC_INFOLEFT contains static module information: + // File Size, Length (in mins), channels, samples, instruments. + + StringCbPrintfA(str, sizeof(str), WASABI_API_LNGSTRING(IDS_X_BTYES_X_OF_X_MINUTES), + m->filesize, m->songlen/60000,(m->songlen%60000)/1000, m->numchn, m->numsmp, m->numins); + SetDlgItemText(dialog, IDC_INFOLEFT, str); + SetDlgItemText(dialog, IDC_TITLE, m->songname); + SetDlgItemText(dialog, IDC_TYPE, m->modtype); + + // IDC_INFORIGHT - contains player information + + StringCbPrintfA(str, sizeof(str), WASABI_API_LNGSTRING(IDS_X_X_X_OF_X_NOT_PLAYING), + m->inittempo, m->initspeed, m->numpos); + SetDlgItemText(dialog, IDC_INFORIGHT, str); + + // pHdr->suse is a samples-used block, allocated if this module uses + // instruments, and used to display the sampels that each inst uses + + if (m->numins) + box->dlg.suse = (BOOL*)calloc(m->numsmp, sizeof(BOOL)); + + CheckDlgButton(dialog, IDC_TRACK, config_track ? BST_CHECKED : BST_UNCHECKED); + infoTabInit(dialog, m, &box->dlg); + SetTimer(dialog, 1, 50, UpdateInfoRight); + + ShowWindow(dialog, SW_SHOW); + if (!activate) SetActiveWindow(hwndPrev); // do not steal focus +} + +// ===================================================================================== +void info_killseeker(HWND hwnd) +// ===================================================================================== +{ + DLGHDR *pHdr = (DLGHDR *)GetWindowLong(hwnd, GWL_USERDATA); + + if (pHdr->seeker) + { + assert(pHdr->inUse); + + if (pHdr->seeker != mp) + Player_Free(pHdr->seeker); + pHdr->seeker = NULL; + } + + pHdr->inUse = FALSE; +} + + +// ===================================================================================== +static BOOL CALLBACK infoProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +// ===================================================================================== +{ + UNIMOD *m = NULL; + + switch (uMsg) + { + case WM_INITDIALOG: + { + RECT rect, wrect; + + if (GetWindowRect(mikmod.hMainWindow, &wrect) && GetWindowRect(hwndDlg, &rect)) + { + wrect.left += config_info_x; + wrect.top += config_info_y; + + if (wrect.left>=0 && wrect.top>=0 && + wrect.left<GetSystemMetrics(SM_CXFULLSCREEN)-16 && + wrect.top<GetSystemMetrics(SM_CYFULLSCREEN)-16) + MoveWindow(hwndDlg, wrect.left, wrect.top, rect.right-rect.left, rect.bottom-rect.top, FALSE); + } + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + break; + case IDC_TRACK: + config_track = IsDlgButtonChecked(hwndDlg, IDC_TRACK) == BST_CHECKED; + break; + } + break; + + case WM_USER + 10: + case WM_CLOSE: + // save offset + { + RECT rect, wrect; + + if (GetWindowRect(mikmod.hMainWindow, &wrect) && GetWindowRect(hwndDlg, &rect)) + { + config_info_x = rect.left - wrect.left; + config_info_y = rect.top - wrect.top; + } + } + config_track = IsDlgButtonChecked(hwndDlg, IDC_TRACK) == BST_CHECKED; + + // clean up + if (uMsg != WM_CLOSE) + break; + + KillTimer(hwndDlg, 1); + infobox_delete(hwndDlg); + config_write(); + break; + + case WM_NOTIFY: + { + NMHDR *notice = (NMHDR*)lParam; + switch(notice->code) + { + case TCN_SELCHANGE: + OnSelChanged(hwndDlg); + break; + } + } + return TRUE; + } + return 0; +} diff --git a/Src/Plugins/Input/in_mod/mikamp/src/Main.c b/Src/Plugins/Input/in_mod/mikamp/src/Main.c new file mode 100644 index 00000000..b10f4bb0 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/Main.c @@ -0,0 +1,1067 @@ +#include "api.h" +extern "C" { +#include "main.h" +} +#include "log.h" +#include "../../winamp/wa_ipc.h" +#include "../nu/AutoWide.h" +#include "../nu/AutoCharFn.h" +#include <shlwapi.h> +#include <commdlg.h> + +extern "C" MMSTREAM *_mm_fopen_rf(const CHAR *fname); //rf_wrapper.c + +// +// data types and stuff +// + +#define SU_POSITION 1 +#define SU_TIME 2 + +#define PPF_CONT_LOOP 1 +#define PPF_LOOPALL 2 +#define PPF_ADD_TITLE 4 + +typedef struct +{ + const char *cmd; + const char *file; + const char *title; + int titleLength; + int start; + int startUnit; + int loops; + int flags; +} PlayParams; + + +// Public Globals! +// --------------- +extern "C" +{ + UNIMOD *mf; + MPLAYER *mp; + int paused; + int decode_pos; // in 1/64th of millisecond + extern char cfg_format[]; +} + + +void infobox_setmodule(HWND hwnd); + + +// Static Globals! +// --------------- + +#define SILENCE_THRESHOLD 10800 + +extern "C" int GetSampleSizeFlag(); +static char ERROR_TITLE[64]; + +static int is_tempfile = 0; +static char cmdName[2048], saveName[MAX_PATH]; +static char songTitle[400]; // as in Winamp +static PlayParams currParams; + +static HANDLE thread_handle = INVALID_HANDLE_VALUE; +static volatile int killDecodeThread; +static volatile int seek_needed; + +// wasabi based services for localisation support +api_application *WASABI_API_APP = 0; +api_language *WASABI_API_LNG = 0; +HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0; + +extern "C" DWORD WINAPI decodeThread(void *b); +void __cdecl setoutputtime(int time_in_ms); + +// ===================================================================================== +// error handling shiz +// ===================================================================================== + +static int lastError = 0; + +__inline void mm_clearerror() { lastError = 0; } + +static void mmerr(int crap, const CHAR *crud) +{ + char tmp[128] = {0}; + if (lastError==crap || crap==MMERR_OPENING_FILE) + return; + else + { + if(!lstrcmpi(crud,"Corrupt file or unsupported module type.")) + { + WASABI_API_LNGSTRING_BUF(IDS_CORRUPT_UNSUPPORTED_TYPE,tmp,128); + } + else + tmp[0] = 0; + } + + MessageBox(mikmod.hMainWindow, (tmp[0]?tmp:crud), ERROR_TITLE, MB_ICONERROR); + lastError = crap; +} + + +// ===================================================================================== +static int __cdecl init(void) +// ===================================================================================== +{ + if (!IsWindow(mikmod.hMainWindow)) + return IN_INIT_FAILURE; + + waServiceFactory *sf = mikmod.service->service_getServiceByGuid(languageApiGUID); + if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface()); + + sf = mikmod.service->service_getServiceByGuid(applicationApiServiceGuid); + if (sf) WASABI_API_APP = reinterpret_cast<api_application*>(sf->getInterface()); + + // need to have this initialised before we try to do anything with localisation features + WASABI_API_START_LANG(mikmod.hDllInstance,InModLangGUID); + + static wchar_t szDescription[256]; + swprintf(szDescription,256,WASABI_API_LNGSTRINGW(IDS_NULLSOFT_MODULE_DECODER),PLUGIN_VER); + mikmod.description = (char*)szDescription; + + WASABI_API_LNGSTRING_BUF(IDS_MOD_PLUGIN_ERROR,ERROR_TITLE,64); + + _mmerr_sethandler(&mmerr); + + config_read(); + + Mikmod_RegisterAllLoaders(); + Mikmod_RegisterDriver(drv_amp); + //Mikmod_RegisterDriver(drv_buffer); + return IN_INIT_SUCCESS; +} + +// ===================================================================================== +static void __cdecl quit() +// ===================================================================================== +{ +//LOG log_exit(); + SL_Cleanup(); +} + +static MDRIVER *md; + +// ===================================================================================== +// file open shiz +// ===================================================================================== + +#define IPC_GETHTTPGETTER 240 + +__inline char *GetFileName(const char *fullname) +{ + const char *c = fullname + strlen(fullname) - 1; + + while (c > fullname) + { + if (*c=='\\' || *c=='/') + { + c++; + break; + } + c--; + } + + return (char*)c; +} + +char* BuildFilterString(void) +{ + static char filterStr[128] = {0}; + if(!filterStr[0]) + { + char* temp = filterStr; + WASABI_API_LNGSTRING_BUF(IDS_ALL_FILES,filterStr,128); + temp += lstrlen(filterStr)+1; + lstrcpy(temp, "*.*"); + *(temp = temp + lstrlen(temp) + 1) = 0; + } + return filterStr; +} + +BOOL GetPlayParams(const char *fileName, BOOL open, PlayParams *params) +{ + mm_clearerror(); + + // fill params + params->cmd = fileName; + params->start = 0; + params->loops = config_loopcount; + params->titleLength = 0; + params->flags = 0; + + if (config_playflag & CPLAYFLG_CONT_LOOP) + params->flags |= PPF_CONT_LOOP; + + if (config_playflag & CPLAYFLG_LOOPALL) + params->flags |= PPF_LOOPALL; + + if (params->loops == -1) + params->flags &= ~PPF_CONT_LOOP; + + // check for mod:// prefix + if (!strncmp(fileName, "mod://", 6)) + { + const char *c = fileName += 6; + + while (c && *c && *c!=':') + { + // jump to + if (!strncmp(c, "jmp=", 4)) + { + // jump units + switch (*(c + 4)) + { + // position + case 'p': + params->startUnit = SU_POSITION; + params->flags &= ~PPF_CONT_LOOP; + break; + // time + case 't': + params->startUnit = SU_TIME; + break; + // invalid + default: + return FALSE; + } + params->start = atoi(c + 5); + } + // loops + else if (!strncmp(c, "lop=", 4)) + { + if (*(c+4) == 'u') + { + params->flags |= PPF_LOOPALL; + c++; + } + params->loops = atoi(c + 4); + params->loops = _mm_boundscheck(params->loops, -1, 64); + if (params->loops == -1) + params->flags &= ~PPF_CONT_LOOP; + } + // continue after loop + else if (!strncmp(c, "con=", 4)) + { + if (atoi(c + 4)) + params->flags |= PPF_CONT_LOOP; + else params->flags &= ~PPF_CONT_LOOP; + } + // title + else if (!strncmp(c, "tit=", 4)) + { + // find string + const char *p = c + 4; + + if (*p == '+') + { + params->flags |= PPF_ADD_TITLE; + c++; + p++; + } + + if (*p++ != '"') return FALSE; + + while (p && *p && *p!='"') + p++; + + if (*p != '"') return FALSE; + // set + params->title = c + 5; + params->titleLength = p - c - 5; + c = p - 3; + } + // invalid + else return FALSE; + + // skip + c += 4; + while (c && *c && *c!=',' && *c!=':') + c++; + if (*c == ',') c++; + } + + if (!*c) return FALSE; + fileName = c + 1; + } + + params->file = fileName; + + // check for URLs + if (open) + { + saveName[0] = 0; + is_tempfile = 0; + + if (!_strnicmp(fileName, "http://", 7) || !_strnicmp(fileName, "https://", 8) || + !_strnicmp(fileName, "ftp://", 6)) // FTP is now currently supported, but still... + { + typedef int (__cdecl *HttpRetrieveFile)(HWND hwnd, const char *url, const char *file, const char *dlgtitle); + + HttpRetrieveFile fileGetter; + int t = SendMessage(mikmod.hMainWindow,WM_USER,0,IPC_GETHTTPGETTER); + // try to get httpGetter + if (!t || t==1) + { + MessageBox(mikmod.hMainWindow, + WASABI_API_LNGSTRING(IDS_URLS_ONLY_SUPPORTED_IN_2_10_PLUS), + ERROR_TITLE, MB_ICONERROR); + return FALSE; + } + + fileGetter = (HttpRetrieveFile)t; + // save stream if required + if (config_savestr) + { + OPENFILENAME l = {0}; + lstrcpyn(saveName, GetFileName(fileName), MAX_PATH); + l.lStructSize = sizeof(l); + l.hwndOwner = mikmod.hMainWindow; + l.hInstance = NULL; + l.lpstrFilter = BuildFilterString(); + l.lpstrCustomFilter = NULL; + l.nMaxCustFilter = 0; + l.nFilterIndex = 0; + l.lpstrFile = saveName; + l.nMaxFile = sizeof(saveName); + l.lpstrFileTitle = 0;; + l.nMaxFileTitle = 0; + l.lpstrInitialDir = NULL; + l.lpstrTitle = WASABI_API_LNGSTRING(IDS_SAVE_MODULE); + l.lpstrDefExt = "mod"; + l.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_OVERWRITEPROMPT; + + if (!GetSaveFileName(&l)) + saveName[0] = 0; + } + // generate temp name, if not saving + if (!saveName[0]) + { + char p[MAX_PATH] = {0}; + + GetTempPath(sizeof(p), p); + GetTempFileName(p, "mod", 0, saveName); + is_tempfile = 1; + } + // get file + if (fileGetter(mikmod.hMainWindow, fileName, saveName, WASABI_API_LNGSTRING(IDS_RETRIEVING_MODULE))) + { + is_tempfile = 0; + saveName[0] = 0; + return FALSE; + } + params->file = saveName; + } + } + else + { + if (saveName[0] && !_stricmp(fileName, cmdName)) + params->file = saveName; + } + + return TRUE; +} + +static void CleanupTemp() +{ + if (is_tempfile && saveName[0]) + { + DeleteFile(saveName); + is_tempfile = 0; + } + + saveName[0] = 0; +} + +BOOL InitPlayer(UNIMOD *mf, MPLAYER **ps, const PlayParams *params, BOOL quick) +{ + int flags; + + // strip silence + if (config_playflag & CPLAYFLG_STRIPSILENCE) + Unimod_StripSilence(mf, SILENCE_THRESHOLD); + + // set flags + flags = PF_TIMESEEK; + if (params->flags & PPF_CONT_LOOP) flags |= PF_CONT_LOOP; + + // init player + if (quick) + *ps = Player_Create(mf, flags); + else *ps = Player_InitSong(mf, NULL, flags, config_voices); + + if (!*ps) return FALSE; + + // position seek + if (params->start && params->startUnit==SU_POSITION) + Player_SetStartPosition(*ps, params->start); + + // looping + Player_SetLoopStatus(*ps, params->flags & PPF_LOOPALL, params->loops); + + if (quick || config_playflag&CPLAYFLG_SEEKBYORDERS) + Player_PredictSongLength(*ps); + else + { + // time calculation & seeking-lookups creation + Player_BuildQuickLookups(*ps); + + // fade (needs results of Player_BuildQuickLookups) + if (config_playflag & CPLAYFLG_FADEOUT) + Player_VolumeFadeEx(*ps, MP_VOLUME_CUR, 0, config_fadeout, MP_SEEK_END, config_fadeout); + } + + // remember song length + mf->songlen = (*ps)->songlen; + + return TRUE; +} + +static UNIMOD *GetModuleInfo(const PlayParams *params) +{ + UNIMOD *m = mf; + + // check against the current one + if (!m || _stricmp(cmdName, params->cmd)) // check the whole string, not just file name + { + MPLAYER *ps; + MMSTREAM * fp; + + // load module + mm_clearerror(); + fp = _mm_fopen_rf(params->file); + if (!fp) return NULL; + m = Unimod_LoadInfo_FP(params->file,fp); + _mm_fclose(fp); + if (!m) return NULL; + + // get info and clean up + if (!InitPlayer(m, &ps, params, TRUE)) + { + Unimod_Free(m); + return NULL; + } + Player_Free(ps); + } + + return m; +} + +static int __cdecl isourfile(const char *fn) +{ + return !_strnicmp(fn, "mod://", 6); +} + +// ===================================================================================== +// helpers +// ===================================================================================== + +static UNIMOD *FindInfoBox(const char *fileName, HWND *hwnd) +{ + INFOBOX *cruise; + + for (cruise=infobox_list; cruise; cruise=cruise->next) + if (!_stricmp(cruise->dlg.module->filename, fileName)) + { + if (hwnd) *hwnd = cruise->hwnd; + return cruise->dlg.module; + } + + return NULL; +} + +static BOOL FindInfoBoxPtr(const UNIMOD *mf) +{ + INFOBOX *cruise; + + for (cruise=infobox_list; cruise; cruise=cruise->next) + if (cruise->dlg.module == mf) + return TRUE; + + return FALSE; +} + +// ===================================================================================== +static int __cdecl play(const char *fileName) +// ===================================================================================== +{ + PlayParams params; + uint md_mode = 0; + + // parse parameters + if (!GetPlayParams(fileName, TRUE, ¶ms)) + return 1; + + // save strings locally + lstrcpyn(cmdName, params.cmd, 2048); + if (params.titleLength) + lstrcpyn(songTitle, params.title, min(params.titleLength+1, sizeof(songTitle))); + else songTitle[0] = 0; + + // save current values + currParams = params; + currParams.cmd = params.cmd; + currParams.title = songTitle; + + // Initialize MDRVER + // ----------------- + + if (config_interp & 1) md_mode |= DMODE_INTERP; + if (config_interp & 2) md_mode |= DMODE_NOCLICK; + if (config_interp & 4) md_mode |= DMODE_FIR; + md_mode |= GetSampleSizeFlag(); + if (AllowSurround()) md_mode |= DMODE_SURROUND; + if (config_panrev) md_mode |= DMODE_REVERSE; + if (config_resonance) md_mode |= DMODE_RESONANCE; + + md = Mikmod_Init(config_srate, 1000, NULL, GetNumChannels()==1 ? MD_MONO : MD_STEREO, config_cpu, md_mode, &drv_amp); + if (!md) + { + CleanupTemp(); + return 1; + } + + md->pansep = config_pansep; + + // Register non-interpolation mixers + // --------------------------------- + // if the user has disabled interpolation... + + if(!(config_interp & 1)) + { + VC_RegisterMixer(md->device.vc, &RF_M8_MONO); + VC_RegisterMixer(md->device.vc, &RF_M16_MONO); + VC_RegisterMixer(md->device.vc, &RF_M8_STEREO); + VC_RegisterMixer(md->device.vc, &RF_M16_STEREO); + + VC_RegisterMixer(md->device.vc, &M8_MONO); + VC_RegisterMixer(md->device.vc, &M16_MONO); + VC_RegisterMixer(md->device.vc, &M8_STEREO); + VC_RegisterMixer(md->device.vc, &M16_STEREO); + } + else if (config_interp&4) + { +/* + VC_RegisterMixerHack(md->device.vc, &M16_MONO_CUBIC); + VC_RegisterMixerHack(md->device.vc, &M16_STEREO_CUBIC); + VC_RegisterMixerHack(md->device.vc, &M8_MONO_CUBIC); + VC_RegisterMixerHack(md->device.vc, &M8_STEREO_CUBIC); +*/ + VC_RegisterMixerHack(md->device.vc, &M16_MONO_FIR); + VC_RegisterMixerHack(md->device.vc, &M16_STEREO_FIR); + VC_RegisterMixerHack(md->device.vc, &M8_MONO_FIR); + VC_RegisterMixerHack(md->device.vc, &M8_STEREO_FIR); + } + + // LOADING THE SONG + // ---------------- + // Check through the list of active info boxes for a matching filename. If found, + // then we use the already-loaded module information instead! + + { + HWND hwnd; + + if ((mf=FindInfoBox(params.file, &hwnd)) != NULL) + { + MMSTREAM *smpfp; + + // prepare for reloading + info_killseeker(hwnd); + + // reload samples + smpfp = _mm_fopen_rf(params.file); + Unimod_LoadSamples(mf, md, smpfp); + _mm_fclose(smpfp); + } + // not already loaded + else + { + MMSTREAM *fp; + fp = _mm_fopen_rf(params.file); + if (!fp) + { + Mikmod_Exit(md); + CleanupTemp(); + return -1; + } +//MMEXPORT UNIMOD *Unimod_LoadFP(MDRIVER *md, MMSTREAM *modfp, MMSTREAM *smpfp, int mode); +//MMEXPORT UNIMOD *Unimod_Load(MDRIVER *md, const CHAR *filename); + + mf=Unimod_Load_FP(md, params.file,fp); + _mm_fclose(fp); + if (mf==NULL) + { + Mikmod_Exit(md); + CleanupTemp(); + return -1; + } + } + } + + // file name is stored in module now + if (!saveName[0]) + params.file = mf->filename; + + // init player + if (!InitPlayer(mf, &mp, ¶ms, FALSE)) + { + CleanupTemp(); + return -1; + } + + Player_Start(mp); + + // set start time + seek_needed = -1; + decode_pos = 0; + if (params.start && params.startUnit==SU_TIME) + setoutputtime(params.start*1000); + + // init output & info + mikmod.outMod->SetVolume(-666); + mikmod.SetInfo(MulDiv(mf->filesize, 8, mf->songlen), config_srate/1000, GetNumChannels(), 1); + + // init decoding thread + { + DWORD threadid; + + killDecodeThread = 0; + paused = 0; + thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)decodeThread, NULL, 0, &threadid); + set_priority(); + } + + return 0; +} + +// ===================================================================================== +static void __cdecl stop(void) +// ===================================================================================== +{ + if (thread_handle != INVALID_HANDLE_VALUE) + { + killDecodeThread = 1; + if (WaitForSingleObject(thread_handle, 2000) == WAIT_TIMEOUT) + { + MessageBox(mikmod.hMainWindow, + WASABI_API_LNGSTRING(IDS_ERROR_KILLING_DECODING_THREAD), + ERROR_TITLE, MB_ICONWARNING); + TerminateThread(thread_handle, 0); + } + + CloseHandle(thread_handle); + thread_handle = INVALID_HANDLE_VALUE; + CleanupTemp(); + } + + Player_Free(mp); + mp = NULL; + + // We need to see if mf is in use. If so, then we can't unload it. + // Bute we *do* have to unload its samples, because those are not needed. + + if (FindInfoBoxPtr(mf)) + Unimod_UnloadSamples(mf); + else Unimod_Free(mf); + + mf = NULL; + + Mikmod_Exit(md); md = NULL; + mikmod.SAVSADeInit(); +} + +// ===================================================================================== +// pausing stuff +// ===================================================================================== + +static void __cdecl pause(void) { paused=1; mikmod.outMod->Pause(1); } +static void __cdecl unpause(void) { paused=0; mikmod.outMod->Pause(0); } +static int __cdecl ispaused(void) { return paused; } + +// ===================================================================================== +// seeking/timing related stuff +// ===================================================================================== + +static int __cdecl getlength(void) +{ + if (mp) + { + if (!(config_playflag & CPLAYFLG_SEEKBYORDERS)) + return mp->songlen; + else return mf->numpos * 1000; + } + else return 0; +} + +static int __cdecl getoutputtime(void) +{ + if (!(config_playflag & CPLAYFLG_SEEKBYORDERS)) + return decode_pos/64 + (mikmod.outMod->GetOutputTime() - mikmod.outMod->GetWrittenTime()); + else return mp ? mp->state.sngpos * 1000 : 0; +} + +static void __cdecl setoutputtime(int time_in_ms) +{ + seek_needed = time_in_ms; +} + +// ===================================================================================== +static int __cdecl infobox(const char *fileName, HWND hwnd) +// ===================================================================================== +{ + PlayParams params; + + // parse params + if (!GetPlayParams(fileName, FALSE, ¶ms)) + return 1; + + // First we check our array of loaded dialog boxes. If there are any filename matches, + // then we just bring that window to the foreground! + + if (FindInfoBox(params.file, &hwnd) != NULL) + { + SetForegroundWindow(hwnd); + return 0; + } + + infoDlg(hwnd, GetModuleInfo(¶ms), TRUE, TRUE); + + return 0; +} + +/*extern "C" __declspec(dllexport) int winampGetExtendedFileInfo(const char *fn, const char *data, char *dest, int destlen) +{ + UNIMOD *m=0; + PlayParams params; + const char *ret=0; + + + if (!_stricmp(data,"TYPE")) + { + dest[0] = '0'; + dest[1] = 0x00; + return 1; + } + if (!_stricmp(data,"FAMILY")) + { + LPCTSTR e; + e = PathFindExtension(fn); + if (L'.' != *e) return 0; + e++; + return GetTypeInfo(e, dest, destlen); + } + + if (!GetPlayParams(fn, FALSE, ¶ms)) + return 0; + + m=GetModuleInfo(¶ms); + if (!m) + return 0; + + if (!_stricmp(data,"TITLE")) + { + if (!params.titleLength || params.flags&PPF_ADD_TITLE) + ret = m->songname; + else + ret=params.title; + } + else if (!_stricmp(data,"PART")) + { + if (params.titleLength && params.flags&PPF_ADD_TITLE) + ret=params.title; + } + else if (!_stricmp(data,"ARTIST") ) + ret=m->composer; + else if (!_stricmp(data,"COMPOSER")) + ret=m->composer; + else if (!_stricmp(data,"COMMENT")) + ret=m->comment; + else if (!_stricmp(data,"FORMAT") || !_stricmp(data,"MODTYPE")) + ret=m->modtype; + else if (!_stricmp(data,"LENGTH")) + { + _itoa(m->songlen, dest, 10); + if (m!=mf) // make sure it's not the currently playing file + Unimod_Free(m); // in theory this is a race condition + return 1; + } + else + { + if (m!=mf) // make sure it's not the currently playing file + Unimod_Free(m); // in theory this is a race condition + return 0; + } + + if (ret) + lstrcpyn(dest, ret, destlen); + else + dest[0]=0; + + if (m!=mf) // make sure it's not the currently playing file + Unimod_Free(m); // in theory this is a race condition + return 1; +}*/ + +extern "C" __declspec(dllexport) int winampGetExtendedFileInfoW(const wchar_t *fn, const char *data, wchar_t *dest, int destlen) +{ + UNIMOD *m=0; + PlayParams params; + const char *ret=0; + + if (!_stricmp(data,"TYPE")) + { + dest[0] = L'0'; + dest[1] = 0x00; + return 1; + } + if (!_stricmp(data,"FAMILY")) + { + LPCWSTR e; + e = PathFindExtensionW(fn); + if (L'.' != *e) return 0; + e++; + return GetTypeInfo(e, dest, destlen); + } + + if (!GetPlayParams(AutoCharFn(fn), FALSE, ¶ms)) + return 0; + + m=GetModuleInfo(¶ms); + if (!m) + return 0; + + if (!_stricmp(data,"TITLE")) + { + if (!params.titleLength || params.flags&PPF_ADD_TITLE) + ret = m->songname; + else + ret=params.title; + } + else if (!_stricmp(data,"PART")) + { + if (params.titleLength && params.flags&PPF_ADD_TITLE) + ret=params.title; + } + else if (!_stricmp(data,"ARTIST") ) + ret=m->composer; + else if (!_stricmp(data,"COMPOSER")) + ret=m->composer; + else if (!_stricmp(data,"COMMENT")) + ret=m->comment; + else if (!_stricmp(data,"FORMAT") || !_stricmp(data,"MODTYPE")) + ret=m->modtype; + else if (!_stricmp(data,"LENGTH")) + { + _itow(m->songlen, dest, 10); + if (m!=mf) // make sure it's not the currently playing file + Unimod_Free(m); // in theory this is a race condition + return 1; + } + else + { + if (m!=mf) // make sure it's not the currently playing file + Unimod_Free(m); // in theory this is a race condition + return 0; + } + + if (ret) + lstrcpynW(dest, AutoWide(ret), destlen); + else + dest[0]=0; + + if (m!=mf) // make sure it's not the currently playing file + Unimod_Free(m); // in theory this is a race condition + return 1; +} + +// ===================================================================================== +static void __cdecl getfileinfo(const char *fileName, char *title, int *length_in_ms) +// ===================================================================================== +{ + PlayParams params; + UNIMOD *m; + BOOL unload = FALSE; + + // empty string stands for the current file + if (fileName!=NULL && *fileName) + { + if (!GetPlayParams(fileName, FALSE, ¶ms)) + { + lstrcpyn(title, fileName, GETFILEINFO_TITLE_LENGTH); + if (length_in_ms) + *length_in_ms = -1; + return; + } + } + else + params = currParams; + + // module loaded + if ((m=FindInfoBox(params.file, NULL))!=NULL || (unload=1, m=GetModuleInfo(¶ms))!=NULL) + { + if (title) + { + if (!params.titleLength || params.flags&PPF_ADD_TITLE) + lstrcpyn(title, m->songname, GETFILEINFO_TITLE_LENGTH); + else + lstrcpyn(title, params.title, GETFILEINFO_TITLE_LENGTH); + } + // set playing time + if (length_in_ms) + *length_in_ms = m->songlen; + + // clean up + if (unload && m!=mf) + Unimod_Free(m); + } + // invalid module or smth else + else + { + lstrcpyn(title, GetFileName(params.file), GETFILEINFO_TITLE_LENGTH); + if (length_in_ms) + *length_in_ms = -1; + } +} + +// ===================================================================================== +// misc stuff +// ===================================================================================== + +static void __cdecl setvolume(int volume) { mikmod.outMod->SetVolume(volume); } +static void __cdecl setpan(int pan) { mikmod.outMod->SetPan(pan); } +static void __cdecl eq_set(int on, char data[10], int preamp) {} + +static CHAR capnstupid[4096]; + +// ===================================================================================== +In_Module mikmod = +// ===================================================================================== +{ + IN_VER_RET, + "nullsoft(in_mod.dll)", // need to set this to some form of valid buffer otherwise in_bass crashes (why it's looking at this i don't know!!) + 0, // hMainWindow + 0, // hDllInstance + capnstupid, + 1, // is_seekable + 1, // uses_output_plug + config, + about, + init, + quit, + getfileinfo, + infobox, + isourfile, + play, + pause, + unpause, + ispaused, + stop, + + getlength, + getoutputtime, + setoutputtime, + + setvolume, + setpan, + + 0,0,0,0,0,0,0,0,0, // vis stuff + + 0,0, // dsp shit + + eq_set, + + NULL, // setinfo + NULL // outmod +}; + +// ===================================================================================== +extern "C" __declspec(dllexport) In_Module *__cdecl winampGetInModule2() +// input module getter. the only thing exported from here. +// ===================================================================================== +{ + return &mikmod; +} + + +// ===================================================================================== +static DWORD WINAPI decodeThread(void *unused) +// ===================================================================================== +{ + int has_flushed = 0; + + while (!killDecodeThread) + { + if (seek_needed >= 0) + { + int ms = seek_needed; + seek_needed = -1; + + if (!(config_playflag & CPLAYFLG_SEEKBYORDERS)) + { + Player_SetPosTime(mp, ms); + decode_pos = ms * 64; + } + else Player_SetPosition(mp, ms/1000, TRUE); + + mikmod.outMod->Flush(ms); + if (paused) mikmod.outMod->Pause(1); + } + + if (!Player_Active(mp)) + { + // check for infinite looping + // infinite looping is done manually (only here). we check if + // it was requested and if the loop is required (song ended + // with loop or unconditional looping is on) + if (mp->loopcount!=-1 || !(mp->flags&PF_LOOP || mp->state.looping<0)) + { + if (!has_flushed) + { + has_flushed = 1; + mikmod.outMod->Write(NULL, 0); // write all samples into buffer queue + } + if (!mikmod.outMod->IsPlaying()) + { + PostMessage(mikmod.hMainWindow, WM_WA_MPEG_EOF, 0, 0); + return 0; + } + else mikmod.outMod->CanWrite(); // make sure plug-in can do any extra processing needed + Sleep(20); + } + else + { + Player_Restart(mp, TRUE); + decode_pos = mp->state.curtime; + } + } + else + { + Mikmod_Update(md); + Sleep(8); + } + } + + return 0; +} + + +// ===================================================================================== +void set_priority(void) // also used in config.c +// ===================================================================================== +{ + if (thread_handle != INVALID_HANDLE_VALUE) + SetThreadPriority(thread_handle, GetThreadPriorityConfig()); +} + + +BOOL WINAPI DllMain(HANDLE h, DWORD r, void *z) +{ + if (r == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls((HMODULE)h); + } + return 1; +}
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/src/api.h b/Src/Plugins/Input/in_mod/mikamp/src/api.h new file mode 100644 index 00000000..b514a409 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/api.h @@ -0,0 +1,11 @@ +#ifndef NULLSOFT_API_H +#define NULLSOFT_API_H + +#include <api/service/waServiceFactory.h> + +#include "../Agave/Language/api_language.h" + +#include <api/application/api_application.h> +#define WASABI_API_APP applicationApi + +#endif
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/src/drv_amp.c b/Src/Plugins/Input/in_mod/mikamp/src/drv_amp.c new file mode 100644 index 00000000..b84c818b --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/drv_amp.c @@ -0,0 +1,254 @@ +#include <windows.h> +#include <malloc.h> +#include "mikmod.h" +#include "virtch.h" +#include "main.h" +#include <io.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define BUFSIZE 28 + +typedef struct AMP_LOCALINFO +{ + uint mode; + uint mixspeed; + uint channels; + + SBYTE RAW_DMABUF[(BUFSIZE*1024*2) + 64]; // added 64 for mmx mixer (it's not exact :) + + int block_len, bits,ismono, bytes_per_sec; + +} AMP_LOCALINFO; + +extern int decode_pos; // from main.c + +// ===================================================================================== + static BOOL RAW_IsThere(void) +// ===================================================================================== +{ + return 1; +} + + +// ===================================================================================== + static BOOL RAW_Init(MDRIVER *md, uint latency, void *optstr) +// ===================================================================================== +{ + AMP_LOCALINFO *hwdata; + + hwdata = (AMP_LOCALINFO *)MikMod_calloc(md->allochandle, 1, sizeof(AMP_LOCALINFO)); + + md->device.vc = VC_Init(); + if(!md->device.vc) + { mikmod.outMod->Close(); + return 1; + } + + hwdata->mode = DMODE_16BITS | DMODE_INTERP | DMODE_NOCLICK; + hwdata->mixspeed = 48000; + hwdata->channels = 2; + + md->device.local = hwdata; + + return 0; +} + + +// ===================================================================================== + static void RAW_Exit(MDRIVER *md) +// ===================================================================================== +{ + VC_Exit(md->device.vc); + mikmod.outMod->Close(); +} + + +// ===================================================================================== + static void RAW_Update(MDRIVER *md) +// ===================================================================================== +{ + AMP_LOCALINFO *hwdata = md->device.local; + int l; + char * vis; + int visbits; + + if ((l=mikmod.outMod->CanWrite()) > hwdata->block_len*16) l = hwdata->block_len*16; + if (mikmod.dsp_isactive()) l>>=1; + + if (l > hwdata->block_len) + { int o=0; + + l -= l % hwdata->block_len; + VC_WriteBytes(md, hwdata->RAW_DMABUF, l); + + while (o < l) + { + int a = min(hwdata->block_len,l-o); + + if (mikmod.dsp_isactive()) + { int t; + int k = (hwdata->bits>>3)*(hwdata->ismono?1:2); + + t = mikmod.dsp_dosamples((short *)(hwdata->RAW_DMABUF+o),a / k,hwdata->bits,(hwdata->ismono?1:2),hwdata->mixspeed) * k; + mikmod.outMod->Write(hwdata->RAW_DMABUF+o,t); + } else + mikmod.outMod->Write(hwdata->RAW_DMABUF+o,a); + + vis=hwdata->RAW_DMABUF+o; + visbits=hwdata->bits; + + if (visbits > 16) + { + uint n = 576 * 2>>hwdata->ismono; + const uint d = visbits >> 3; + WORD *const visbuf = (WORD*)alloca(n * sizeof(WORD)); + char *ptr = vis + d - 2; + WORD *vp = visbuf; + + for (;n;n--) + { + *vp++ = *(WORD*)ptr; + ptr += d; + } + vis=(char*)visbuf; + visbits=16; + } + + mikmod.SAAddPCMData(vis,hwdata->ismono ? 1 : 2, visbits, decode_pos/64); + mikmod.VSAAddPCMData(vis,hwdata->ismono ? 1 : 2, visbits, decode_pos/64); + + decode_pos += (a*1000*64) / hwdata->bytes_per_sec; + o+=a; + } + } else Sleep(6); +} + + +// ===================================================================================== + static BOOL RAW_SetMode(MDRIVER *md, uint mixspeed, uint mode, uint channels, uint cpumode) +// ===================================================================================== +{ + AMP_LOCALINFO *hwdata = md->device.local; + + // Check capabilities... + // [...] + + // Set the new mode of play + + if (mixspeed) hwdata->mixspeed = mixspeed; + + if(!(mode & DMODE_DEFAULT)) hwdata->mode = mode; + + switch(channels) + { case MD_MONO: + hwdata->channels = 1; + break; + + default: + hwdata->channels = 2; + channels = MD_STEREO; + break; + } + + VC_SetMode(md->device.vc, hwdata->mixspeed, hwdata->mode, channels, cpumode); + + { + int bits = (hwdata->mode & DMODE_16BITS) ? 16: ((hwdata->mode & DMODE_24BITS) ? 24 : 8); + int z; + int a = 576*2*(bits>>3); + + hwdata->bits = bits; + hwdata->ismono = (hwdata->channels == 1) ? 1 : 0; + + if (hwdata->ismono) a/=2; + + hwdata->block_len = a; + + hwdata->bytes_per_sec = hwdata->mixspeed * (hwdata->bits>>3) * (hwdata->ismono ? 1 : 2); + + z = mikmod.outMod->Open(hwdata->mixspeed,hwdata->channels,bits,-1,-1); + if (z < 0) return 1; + + mikmod.SAVSAInit(z,hwdata->mixspeed); + mikmod.VSASetInfo(hwdata->mixspeed,hwdata->channels); + + mikmod.outMod->SetVolume(-666); + } + + return 0; +} + + +// ===================================================================================== + static BOOL AMP_SetSoftVoices(MDRIVER *md, uint voices) +// ===================================================================================== +{ + return VC_SetSoftVoices(md->device.vc, voices); +} + + +// ===================================================================================== + static void AMP_GetMode(MDRIVER *md, uint *mixspeed, uint *mode, uint *channels, uint *cpumode) +// ===================================================================================== +{ + VC_GetMode(md->device.vc, mixspeed, mode, channels, cpumode); +} + + +// ===================================================================================== + MD_DEVICE drv_amp = +// ===================================================================================== +{ + "win32au", + BLAH("Nullsoft win32 output driver v0.700"), + 0, VC_MAXVOICES, + + NULL, + NULL, + NULL, + + // Sample Loading + VC_SampleAlloc, + VC_SampleGetPtr, + VC_SampleLoad, + VC_SampleUnload, + VC_SampleSpace, + VC_SampleLength, + + // Detection and Initialization + RAW_IsThere, + RAW_Init, + RAW_Exit, + RAW_Update, + VC_Preempt, + + NULL, + AMP_SetSoftVoices, + + RAW_SetMode, + AMP_GetMode, + + VC_SetVolume, + VC_GetVolume, + + // Voice control and Voie information + VC_GetActiveVoices, + + VC_VoiceSetVolume, + VC_VoiceGetVolume, + VC_VoiceSetFrequency, + VC_VoiceGetFrequency, + VC_VoiceSetPosition, + VC_VoiceGetPosition, + VC_VoiceSetSurround, + VC_VoiceSetResonance, + + VC_VoicePlay, + VC_VoiceResume, + VC_VoiceStop, + VC_VoiceStopped, + VC_VoiceReleaseSustain, + VC_VoiceRealVolume, + +};
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/src/drv_buffer.cpp b/Src/Plugins/Input/in_mod/mikamp/src/drv_buffer.cpp new file mode 100644 index 00000000..ed75d798 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/drv_buffer.cpp @@ -0,0 +1,176 @@ +#include <windows.h> +#include <malloc.h> +#include "mikmod.h" +#include "virtch.h" +#include "main.h" +#include <io.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "drv_buffer.h" + +#define BUFSIZE 28 + + +// ===================================================================================== +static BOOL Decode_IsThere(void) +// ===================================================================================== +{ + return 1; +} + + +// ===================================================================================== +static BOOL Decode_Init(MDRIVER *md, uint latency, void *optstr) +// ===================================================================================== +{ + DecodeInfo *hwdata; + + hwdata = (DecodeInfo *)MikMod_calloc(md->allochandle, 1, sizeof(DecodeInfo)); + + md->device.vc = VC_Init(); + if(!md->device.vc) + { + hwdata->error = 1; + return 1; + } + + hwdata->mode = DMODE_16BITS | DMODE_INTERP | DMODE_NOCLICK; + hwdata->mixspeed = 48000; + hwdata->channels = 2; + + md->device.local = hwdata; + + return 0; +} + + +// ===================================================================================== +static void Decode_Exit(MDRIVER *md) +// ===================================================================================== +{ + DecodeInfo *hwdata = (DecodeInfo *)md->device.local; + VC_Exit(md->device.vc); +} + + +// ===================================================================================== +static void Decode_Update(MDRIVER *md) +// ===================================================================================== +{ + DecodeInfo *hwdata = (DecodeInfo *)md->device.local; + + hwdata->bytesWritten = VC_WriteBytes(md, (SBYTE *)hwdata->buffer, hwdata->buffersize); +} + + +// ===================================================================================== +static BOOL Decode_SetMode(MDRIVER *md, uint mixspeed, uint mode, uint channels, uint cpumode) +// ===================================================================================== +{ + DecodeInfo *hwdata = (DecodeInfo *)md->device.local; + + // Check capabilities... + // [...] + + // Set the new mode of play + + if (mixspeed) hwdata->mixspeed = mixspeed; + + if(!(mode & DMODE_DEFAULT)) hwdata->mode = mode; + + switch(channels) + { + case MD_MONO: + hwdata->channels = 1; + break; + + default: + hwdata->channels = 2; + channels = MD_STEREO; + break; + } + + VC_SetMode(md->device.vc, hwdata->mixspeed, hwdata->mode, channels, cpumode); + + int bits = (hwdata->mode & DMODE_16BITS) ? 16: ((hwdata->mode & DMODE_24BITS) ? 24 : 8); + + hwdata->bits = bits; + hwdata->frame_size = MulDiv(hwdata->channels, bits, 8); + + + return 0; +} + + +// ===================================================================================== +static BOOL Decode_SetSoftVoices(MDRIVER *md, uint voices) +// ===================================================================================== +{ + return VC_SetSoftVoices(md->device.vc, voices); +} + + +// ===================================================================================== +static void Decode_GetMode(MDRIVER *md, uint *mixspeed, uint *mode, uint *channels, uint *cpumode) +// ===================================================================================== +{ + VC_GetMode(md->device.vc, mixspeed, mode, channels, cpumode); +} + + +// ===================================================================================== +extern "C" MD_DEVICE drv_buffer = +// ===================================================================================== +{ + "ExtendedRead", + BLAH("Nullsoft Extended Read decode driver v0.1"), + 0, VC_MAXVOICES, + + NULL, + NULL, + NULL, + + // Sample Loading + VC_SampleAlloc, + VC_SampleGetPtr, + VC_SampleLoad, + VC_SampleUnload, + VC_SampleSpace, + VC_SampleLength, + + // Detection and Initialization + Decode_IsThere, + Decode_Init, + Decode_Exit, + Decode_Update, + VC_Preempt, + + NULL, + Decode_SetSoftVoices, + + Decode_SetMode, + Decode_GetMode, + + VC_SetVolume, + VC_GetVolume, + + // Voice control and Voie information + VC_GetActiveVoices, + + VC_VoiceSetVolume, + VC_VoiceGetVolume, + VC_VoiceSetFrequency, + VC_VoiceGetFrequency, + VC_VoiceSetPosition, + VC_VoiceGetPosition, + VC_VoiceSetSurround, + VC_VoiceSetResonance, + + VC_VoicePlay, + VC_VoiceResume, + VC_VoiceStop, + VC_VoiceStopped, + VC_VoiceReleaseSustain, + VC_VoiceRealVolume, + +};
\ No newline at end of file diff --git a/Src/Plugins/Input/in_mod/mikamp/src/drv_buffer.h b/Src/Plugins/Input/in_mod/mikamp/src/drv_buffer.h new file mode 100644 index 00000000..e96006c9 --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/drv_buffer.h @@ -0,0 +1,18 @@ +#pragma once +#include "mikmod.h" +struct DecodeInfo +{ + uint mode; + uint mixspeed; + uint channels; + + void *buffer; + size_t buffersize; + + int bits; + int frame_size; // cached channels*bits/8 + int error; + size_t bytesWritten; +}; + +//extern MD_DEVICE drv_buffer; diff --git a/Src/Plugins/Input/in_mod/mikamp/src/rf_wrapper.c b/Src/Plugins/Input/in_mod/mikamp/src/rf_wrapper.c new file mode 100644 index 00000000..3431affd --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/src/rf_wrapper.c @@ -0,0 +1,241 @@ +#include <windows.h> +#include <mmio.h> +#include <shlwapi.h> +#include "../../winamp/wa_ipc.h" +#include "../../winamp/in2.h" +extern In_Module mikmod; +//big mess here + +typedef struct // quick _thiscall hack +{ + char *(_fastcall *GetDescription)(void*,int); + int (_fastcall *Open)(void*,int,char *url, int *killswitch); + int (_fastcall *Read)(void*,int,void *buffer, int length, int *killswitch); + int (_fastcall *GetLength)(void*); + int (_fastcall *CanSeek)(void*); + int (_fastcall *Seek)(void*,int,int position, int *killswitch); + char *(_fastcall *GetHeader)(void*,int,char *name); + void (_fastcall *Release)(void*,int,int); // rough ~WReader() hack +} RF_vtbl; + +#define RF_Open(x,a,b) (*x)->Open(x,0,a,b) +#define RF_Read(x,a,b,c) (*x)->Read(x,0,a,b,c) +#define RF_GetLength(x) (*x)->GetLength(x) +#define RF_Seek(x,a,b) (*x)->Seek(x,0,a,b) +#define RF_Release(x) (*x)->Release(x,0,0) + +#define READ_VER 0x100 + +typedef struct +{ + int version; + char *description; + + RF_vtbl ** (_cdecl *create)(); + + int (_cdecl *ismine)(char *url); + +} reader_source; + +typedef int (_cdecl *RF_entry)(HINSTANCE hIns,reader_source** s); + +static int initialized,got_dll; +static HINSTANCE hRF; + +typedef struct +{ + RF_vtbl ** r; + UINT size,pos; +} RFstruct; + +static RF_vtbl** (_cdecl *rf_create)(); + +static int rf_init() +{ + wchar_t fn[MAX_PATH] = {0}; + RF_entry rf_entry; + reader_source * source; + + if (initialized) return got_dll; + initialized=1; + + PathCombineW(fn, (wchar_t*)SendMessage(mikmod.hMainWindow, WM_WA_IPC, 0, IPC_GETSHAREDDLLDIRECTORYW), L"read_file.dll"); + + hRF=LoadLibraryW(fn); + if (!hRF) return 0; + + rf_entry = (RF_entry)GetProcAddress(hRF,"readerSource"); + if (!rf_entry) + { + FreeLibrary(hRF); + return 0; + } + + rf_entry(hRF,&source); + + if (source->version!=READ_VER) + { + FreeLibrary(hRF); + return 0; + } + + rf_create=source->create; + + got_dll=1; + return 1; +} + +static void rf_quit() +{ + if (got_dll) + { + FreeLibrary(hRF); + got_dll=0; + } + initialized=0; +} + +static void * _cdecl rfopen(const char * fn) +{ + int ks; + RF_vtbl ** r; + RFstruct * rs; + + + if (!got_dll) return 0; + + r=rf_create(); + if (!r) return 0; + + ks=0; + + if (RF_Open(r,(char*)fn,&ks)) + { + RF_Release(r); + return 0; + } + + rs=malloc(sizeof(RFstruct)); + if (!rs) + { + RF_Release(r); + return 0; + } + rs->r=r; + rs->pos=0; + rs->size=RF_GetLength(r); + + return rs; +} + +static size_t _cdecl rfread( void *buffer, size_t size, size_t count, void *stream ) +{ + RFstruct * rs; + int ks,rv; + UINT siz; + rs=stream; + ks=0; + siz=size*count; + if (siz>rs->size-rs->pos) siz=rs->size-rs->pos;//just to be sure + rv=RF_Read(rs->r,buffer,siz,&ks); + if (rv>0) rs->pos+=rv; + return rv; + +} + +static size_t _cdecl rfwrite( const void *buffer, size_t size, size_t count, void *stream ) {return -1;} + +static int _cdecl rfgetc( void *stream ) +{ + RFstruct * rs; + int rv,ks; + rv=0; + ks=0; + rs=stream; + + if (RF_Read(rs->r,&rv,1,&ks)>0) rs->pos++; + else rv=EOF; + return rv; +} + +static int _cdecl rfputc( int c, void *stream ) +{ + // not implemented + return -1; +} + +static int _cdecl rfseek( void *stream, long offset, int origin ) +{ + RFstruct * rs; + int ks; + UINT new_pos; + + ks=0; + rs=stream; + + switch(origin) + { + case SEEK_CUR: + new_pos=rs->pos+offset; + break; + case SEEK_END: + new_pos=rs->size+offset; + break; + case SEEK_SET: + new_pos=offset; + break; + default: + return -1; + } + if (new_pos>rs->size) new_pos=rs->size; + if (RF_Seek(rs->r,new_pos,&ks)) + { + return -1; + } + rs->pos=new_pos; + return 0; +} + +static long _cdecl rftell(void * stream) +{ + RFstruct * rs=stream; + return rs->pos; +} + +static int _cdecl rfeof(void * stream) +{ + RFstruct * rs=stream; + return rs->pos==rs->size; +} + +static int _cdecl rfclose(void * stream) +{ + RFstruct * rs=stream; + RF_Release(rs->r); + free(rs); + return 0; +} + +static const MMSTREAM_CALLBACK callback_rf = +{ + rfread, + rfwrite, + rfgetc, + rfputc, + rfseek, + rftell, + rfeof, + rfclose +}; + + +MMSTREAM *_mm_fopen_rf(const CHAR *fname) +{ + void * handle; + if (!rf_init()) return 0; + handle = rfopen(fname); + if (!handle) return _mm_fopen(fname,"rb"); + return _mmstream_createfp_callback(handle,0,&callback_rf); +} + + diff --git a/Src/Plugins/Input/in_mod/mikamp/version.rc2 b/Src/Plugins/Input/in_mod/mikamp/version.rc2 new file mode 100644 index 00000000..62a67dcc --- /dev/null +++ b/Src/Plugins/Input/in_mod/mikamp/version.rc2 @@ -0,0 +1,39 @@ + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// +#include "../../../../Winamp/buildType.h" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,94,0,0 + PRODUCTVERSION WINAMP_PRODUCTVER + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Winamp SA" + VALUE "FileDescription", "Winamp Input Plug-in" + VALUE "FileVersion", "2,94,0,0" + VALUE "InternalName", "Nullsoft Module Decoder" + VALUE "LegalCopyright", "Copyright © 1998-2014 Winamp SA" + VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA" + VALUE "OriginalFilename", "in_mod.dll" + VALUE "ProductName", "Winamp" + VALUE "ProductVersion", STR_WINAMP_PRODUCTVER + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END |